using System.Linq.Expressions; using System.Text; using System.Text.Json; using Fake.Application; using Fake.Users; using Microsoft.AspNetCore.Mvc; using MiniExcelLibs; using Newtonsoft.Json; using Oms.Application.DataPerm; using Oms.Application.Dtos.Orders; using Oms.Application.Dtos.Shared; using Oms.Application.Messaging; using Oms.Application.Services.Orders.Templates; using Oms.Application.Shared; using Oms.Domain.OrdersAggregate; using Oms.Domain.ChannelsAggregate.Consts; using Oms.Domain.OrdersAggregate.Consts; using Oms.Domain.OrdersAggregate.Entities; using Oms.Domain.SystemAggregate.Entities; namespace Oms.Application.Services.Orders; public partial class OrderService { private async Task> MapOrderOutputsAsync(IReadOnlyCollection orders) { if (orders.Count == 0) { return []; } var orderIds = orders.Select(x => x.Id).ToArray(); var warehouseIds = orders.Where(x => x.WarehouseId.HasValue).Select(x => x.WarehouseId!.Value).Distinct().ToArray(); var senders = await OrderRepository.GetSendersByOrderIdsAsync(orderIds); var recipients = await OrderRepository.GetRecipientsByOrderIdsAsync(orderIds); var declarations = await OrderRepository.GetDeclarationsByOrderIdsAsync(orderIds); var weights = await OrderRepository.GetWeightsByOrderIdsAsync(orderIds); var fees = await OrderRepository.GetFeesByOrderIdsAsync(orderIds); var warehouses = warehouseIds.Length == 0 ? [] : await WarehouseAddressRepository.GetListAsync(x => warehouseIds.Contains(x.Id)); var senderMap = senders.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.First()); var recipientMap = recipients.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.First()); var declarationMap = declarations.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.ToList()); var weightMap = weights.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.ToList()); var feeMap = fees.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.ToList()); var warehouseMap = warehouses.ToDictionary(x => x.Id); var productCodes = orders .Where(x => !string.IsNullOrWhiteSpace(x.ProductCode)) .Select(x => x.ProductCode!.Trim()) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); var channelCodes = orders .Where(x => !string.IsNullOrWhiteSpace(x.ChannelCode)) .Select(x => x.ChannelCode!.Trim()) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); var products = productCodes.Length == 0 ? [] : await SalesProductRepository.GetListAsync(x => productCodes.Contains(x.ProductCode)); var channels = channelCodes.Length == 0 ? [] : await ServiceChannelRepository.GetListAsync(x => channelCodes.Contains(x.ChannelCode)); var productMap = products.ToDictionary(x => x.ProductCode, StringComparer.OrdinalIgnoreCase); var channelMap = channels.ToDictionary(x => x.ChannelCode, StringComparer.OrdinalIgnoreCase); var countryCodes = orders .Where(x => !string.IsNullOrWhiteSpace(x.ConsigneeCountry)) .Select(x => x.ConsigneeCountry!.Trim()) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); var countries = countryCodes.Length == 0 ? [] : await CountryRepository.GetListAsync(x => countryCodes.Contains(x.CountryCode)); var countryMap = countries.ToDictionary(x => x.CountryCode, StringComparer.OrdinalIgnoreCase); var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync( orders.SelectMany(x => new[] { x.CreateUserId, x.UpdateUserId })); var customerIds = orders .Where(x => x.CustomerId is > 0) .Select(x => x.CustomerId!.Value) .Distinct() .ToArray(); var customers = customerIds.Length == 0 ? [] : await CustomerRepository.GetListAsync(x => customerIds.Contains(x.Id)); var customerMap = customers.ToDictionary(x => x.Id); var outputs = orders.Select(order => { senderMap.TryGetValue(order.Id, out var sender); recipientMap.TryGetValue(order.Id, out var recipient); declarationMap.TryGetValue(order.Id, out var items); weightMap.TryGetValue(order.Id, out var orderWeights); feeMap.TryGetValue(order.Id, out var orderFees); var feeOutputs = (orderFees ?? []).Select(MapFee).ToList(); var chargeableWeight = ResolveDisplayChargeableWeight(orderWeights); var receivableAmount = feeOutputs .Where(x => x.Type == OrderFeeTypeCodes.Receivable) .Sum(x => x.Amount); string? customerName = null; string? customerCode = null; if (order.CustomerId is > 0 && customerMap.TryGetValue(order.CustomerId.Value, out var customer)) { customerName = customer.CustomerName; customerCode = customer.CustomerCode; } return new OrderOutput { Id = order.Id, ClientNo = order.ClientNo, TrackNo = order.TrackNo, DownstreamServiceNo = order.DownstreamServiceNo, ServiceNo = order.ServiceNo, ProductCode = order.ProductCode, ProductName = !string.IsNullOrWhiteSpace(order.ProductCode) && productMap.TryGetValue(order.ProductCode.Trim(), out var product) ? product.ProductName : null, ChannelCode = order.ChannelCode, DownstreamSupplierCode = order.DownstreamSupplierCode, DownstreamAppKey = order.DownstreamAppKey, DownstreamAppId = order.DownstreamAppId, ChannelForecastCode = order.ChannelForecastCode, ChannelName = !string.IsNullOrWhiteSpace(order.ChannelCode) && channelMap.TryGetValue(order.ChannelCode.Trim(), out var channel) ? channel.ChannelName : null, ConsigneeCountry = order.ConsigneeCountry, ConsigneeCountryName = ResolveConsigneeCountryName(order, countryMap), CargoAttribute = order.CargoAttribute, WarehouseId = order.WarehouseId, Warehouse = order.WarehouseId.HasValue && warehouseMap.TryGetValue(order.WarehouseId.Value, out var warehouse) ? warehouse.WarehouseName : null, CustomerId = order.CustomerId, CustomerName = customerName, CustomerCode = customerCode, OrderSource = string.IsNullOrWhiteSpace(order.OrderSource) ? OrderSourceCodes.Manual : order.OrderSource, PickupTime = order.PickupTime, CustomerSenderAddressId = order.CustomerSenderAddressId, RequestId = order.RequestId, ExportCustomsMode = order.ExportCustomsMode, PredeclareFailReason = string.IsNullOrWhiteSpace(order.PredeclareFailReason) ? null : order.PredeclareFailReason.Trim(), AllocationPendingReason = string.IsNullOrWhiteSpace(order.AllocationPendingReason) ? null : order.AllocationPendingReason.Trim(), DeclaredCurrency = order.DeclaredCurrency, DeclaredSum = order.DeclaredSum, Quantity = order.Quantity, IsCod = order.IsCod > 0, CodCurrency = order.CodCurrency, CodSum = order.CodSum, OrderStatus = OmsDocHelper.GetOrderStatusName(order.OrderStatus), Status = order.OrderStatus, HandleStatus = OrderHandleStatusCodes.IsProcessed(order.HandleStatus) ? OrderHandleStatusCodes.Processed : OrderHandleStatusCodes.Pending, HandleStatusName = OrderHandleStatusCodes.GetDisplayName(order.HandleStatus), IssueType = order.IssueType, IssueTypeName = IssueTypeCodes.GetDisplayName(order.IssueType), IssueTitle = order.IssueTitle, IssueContent = order.IssueContent, IssueTemplateId = order.IssueTemplateId, IssueRemark = order.IssueRemark, IssueTime = order.IssueTime, ClaimType = order.ClaimType, ClaimTypeName = ClaimTypeCodes.GetDisplayName(order.ClaimType), ClaimAmount = order.ClaimAmount, ClaimCurrency = order.ClaimCurrency, ClaimReason = order.ClaimReason, ClaimTime = order.ClaimTime, PreviousOrderStatus = order.PreviousOrderStatus, ReceiveTime = order.ReceiveTime, ShipTime = order.ShipTime, PayTime = order.PayTime, IsPaid = order.IsPaid > 0, SignTime = order.SignTime, IsIntercept = order.IsIntercept > 0, IsRemote = order.IsRemote > 0, CreateTime = order.CreateTime, CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(order.CreateUserId, auditUserNameMap), UpdateTime = OmsDocHelper.NullIfDefault(order.UpdateTime), UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(order.UpdateUserId, auditUserNameMap), Sender = MapSender(sender), Receiver = MapReceiver(recipient), Items = (items ?? []).Select(MapDeclaration).ToList(), WeightList = (orderWeights ?? []).Select(MapWeight).ToList(), FeeList = feeOutputs, ChargeableWeight = chargeableWeight, ReceivableAmount = feeOutputs.Count == 0 ? null : receivableAmount }; }).ToList(); if (OmsSessionHelper.IsCustomerLogin(CurrentUser)) { RedactChannelFieldsForCustomer(outputs); } return outputs; } private static void RedactChannelFieldsForCustomer(IEnumerable outputs) { foreach (var output in outputs) { output.ChannelCode = null; output.ChannelName = null; output.DownstreamSupplierCode = null; output.DownstreamAppKey = null; output.DownstreamAppId = null; output.ChannelForecastCode = null; } } private async Task> BuildOrderExportRowsAsync(IReadOnlyCollection orders) { var mapped = await MapOrderOutputsAsync(orders); return mapped.Select(x => (object)new { x.Id, x.ClientNo, x.TrackNo, x.DownstreamServiceNo, x.ServiceNo, x.ProductCode, x.ProductName, x.ChannelCode, x.ChannelName, x.CargoAttribute, x.WarehouseId, x.Warehouse, x.CustomerId, x.Status, x.OrderStatus, x.PredeclareFailReason, x.ReceiveTime, x.ShipTime, x.PayTime, x.IsPaid, x.SignTime, x.IsCod, x.CodCurrency, x.CodSum, x.IsIntercept, x.IsRemote, x.CreateTime, x.UpdateTime }).ToList(); } private async Task> GetTemplateOutputsAsync(OrderTemplateListInput input) { if (string.IsNullOrWhiteSpace(input.Type) || string.Equals(input.Type, "standard", StringComparison.OrdinalIgnoreCase)) { await EnsureDedicatedSmallParcelStandardTemplateAsync(); } var page = OmsDocHelper.NormalizePage(input.Page); var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize); var keyword = input.Keyword?.Trim(); var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync( CustomerRepository, CurrentUser, null); var hasCustomerFilter = customerId.HasValue; var customerIdValue = customerId.GetValueOrDefault(); var predicate = (Expression>)(x => (string.IsNullOrWhiteSpace(input.Type) || x.Type == input.Type) && (string.IsNullOrWhiteSpace(keyword) || x.Name.Contains(keyword) || (x.TemplateKey ?? string.Empty).Contains(keyword)) && (!hasCustomerFilter || x.Type == "standard" || x.CustomerId == customerIdValue)); var templates = await OrderTemplateRepository.GetPagedListAsync( predicate, page, pageSize, new Dictionary { [nameof(OrderTemplate.UpdateTime)] = false, [nameof(OrderTemplate.Id)] = false }); var total = await OrderTemplateRepository.CountAsync(predicate); return new OmsPageResult { Items = templates.Select(x => new OrderTemplateOutput { Id = x.Id, Name = x.Name, Type = x.Type, TemplateKey = x.TemplateKey, CustomerId = x.CustomerId, MappingStatus = string.Equals(x.Type, "standard", StringComparison.OrdinalIgnoreCase) ? OrderTemplateMappingStatus.Ready : x.MappingStatus, StandardTemplateKey = x.StandardTemplateKey ?? x.TemplateKey, SourceFileName = x.SourceFileName, CreateTime = x.CreateTime, UpdateTime = OmsDocHelper.NullIfDefault(x.UpdateTime) }).ToList(), Total = total }; } private async Task BuildTemplateDownloadAsync(int templateId) { var template = await OrderTemplateRepository.FirstOrDefaultAsync(x => x.Id == templateId); if (template == null) { throw new BusinessException("模板不存在"); } var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync( CustomerRepository, CurrentUser, null); if (customerId.HasValue) { EnsureTemplateAccessible(template, customerId.Value); } if (string.Equals(template.Type, "custom", StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrWhiteSpace(template.SourceFilePath)) { throw new BusinessException("自定义模板样例文件不存在,请重新上传"); } var absolutePath = OmsFileUploadHelper.ResolveWebRootAbsolutePath(WebHostEnvironment, template.SourceFilePath); if (!File.Exists(absolutePath)) { throw new BusinessException("自定义模板样例文件不存在,请重新上传"); } var bytes = await File.ReadAllBytesAsync(absolutePath); var downloadName = string.IsNullOrWhiteSpace(template.SourceFileName) ? $"{template.Name}.xlsx" : template.SourceFileName; return new FileContentResult(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { FileDownloadName = downloadName }; } var templateKey = template.TemplateKey ?? template.StandardTemplateKey ?? OrderTemplateKeys.DedicatedSmallParcel; var exampleOverrides = await BuildTemplateExampleOverridesAsync(customerId); var dictOptions = await LoadTemplateDictOptionsAsync( ["sales_product", "cargo_attribute", "export_customs_mode", "currency", "warehouse"]); var fileBytes = await OrderTemplateExcelGenerator.BuildStandardTemplateAsync( templateKey, exampleOverrides, dictOptions); return new FileContentResult(fileBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { FileDownloadName = $"{template.Name}-{DateTime.Now:yyyyMMddHHmmss}.xlsx" }; } private async Task ImportOrdersAsync(OrderUploadInput input) { if (input.File == null || input.File.Length == 0) { throw new BusinessException("上传文件不能为空"); } var batchInput = await BuildImportBatchJobInputAsync(input); var operatorUserId = CurrentUser.GetId(); if (BatchJobPublisher.IsEnabled) { var job = await BatchJobCoordinator.CreatePayloadJobAsync(batchInput, operatorUserId); return new OrderUploadOutput { JobId = job.JobId, Async = true }; } var syncJob = await BatchJobCoordinator.CreatePayloadJobAndProcessSyncAsync(batchInput, operatorUserId); return new OrderUploadOutput { JobId = syncJob.JobId, Async = false }; } private async Task BuildImportBatchJobInputAsync(OrderUploadInput input) { var template = await OrderTemplateRepository.FirstOrDefaultAsync(x => x.Id == input.TemplateId) ?? throw new BusinessException("模板不存在"); var effectiveCustomer = await ResolveEffectiveCustomerAsync(); EnsureTemplateAccessible(template, effectiveCustomer.Id); OrderTemplateImportMapping.EnsureTemplateReadyForImport(template); var mapping = OrderTemplateImportMapping.Resolve(template); await using var stream = input.File!.OpenReadStream(); var parsedRows = await OrderTemplateExcelReader.ReadDataRowsAsync(stream, mapping); if (parsedRows.Count == 0) { throw new BusinessException("Excel 中未读取到可用数据"); } if (parsedRows.Count > ParcelBatchMaxCount) { throw new BusinessException($"单次最多导入 {ParcelBatchMaxCount} 行"); } var senderAddressId = await ResolveImportSenderAddressIdAsync( effectiveCustomer.Id, input.SenderAddressId, cancellationToken: default); var taskName = $"批量下单_{DateTime.Now:yyyyMMddHHmmss}"; var requestId = $"import-{effectiveCustomer.Id}-{template.Id}-{DateTime.Now:yyyyMMddHHmmssfff}"; var jobPayload = JsonConvert.SerializeObject(new OrderBatchImportJobPayload { TaskName = taskName, TemplateId = template.Id, CustomerId = effectiveCustomer.Id, CustomerSenderAddressId = senderAddressId, }); var payloadItems = parsedRows.Select(row => { var parcelInput = OrderTemplateRowMapper.MapToParcelCreateInput(row.SourceValues, mapping, effectiveCustomer.Id); return new OrderBatchPayloadItemInput { OrderId = 0, ServiceNo = parcelInput.ServiceNo, ClientNo = parcelInput.ClientNo, ItemKey = $"import:{requestId}:{row.RowNumber}", PayloadJson = JsonConvert.SerializeObject(new OrderBatchImportRowPayload { RowNumber = row.RowNumber, CustomerId = effectiveCustomer.Id, TemplateId = template.Id, CustomerSenderAddressId = senderAddressId, RowDataJson = JsonConvert.SerializeObject(row.SourceValues), }), }; }).ToList(); return new OrderBatchPayloadJobCreateInput { Action = OrderBatchActionCodes.ImportRow, CustomerId = effectiveCustomer.Id, JobPayloadJson = jobPayload, RequestId = requestId, Items = payloadItems, }; } private async Task CreateOrderPrintFileAsync(OrderOutput order) { var directory = Path.Combine(GetWebRootDirectory(), "uploads", "prints", "orders"); Directory.CreateDirectory(directory); var fileName = $"{order.ServiceNo}-{DateTime.Now:yyyyMMddHHmmss}.html"; var html = $""" {order.ServiceNo}

Order Label

ServiceNo: {order.ServiceNo}

ClientNo: {order.ClientNo}

TrackNo: {order.TrackNo}

Warehouse: {order.Warehouse}

"""; await File.WriteAllTextAsync(Path.Combine(directory, fileName), html, Encoding.UTF8); return $"/uploads/prints/orders/{fileName}"; } private string GetOrderExportDirectory() => Path.Combine(GetWebRootDirectory(), "uploads", "exports", "orders"); private string GetWebRootDirectory() { var webRoot = string.IsNullOrWhiteSpace(WebHostEnvironment.WebRootPath) ? Path.Combine(WebHostEnvironment.ContentRootPath, "wwwroot") : WebHostEnvironment.WebRootPath; Directory.CreateDirectory(webRoot); return webRoot; } private async Task CleanupExpiredFilesAsync(string directory) { if (!Directory.Exists(directory)) { return; } await Task.Run(() => { foreach (var file in Directory.GetFiles(directory)) { if (File.GetCreationTime(file) <= DateTime.Now.AddHours(-24)) { File.Delete(file); } } }); } private static string? ResolveConsigneeCountryName( Order order, IReadOnlyDictionary countryMap) { if (!string.IsNullOrWhiteSpace(order.ConsigneeCountryName)) { return order.ConsigneeCountryName.Trim(); } if (string.IsNullOrWhiteSpace(order.ConsigneeCountry)) { return null; } return countryMap.TryGetValue(order.ConsigneeCountry.Trim(), out var country) ? country.ChineseName : null; } private static OrderSenderOutput? MapSender(OrderSender? sender) { return sender == null ? null : new OrderSenderOutput { SenderName = sender.SenderName, Company = sender.Company, Phone = sender.Phone, TelePhone = sender.TelePhone, Email = sender.Email, CountryCode = sender.Country, Province = sender.Province, City = sender.City, ZipCode = sender.ZipCode, StreetAddress1 = sender.StreetAddress1, StreetAddress2 = sender.StreetAddress2, StreetAddress3 = sender.StreetAddress3, HouseNumber = sender.HouseNumber }; } private static OrderReceiverOutput? MapReceiver(OrderRecipient? recipient) { return recipient == null ? null : new OrderReceiverOutput { RecipientsName = recipient.RecipientsName, CompanyName = recipient.CompanyName, Phone = recipient.Phone, TelePhone = recipient.TelePhone, Email = recipient.Email, CountryCode = recipient.Country, Province = recipient.Province, City = recipient.City, StreetNumber = recipient.StreetNumber, StreetAddress1 = recipient.StreetAddress1, StreetAddress2 = recipient.StreetAddress2, StreetAddress3 = recipient.StreetAddress3, ZipCode = recipient.ZipCode, TaxType = recipient.TaxType, TaxNo = recipient.TaxNo, CertificateType = recipient.CertificateType, CertificateNo = recipient.CertificateNo, Eori = recipient.Eori, Vat = recipient.Vat }; } private static OrderItemOutput MapDeclaration(OrderDeclaration x) { return new OrderItemOutput { CnName = x.CnName, EnName = x.EnName, Sku = x.Sku, Unit = x.Unit, UnitPrice = x.UnitPrice, UnitWeight = x.UnitWeight, Quantity = x.Quantity, Amount = x.Amount, Weight = x.Weight, HsCode = x.ExHsCode ?? x.ImHsCode ?? x.HsCode, SkuImage = x.SkuImage, Category = x.Category, Brand = x.Brand, BrandType = x.BrandType, IsMagnetic = x.IsMagnetic > 0, Distribution = x.Distribution, Material = x.Material, EnMaterial = x.EnMaterial, Purpose = x.Purpose, Attributes = x.Attributes, OriginCountry = x.OriginCountry, SalesLink = x.SalesLink, Model = x.Model, Specifications = x.Specifications, Comment = x.Comment }; } private static OrderWeightOutput MapWeight(OrderWeight x) { return new OrderWeightOutput { Type = x.Type, Length = x.Length, Width = x.Width, Height = x.Height, ActualWeight = x.ActualWeight, VolumetricWeight = x.VolumetricWeight, ChargeableWeight = x.ChargeableWeight, Cubic = x.Cubic }; } private static OrderFeeOutput MapFee(OrderFee x) => new() { Id = x.Id, Type = x.Type, CostItem = x.CostItem, Amount = x.Amount, Currency = x.Currency, DownstreamProvider = x.DownstreamProvider, PriceNo = x.PriceNo, PriceEffectiveTime = x.PriceEffectiveTime, ChargingStage = x.ChargingStage }; private static decimal? ResolveDisplayChargeableWeight(IReadOnlyList? weights) { if (weights == null || weights.Count == 0) { return null; } var receive = weights.FirstOrDefault(x => x.Type == OrderWeightTypeCodes.Receive); if (receive?.ChargeableWeight is > 0) { return receive.ChargeableWeight; } var forecast = weights.FirstOrDefault(x => x.Type == OrderWeightTypeCodes.Forecast); return forecast?.ChargeableWeight; } private static string? GetStringCell(IDictionary row, string key) => row.TryGetValue(key, out var value) ? value?.ToString() : null; private static int? GetintCell(IDictionary row, string key) => int.TryParse(GetStringCell(row, key), out var value) ? value : null; private static int? GetIntCell(IDictionary row, string key) => int.TryParse(GetStringCell(row, key), out var value) ? value : null; private static decimal? GetDecimalCell(IDictionary row, string key) => decimal.TryParse(GetStringCell(row, key), out var value) ? value : null; private static bool GetBoolCell(IDictionary row, string key) => GetStringCell(row, key) is "1" or "true" or "True" or "TRUE" or "是"; private static void EnsureTemplateAccessible(OrderTemplate template, int effectiveCustomerId) { if (string.Equals(template.Type, "standard", StringComparison.OrdinalIgnoreCase)) { return; } if (template.CustomerId != effectiveCustomerId) { throw new BusinessException("模板不存在"); } } private OrderWeight? BuildForecastWeight(int orderId, IDictionary row) { var length = GetDecimalCell(row, "Length"); var width = GetDecimalCell(row, "Width"); var height = GetDecimalCell(row, "Height"); var actualWeight = GetDecimalCell(row, "ActualWeight"); var volumetricWeight = GetDecimalCell(row, "VolumetricWeight"); var chargeableWeight = GetDecimalCell(row, "ChargeableWeight"); var cubic = GetDecimalCell(row, "Cubic"); if (!length.HasValue && !width.HasValue && !height.HasValue && !actualWeight.HasValue && !volumetricWeight.HasValue && !chargeableWeight.HasValue && !cubic.HasValue) { return null; } return new OrderWeight { OrderId = orderId, Type = OrderWeightTypeCodes.Forecast, Length = length, Width = width, Height = height, ActualWeight = actualWeight, VolumetricWeight = volumetricWeight, ChargeableWeight = chargeableWeight, Cubic = cubic }; } private async Task ApplyInternalOrderDataScopeAsync(OrderListFilter filter) { if (OmsSessionHelper.IsCustomerLogin(CurrentUser)) { return; } var userGuidRaw = CurrentUser.FindClaimValueOrNull(global::System.Security.Claims.ClaimTypes.NameIdentifier); if (string.IsNullOrWhiteSpace(userGuidRaw) || !Guid.TryParse(userGuidRaw, out var userGuid)) { return; } var context = await DataScopeBuilder.BuildAsync(userGuid, DataScopeApplier.OrderResourceCode); DataScopeApplier.ApplyToOrderListFilter(filter, context); } }