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 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); }