154 lines
5.6 KiB
C#
154 lines
5.6 KiB
C#
using Fake.DependencyInjection;
|
||
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,
|
||
IOrderSideEffectEventPublisher sideEffectEventPublisher,
|
||
ILogger<AutoTriggerRuntimeService> logger) : IScopedDependency
|
||
{
|
||
private const string InterceptOperation = "拦截";
|
||
|
||
/// <summary>
|
||
/// 投递自动触发事件(须在事务 UoW 内调用,写入 Outbox)。
|
||
/// </summary>
|
||
public Task EnqueueFireAsync(int orderId, AutoTriggerTiming timing, int operatorUserId) =>
|
||
orderId <= 0
|
||
? Task.CompletedTask
|
||
: sideEffectEventPublisher.PublishAutoTriggerFireAsync(orderId, timing, 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);
|
||
}
|
||
}
|
||
}
|