补齐揽收单字段/并发戳与问题件处理人配置,扩展异常工作流与下单同步揽收出参;移除已收货状态并补充相关 SQL 脚本。 Co-authored-by: Cursor <cursoragent@cursor.com>
175 lines
6.0 KiB
C#
175 lines
6.0 KiB
C#
using Fake.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
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,
|
|
IServiceScopeFactory scopeFactory,
|
|
ILogger<AutoTriggerRuntimeService> logger) : IScopedDependency
|
|
{
|
|
private const string InterceptOperation = "拦截";
|
|
|
|
/// <summary>
|
|
/// 后台异步触发,避免拉长入库/出库扫码请求。
|
|
/// </summary>
|
|
public void EnqueueFire(int orderId, AutoTriggerTiming timing, int operatorUserId)
|
|
{
|
|
if (orderId <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_ = Task.Run(async () =>
|
|
{
|
|
try
|
|
{
|
|
using var scope = scopeFactory.CreateScope();
|
|
var runtime = scope.ServiceProvider.GetRequiredService<AutoTriggerRuntimeService>();
|
|
await runtime.FireByOrderIdAsync(orderId, timing, operatorUserId);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogWarning(
|
|
ex,
|
|
"异步自动触发失败 OrderId={OrderId} Timing={Timing}",
|
|
orderId,
|
|
timing);
|
|
}
|
|
});
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|