< Summary

Information
Class: Services.FeedPriceServices.FeedOrderPick
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/FeedPriceServices/FeedOrderRowPicker.cs
Line coverage
100%
Covered lines: 7
Uncovered lines: 0
Coverable lines: 7
Total lines: 100
Line coverage: 100%
Branch coverage
50%
Covered branches: 1
Total branches: 2
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_State()100%11100%
get_Row()100%11100%
get_Cabinet()100%11100%
get_CabinetName()50%22100%
get_Client()100%11100%
get_OrderWarehouse()100%11100%
get_WarehouseFallback()100%11100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/FeedPriceServices/FeedOrderRowPicker.cs

#LineLine coverage
 1using System.Text.Json.Serialization;
 2using OzonDomains.Models;
 3
 4namespace Services.FeedPriceServices;
 5
 6/// <summary>Результат выбора строки фида для заказа.</summary>
 7[JsonConverter(typeof(JsonStringEnumConverter))]
 8public enum FeedOrderState
 9{
 10    /// <summary>Строка найдена, цена есть.</summary>
 11    Ok,
 12
 13    /// <summary>У заказа нет ключа артикула.</summary>
 14    NoKey,
 15
 16    /// <summary>Клиент заказа не сопоставлен с кабинетом фида.</summary>
 17    NoCabinet,
 18
 19    /// <summary>В кабинете клиента нет такого артикула.</summary>
 20    NotInFeed,
 21
 22    /// <summary>Артикул в фиде есть, но ни цены, ни закупки, ни старой цены.</summary>
 23    NoPrice,
 24
 25    /// <summary>Фид-сервис недоступен (используется расшифровкой цены).</summary>
 26    Error
 27}
 28
 29/// <summary>Строка фида, соответствующая клиенту и складу заказа.</summary>
 30public sealed class FeedOrderPick
 31{
 3432    public FeedOrderState State { get; init; }
 3433    public FeedCurrentRow? Row { get; init; }
 34
 35    /// <summary>Кабинет клиента заказа (ключ фида); null, если клиент не сопоставлен.</summary>
 2836    public string? Cabinet { get; init; }
 37
 238    public string? CabinetName => Cabinet is null ? null : FeedCabinets.DisplayName(Cabinet);
 2339    public string? Client { get; init; }
 40
 41    /// <summary>Склад отгрузки заказа.</summary>
 2242    public string? OrderWarehouse { get; init; }
 43
 44    /// <summary>Склада заказа нет среди складов фида: показана строка склада цены кабинета.</summary>
 2745    public bool WarehouseFallback { get; init; }
 46}
 47
 48/// <summary>Выбирает из снимка фида строку по кабинету клиента и складу заказа.</summary>
 49public static class FeedOrderRowPicker
 50{
 51    public static FeedOrderPick Pick(
 52        IReadOnlyCollection<FeedCurrentRow> current,
 53        IReadOnlyCollection<string> articleKeys,
 54        string? clientName,
 55        string? warehouseName)
 56    {
 57        var cabinet = FeedCabinets.ForClientName(clientName);
 58        FeedOrderPick Result(FeedOrderState state, FeedCurrentRow? row = null, bool fallback = false) => new()
 59        {
 60            State = state,
 61            Row = row,
 62            Cabinet = cabinet,
 63            Client = clientName,
 64            OrderWarehouse = warehouseName,
 65            WarehouseFallback = fallback
 66        };
 67
 68        if (articleKeys.Count == 0) return Result(FeedOrderState.NoKey);
 69        if (cabinet is null) return Result(FeedOrderState.NoCabinet);
 70
 71        // Ключей до двух; берём первый, по которому в кабинете есть данные.
 72        List<FeedCurrentRow> rows = [];
 73        foreach (var key in articleKeys)
 74        {
 75            rows = current
 76                .Where(x => string.Equals(x.Cabinet, cabinet, StringComparison.OrdinalIgnoreCase)
 77                            && string.Equals(x.Article, key, StringComparison.OrdinalIgnoreCase))
 78                .ToList();
 79            if (rows.Count > 0) break;
 80        }
 81
 82        if (rows.Count == 0) return Result(FeedOrderState.NotInFeed);
 83
 84        var wanted = WarehouseNameNormalizer.Normalize(warehouseName);
 85        var exact = wanted is null
 86            ? null
 87            : rows.FirstOrDefault(x => string.Equals(WarehouseNameNormalizer.Normalize(x.Warehouse), wanted, StringCompa
 88
 89        // Цена кабинета общая для складов, но у склада без цены строка пустая: тогда берём склад цены.
 90        if (exact is not null && HasValues(exact)) return Result(FeedOrderState.Ok, exact);
 91
 92        var fallback = rows.FirstOrDefault(x => x.IsPriceWarehouse && HasValues(x)) ?? rows.FirstOrDefault(HasValues);
 93        if (fallback is not null) return Result(FeedOrderState.Ok, fallback, fallback: true);
 94
 95        return Result(FeedOrderState.NoPrice, exact ?? rows[0], fallback: exact is null);
 96    }
 97
 98    private static bool HasValues(FeedCurrentRow row) =>
 99        row.PurchasePrice is not null || row.Price is not null || row.OldPrice is not null;
 100}