using Fake.DependencyInjection; using Oms.Application.Dtos.Channels; using Oms.Application.Integrations.Itfx; using Oms.Domain.ChannelsAggregate.Entities; using Oms.Domain.ChannelsAggregate.Repositories; namespace Oms.Application.Shared; /// /// 为排货 Provider 快照补充渠道与 itfx 下游对接元数据。 /// public class AllocationProviderSnapshotEnricher( IServiceChannelRepository serviceChannelRepository, IServiceChannelGroupRepository serviceChannelGroupRepository, IItfxMetadataClient itfxMetadataClient) : IScopedDependency { public async Task EnrichAsync( IList providers, CancellationToken cancellationToken = default) { if (providers.Count == 0) { return; } var channelIds = providers .Where(x => x.ServiceChannelId.HasValue && x.ServiceChannelId.Value > 0) .Select(x => x.ServiceChannelId!.Value) .Distinct() .ToArray(); if (channelIds.Length == 0) { return; } var channels = await serviceChannelRepository.GetListAsync(x => channelIds.Contains(x.Id)); var channelMap = channels.ToDictionary(x => x.Id); var groupIds = channels .Where(x => x.GroupId.HasValue && x.GroupId.Value > 0) .Select(x => x.GroupId!.Value) .Distinct() .ToArray(); var groups = groupIds.Length == 0 ? [] : await serviceChannelGroupRepository.GetListAsync(x => groupIds.Contains(x.Id)); var groupMap = groups.ToDictionary(x => x.Id); foreach (var provider in providers) { if (!provider.ServiceChannelId.HasValue || !channelMap.TryGetValue(provider.ServiceChannelId.Value, out var channel)) { continue; } ApplyChannelFields(provider, channel); if (!channel.GroupId.HasValue || !groupMap.TryGetValue(channel.GroupId.Value, out var group)) { continue; } await ApplyGroupDownstreamFieldsAsync(provider, group, cancellationToken); } } public async Task BuildDownstreamFromGroupAsync( ServiceChannelGroup group, CancellationToken cancellationToken = default) { var snapshot = new ServiceChannelDownstreamSnapshotDto { GroupId = group.Id, GroupName = NullIfEmpty(group.Name), AppId = group.AppId > 0 ? group.AppId : null, ApiServiceProviderId = group.ApiServiceProviderId > 0 ? group.ApiServiceProviderId : null }; await FillItfxMetadataAsync(snapshot, cancellationToken); return snapshot.GroupId.HasValue || !string.IsNullOrWhiteSpace(snapshot.GroupName) || snapshot.AppId is > 0 || !string.IsNullOrWhiteSpace(snapshot.AppKey) || !string.IsNullOrWhiteSpace(snapshot.AppName) || snapshot.ApiServiceProviderId is > 0 || !string.IsNullOrWhiteSpace(snapshot.SupplierCode) || !string.IsNullOrWhiteSpace(snapshot.ApiServiceProviderName) ? snapshot : null; } public static void ApplyChannelFields(SalesProductAllocationProviderSnapshotDto provider, ServiceChannel channel) { provider.ChannelCode = NullIfEmpty(channel.ChannelCode); provider.ForecastCode = NullIfEmpty(channel.ForecastCode); provider.GroupId = channel.GroupId; if (string.IsNullOrWhiteSpace(provider.ServiceChannelName)) { provider.ServiceChannelName = NullIfEmpty(channel.ChannelName); } } public static void ApplyDownstreamFieldsToOrder( Domain.OrdersAggregate.Entities.Order order, SalesProductAllocationProviderSnapshotDto provider, ServiceChannel? channelFallback = null) { order.DownstreamSupplierCode = NullIfEmpty(provider.SupplierCode); order.DownstreamAppKey = NullIfEmpty(provider.AppKey); order.DownstreamAppId = provider.AppId; order.ChannelForecastCode = NullIfEmpty(provider.ForecastCode) ?? NullIfEmpty(channelFallback?.ForecastCode); } private async Task ApplyGroupDownstreamFieldsAsync( SalesProductAllocationProviderSnapshotDto provider, ServiceChannelGroup group, CancellationToken cancellationToken) { provider.GroupId = group.Id; provider.GroupName = NullIfEmpty(group.Name); provider.AppId = group.AppId > 0 ? group.AppId : null; provider.ApiServiceProviderId = group.ApiServiceProviderId > 0 ? group.ApiServiceProviderId : null; if (provider.AppId is > 0) { var app = await itfxMetadataClient.GetAppAsync(provider.AppId.Value, cancellationToken); if (!string.IsNullOrWhiteSpace(app?.AppKey)) { provider.AppKey = app.AppKey; } provider.AppName = NullIfEmpty(app?.Name); } if (provider.ApiServiceProviderId is > 0) { var sp = await itfxMetadataClient.GetServiceProviderAsync( provider.ApiServiceProviderId.Value, cancellationToken); if (!string.IsNullOrWhiteSpace(sp?.Code)) { provider.SupplierCode = sp.Code; } provider.ApiServiceProviderName = NullIfEmpty(sp?.Name); } } private async Task FillItfxMetadataAsync( ServiceChannelDownstreamSnapshotDto snapshot, CancellationToken cancellationToken) { if (snapshot.AppId is > 0) { var app = await itfxMetadataClient.GetAppAsync(snapshot.AppId.Value, cancellationToken); if (!string.IsNullOrWhiteSpace(app?.AppKey)) { snapshot.AppKey = app.AppKey; } if (!string.IsNullOrWhiteSpace(app?.AppSecret)) { snapshot.AppSecret = app.AppSecret; } snapshot.AppName = NullIfEmpty(app?.Name); } if (snapshot.ApiServiceProviderId is > 0) { var sp = await itfxMetadataClient.GetServiceProviderAsync( snapshot.ApiServiceProviderId.Value, cancellationToken); if (!string.IsNullOrWhiteSpace(sp?.Code)) { snapshot.SupplierCode = sp.Code; } snapshot.ApiServiceProviderName = NullIfEmpty(sp?.Name); } } private static string? NullIfEmpty(string? value) => string.IsNullOrWhiteSpace(value) ? null : value.Trim(); public static bool NeedsDownstreamEnrichment(SalesProductAllocationProviderSnapshotDto provider) => provider.ServiceChannelId is > 0 && (string.IsNullOrWhiteSpace(provider.ChannelCode) || string.IsNullOrWhiteSpace(provider.ForecastCode) || string.IsNullOrWhiteSpace(provider.SupplierCode) || string.IsNullOrWhiteSpace(provider.AppKey)); }