admin/src/Oms.Application/Services/Orders/Issues/AutoTriggerConditionMatcher.cs
zzh 43563b727f feat: 自动触发公式引擎与查价运输方式分组接口
实现中文公式预报前拦截、规则测试 API 及按销售产品分组返回查价运输方式选项。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-09 18:36:17 +08:00

186 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text.Json;
using Oms.Domain.ChannelsAggregate.Consts;
using Oms.Domain.OrdersAggregate.Entities;
namespace Oms.Application.Services.Orders.Issues;
public static class AutoTriggerConditionMatcher
{
public static bool Matches(Order order, string? triggerCondition) =>
Matches(OrderRuleEvaluationContext.FromOrderOnly(order), triggerCondition);
public static bool Matches(OrderRuleEvaluationContext context, string? triggerCondition)
{
var text = triggerCondition?.Trim();
if (string.IsNullOrWhiteSpace(text))
{
return true;
}
var parsed = AutoTriggerConditionParser.Parse(text);
if (ShouldUseFormulaEvaluator(parsed, text))
{
if (string.IsNullOrWhiteSpace(parsed.Expression))
{
return true;
}
if (ChineseFormulaEvaluator.TryEvaluate(parsed.Expression, context, out var result))
{
return result;
}
}
if (parsed.IsLegacyJsonMatcher && text.StartsWith('{') && text.EndsWith('}'))
{
return MatchesLegacyJson(context.Order, text);
}
if (context.Order != null)
{
var lowered = text.ToLowerInvariant();
if (IssueTypeCodes.All.Contains(lowered))
{
return true;
}
return ContainsKeyword(context.Order, text);
}
return false;
}
public static string ResolveIssueType(string? triggerCondition)
{
var text = triggerCondition?.Trim();
if (string.IsNullOrWhiteSpace(text))
{
return IssueTypeCodes.Other;
}
if (text.StartsWith('{') && text.EndsWith('}'))
{
try
{
using var doc = JsonDocument.Parse(text);
if (doc.RootElement.TryGetProperty("issueType", out var issueTypeElement))
{
var code = issueTypeElement.GetString()?.Trim().ToLowerInvariant();
if (!string.IsNullOrWhiteSpace(code) && IssueTypeCodes.All.Contains(code))
{
return code;
}
}
}
catch (JsonException)
{
// fall through
}
}
var lowered = text.ToLowerInvariant();
if (IssueTypeCodes.All.Contains(lowered))
{
return lowered;
}
return IssueTypeCodes.Other;
}
public static List<int> ParseNotifierUserIds(string? notifier)
{
if (string.IsNullOrWhiteSpace(notifier))
{
return [];
}
return notifier
.Split([',', ';', ' ', ','], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(x => int.TryParse(x, out var id) ? id : 0)
.Where(x => x > 0)
.Distinct()
.ToList();
}
private static bool ShouldUseFormulaEvaluator(ParsedTriggerCondition parsed, string rawText) =>
parsed.IsFormulaVersion
|| (!string.IsNullOrWhiteSpace(parsed.Expression) && AutoTriggerConditionParser.LooksLikeFormula(parsed.Expression))
|| (!parsed.IsLegacyJsonMatcher && AutoTriggerConditionParser.LooksLikeFormula(rawText));
private static bool MatchesLegacyJson(Order? order, string json)
{
if (order == null)
{
return false;
}
try
{
using var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
if (root.TryGetProperty("orderStatus", out var statusElement))
{
var expected = statusElement.GetString()?.Trim();
if (!string.IsNullOrWhiteSpace(expected)
&& !string.Equals(order.OrderStatus, expected, StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
if (root.TryGetProperty("productCode", out var productElement))
{
var expected = productElement.GetString()?.Trim();
if (!string.IsNullOrWhiteSpace(expected)
&& !string.Equals(order.ProductCode?.Trim(), expected, StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
if (root.TryGetProperty("channelCode", out var channelElement))
{
var expected = channelElement.GetString()?.Trim();
if (!string.IsNullOrWhiteSpace(expected)
&& !string.Equals(order.ChannelCode?.Trim(), expected, StringComparison.OrdinalIgnoreCase))
{
return false;
}
}
if (root.TryGetProperty("keyword", out var keywordElement))
{
var keyword = keywordElement.GetString()?.Trim();
if (!string.IsNullOrWhiteSpace(keyword) && !ContainsKeyword(order, keyword))
{
return false;
}
}
return true;
}
catch (JsonException)
{
return ContainsKeyword(order, json);
}
}
private static bool ContainsKeyword(Order order, string keyword)
{
if (string.IsNullOrWhiteSpace(keyword))
{
return true;
}
return Contains(order.ServiceNo, keyword)
|| Contains(order.ClientNo, keyword)
|| Contains(order.TrackNo, keyword)
|| Contains(order.ProductCode, keyword)
|| Contains(order.ChannelCode, keyword);
}
private static bool Contains(string? source, string keyword) =>
!string.IsNullOrWhiteSpace(source)
&& source.Contains(keyword, StringComparison.OrdinalIgnoreCase);
}