< Summary

Information
Class: OzonOrdersWeb.WebServices.Orders.OrderSupplierStateInfoService
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/WebServices/Orders/OrderSupplierStateInfoService.cs
Line coverage
88%
Covered lines: 54
Uncovered lines: 7
Coverable lines: 61
Total lines: 105
Line coverage: 88.5%
Branch coverage
36%
Covered branches: 17
Total branches: 46
Branch coverage: 36.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
PopulateForOrdersAsync()90%101097.67%
ResolveDisplayName(...)22.22%2463645.45%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/WebServices/Orders/OrderSupplierStateInfoService.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using OzonDomains.Models;
 3using OzonDomains.Models.SupplierStatuses;
 4using OzonRepositories.Context;
 5
 6namespace OzonOrdersWeb.WebServices.Orders;
 7
 8public interface IOrderSupplierStateInfoService
 9{
 10    /// <summary>
 11    /// Проецирует состояние у поставщика на [NotMapped] поля заказов страницы.
 12    /// Один запрос на страницу — модель Order при этом не расширяется.
 13    /// </summary>
 14    Task PopulateForOrdersAsync(IReadOnlyList<Order> ordersForPage, CancellationToken cancellationToken = default);
 15}
 16
 17public sealed class OrderSupplierStateInfoService : IOrderSupplierStateInfoService
 18{
 19    private readonly ApplicationDbContext _context;
 20
 521    public OrderSupplierStateInfoService(ApplicationDbContext context)
 22    {
 523        _context = context;
 524    }
 25
 26    public async Task PopulateForOrdersAsync(
 27        IReadOnlyList<Order> ordersForPage, CancellationToken cancellationToken = default)
 28    {
 529        if (ordersForPage.Count == 0)
 30        {
 031            return;
 32        }
 33
 1034        var orderIds = ordersForPage.Select(o => o.Id).Distinct().ToList();
 35
 36        // Активных строк на заказ может быть несколько (позиция разведена по двум поставщикам) —
 37        // в узкую ячейку списка помещается одна, берём самую свежую по смене статуса.
 538        var stateMap = await _context.OrderSupplierStates
 539            .AsNoTracking()
 540            .Where(s => s.ActiveOrderId != null && orderIds.Contains(s.OrderId))
 541            .Select(s => new
 542            {
 543                s.OrderId,
 544                s.ProviderKey,
 545                s.Stage,
 546                s.ExternalOrderNumber,
 547                s.LastStatusChangeAt,
 548                s.DeliveryDaysMin,
 549                s.DeliveryDaysMax,
 550                s.Direction,
 551                s.OrderedAt,
 552                s.CreatedAt,
 553                StatusName = s.SupplierStatus != null ? s.SupplierStatus.Name : null,
 554                StatusColor = s.SupplierStatus != null && s.SupplierStatus.StatusColor != null
 555                    ? s.SupplierStatus.StatusColor.ColorCode
 556                    : null,
 557                SupplierName = s.SupplierStatus != null && s.SupplierStatus.Supplier != null
 558                    ? s.SupplierStatus.Supplier.Name
 559                    : null
 560            })
 561            .ToListAsync(cancellationToken);
 62
 563        var latestByOrderId = stateMap
 564            .GroupBy(x => x.OrderId)
 565            .ToDictionary(
 466                g => g.Key,
 1467                g => g.OrderByDescending(x => x.LastStatusChangeAt ?? DateTime.MinValue).First());
 68
 2069        foreach (var order in ordersForPage)
 70        {
 571            if (!latestByOrderId.TryGetValue(order.Id, out var state))
 72            {
 73                continue;
 74            }
 75
 476            order.SupplierStateProviderKey = state.ProviderKey;
 477            order.SupplierStateStage = state.Stage;
 478            order.SupplierStatusName = state.StatusName;
 479            order.SupplierStatusColor = state.StatusColor;
 480            order.SupplierStateExternalOrderNumber = state.ExternalOrderNumber;
 481            order.SupplierStateChangedAt = state.LastStatusChangeAt;
 482            order.SupplierStateSupplierName = state.SupplierName ?? ResolveDisplayName(state.ProviderKey);
 483            order.SupplierStateDeliveryDaysMin = state.DeliveryDaysMin;
 484            order.SupplierStateDeliveryDaysMax = state.DeliveryDaysMax;
 485            order.SupplierStateDirection = state.Direction;
 86            // Хранятся в БД в UTC — приводим к локальному времени сервера, как и остальные даты заказа
 87            // (ProcessingDate/ShippingDate считаются уже в местном времени, TimeLeft сравнивает с DateTime.Now).
 488            order.SupplierStateOrderedAt = state.OrderedAt?.ToLocalTime();
 489            order.SupplierStateCartCreatedAt = state.CreatedAt.ToLocalTime();
 90        }
 591    }
 92
 93    /// <summary>Запасное имя, когда связь провайдера с записью справочника Supplier не настроена.</summary>
 494    private static string ResolveDisplayName(string providerKey) => providerKey switch
 495    {
 396        ApiSupplierSettings.AvdProviderKey => "АВД",
 197        ApiSupplierSettings.ArmtekProviderKey => "Армтек",
 098        ApiSupplierSettings.ArmtekByProviderKey => "Армтек BY",
 099        ApiSupplierSettings.MlAutoProviderKey => "ML-Auto BY",
 0100        ApiSupplierSettings.MlAutoRuProviderKey => "ML-Auto RU",
 0101        ApiSupplierSettings.FavoritPartsProviderKey => "Фаворит Союз",
 0102        ApiSupplierSettings.FavoritPartsIstraProviderKey => "Фаворит Истра",
 0103        _ => providerKey
 4104    };
 105}