using Fake.DependencyInjection; using Fake.EventBus.Distributed; using Microsoft.Extensions.Logging; using Oms.Application.Messaging.OrderSideEffects; using Oms.Domain.ChannelsAggregate.Consts; using Oms.Domain.ChannelsAggregate.Entities; using Oms.Domain.ChannelsAggregate.Repositories; using Oms.Domain.OrdersAggregate.Entities; using Oms.Domain.OrdersAggregate.Repositories; using Oms.Domain.Shared.Enums; namespace Oms.Application.Services.Orders.Issues; public class AutoTriggerRuntimeService( IAutoTriggerRepository autoTriggerRepository, IOrderRepository orderRepository, OrderAutoTriggerService orderAutoTriggerService, OrderExceptionWorkflowService exceptionWorkflowService, OrderIssueNotificationService issueNotificationService, IDistributedEventBus eventBus, ILogger logger) : IScopedDependency { private const string InterceptOperation = "拦截"; /// /// 投递自动触发事件(须在事务 UoW 内调用,写入 Outbox)。 /// public Task EnqueueFireAsync(int orderId, AutoTriggerTiming timing, int operatorUserId) => orderId <= 0 ? Task.CompletedTask : eventBus.PublishAsync(new OrderAutoTriggerFireIntegrationEvent { OrderId = orderId, Timing = timing.ToString(), OperatorUserId = operatorUserId }); public async Task FireAsync(Order order, AutoTriggerTiming timing, int operatorUserId) { if (order.Id <= 0) { return; } var context = await orderAutoTriggerService.BuildPostCommitContextAsync(order); var triggers = await autoTriggerRepository.GetListAsync(x => x.Status == EnableStatus.Enabled); var orderedTriggers = triggers .Where(x => AutoTriggerTimingCodes.Matches(x.TriggerTiming, timing)) .Select(x => (Trigger: x, Priority: AutoTriggerRuleResolver.GetPriority(x))) .OrderBy(x => x.Priority) .ThenBy(x => x.Trigger.Id) .Select(x => x.Trigger) .ToList(); foreach (var trigger in orderedTriggers) { if (timing == AutoTriggerTiming.OrderCreate && string.Equals(trigger.Operation?.Trim(), InterceptOperation, StringComparison.Ordinal)) { continue; } if (!AutoTriggerConditionMatcher.Matches(context, trigger.TriggerCondition)) { continue; } try { await ExecuteTriggerAsync(order, trigger, operatorUserId); } catch (Exception ex) { logger.LogWarning(ex, "自动触发失败 OrderId={OrderId} TriggerId={TriggerId}", order.Id, trigger.Id); } } } public async Task FireByOrderIdAsync(int orderId, AutoTriggerTiming timing, int operatorUserId) { var order = await orderRepository.FirstOrDefaultAsync(x => x.Id == orderId); if (order == null) { return; } await FireAsync(order, timing, operatorUserId); } private async Task ExecuteTriggerAsync( Order order, AutoTrigger trigger, int operatorUserId) { var operation = trigger.Operation?.Trim(); if (string.Equals(operation, InterceptOperation, StringComparison.Ordinal)) { if (order.IsIntercept == 0) { order.IsIntercept = 1; await orderRepository.UpdateAsync(order); } return; } if (string.Equals(operation, "警告", StringComparison.Ordinal)) { var title = string.IsNullOrWhiteSpace(trigger.PromptMessage) ? "订单预警" : trigger.PromptMessage.Trim(); var content = string.IsNullOrWhiteSpace(trigger.TriggerCondition) ? $"运单 {{serviceNo}} 触发自动警告规则" : trigger.TriggerCondition.Trim(); var context = IssuePlaceholderContext.FromOrder(order, null, title); await issueNotificationService.DispatchAsync( order, IssuePlaceholderRenderer.Render(title, context), IssuePlaceholderRenderer.Render(content, context), IssueNotifyMethodCodes.InApp, operatorUserId, null, AutoTriggerConditionMatcher.ParseNotifierUserIds(trigger.Notifier)); return; } if (!string.Equals(operation, "问题件", StringComparison.Ordinal)) { return; } var issueType = AutoTriggerConditionMatcher.ResolveIssueType(trigger.TriggerCondition); var request = await exceptionWorkflowService.BuildRequestFromTemplateAsync( order.OrganizationId, issueType, trigger.PromptMessage, null, $"自动触发#{trigger.Id}"); if (request == null) { logger.LogInformation( "自动触发问题件跳过:未匹配问题模板 OrderId={OrderId} TriggerId={TriggerId}", order.Id, trigger.Id); return; } request.ExtraReceiverUserIds = AutoTriggerConditionMatcher.ParseNotifierUserIds(trigger.Notifier); var reason = await exceptionWorkflowService.TryMarkProblematicAsync(order, request, operatorUserId, true); if (!string.IsNullOrWhiteSpace(reason)) { logger.LogInformation( "自动触发问题件未执行 OrderId={OrderId} TriggerId={TriggerId} Reason={Reason}", order.Id, trigger.Id, reason); } } }