using System.Text.RegularExpressions; using Oms.Application.Dtos.Orders; using Oms.Domain.ChannelsAggregate.Entities; namespace Oms.Application.Shared; /// /// KPI 分区快照映射与左开右闭邮编匹配。 /// public static class KpiAreaSnapshotMapper { private static readonly Regex PostcodeRangePattern = new( @"^\(\s*([^,)\]]*)\s*,\s*([^,)\]]*)\s*\]$", RegexOptions.Compiled | RegexOptions.CultureInvariant); public static KpiAreaSnapshotRuleDto MapToSnapshotRule(KpiAreaInfo entity) => new() { Id = entity.Id, CountryCode = entity.CountryCode, Province = entity.Province, City = entity.City, PostcodeRange = BuildPostcodeRange(entity.LeftPostcode, entity.RightPostcode) }; public static string? BuildPostcodeRange(string? left, string? right) { if (string.IsNullOrWhiteSpace(left) && string.IsNullOrWhiteSpace(right)) { return null; } return $"({left?.Trim()},{right?.Trim()}]"; } public static string? ResolvePostcodeRange(KpiAreaSnapshotRuleDto rule) { if (!string.IsNullOrWhiteSpace(rule.PostcodeRange)) { return rule.PostcodeRange.Trim(); } return BuildPostcodeRange(rule.LeftPostcode, rule.RightPostcode); } public static bool IsRuleMatched( KpiAreaSnapshotRuleDto rule, string countryCode, string? province, string? city, string? zipCode) { if (!string.IsNullOrWhiteSpace(rule.CountryCode) && !string.Equals(rule.CountryCode, countryCode, StringComparison.OrdinalIgnoreCase)) { return false; } if (!string.IsNullOrWhiteSpace(rule.Province) && !string.Equals(rule.Province, province, StringComparison.OrdinalIgnoreCase)) { return false; } if (!string.IsNullOrWhiteSpace(rule.City) && !string.Equals(rule.City, city, StringComparison.OrdinalIgnoreCase)) { return false; } var postcodeRange = ResolvePostcodeRange(rule); if (string.IsNullOrWhiteSpace(postcodeRange)) { return true; } if (string.IsNullOrWhiteSpace(zipCode)) { return false; } return IsZipInLeftOpenRightClosedRange(zipCode.Trim(), postcodeRange); } public static bool IsZipInLeftOpenRightClosedRange(string zipCode, string postcodeRange) { var match = PostcodeRangePattern.Match(postcodeRange.Trim()); if (!match.Success) { return false; } var left = match.Groups[1].Value.Trim(); var right = match.Groups[2].Value.Trim(); if (long.TryParse(zipCode, out var zip) && long.TryParse(left, out var leftValue) && long.TryParse(right, out var rightValue)) { return zip > leftValue && zip <= rightValue; } return string.Compare(zipCode, left, StringComparison.OrdinalIgnoreCase) > 0 && string.Compare(zipCode, right, StringComparison.OrdinalIgnoreCase) <= 0; } }