< Summary

Information
Class: Services.ApiServices.ProfitLigaApi.ProfitLigaOrderStatus
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/ProfitLigaApi/ProfitLigaModels.cs
Line coverage
100%
Covered lines: 1
Uncovered lines: 0
Coverable lines: 1
Total lines: 122
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Id()100%11100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/ApiServices/ProfitLigaApi/ProfitLigaModels.cs

#LineLine coverage
 1using Newtonsoft.Json.Linq;
 2
 3namespace Services.ApiServices.ProfitLigaApi;
 4
 5/// <summary>Склад Профит-Лиги из GET /search/warehouses.</summary>
 6public sealed record ProfitLigaWarehouse(int Id, string Name, int DeliveryHours, bool Own, bool Active, string? Comment)
 7
 8/// <summary>Способ доставки из GET /cart/params.</summary>
 9public sealed record ProfitLigaDeliveryMethod(string Id, string Name);
 10
 11/// <summary>Торговая точка доставки либо точка самовывоза из GET /cart/params.</summary>
 12public sealed record ProfitLigaPoint(string Code, string Name, string? Address, bool IsPickup)
 13{
 14    public string DisplayName => string.IsNullOrWhiteSpace(Address) ? Name : $"{Name} — {Address}";
 15}
 16
 17/// <summary>Способ оплаты из GET /cart/params.</summary>
 18public sealed record ProfitLigaPaymentMethod(string Id, string Name);
 19
 20/// <summary>Статус заказа из GET /cart/params. Description приходит с HTML-разметкой.</summary>
 2321public sealed record ProfitLigaOrderStatus(string Id, string Name, string? Description);
 22
 23/// <summary>Справочники оформления заказа: GET /cart/params.</summary>
 24public sealed record ProfitLigaOrderParams(
 25    IReadOnlyList<ProfitLigaDeliveryMethod> Methods,
 26    IReadOnlyList<ProfitLigaPoint> Points,
 27    IReadOnlyList<ProfitLigaPoint> PickupPoints,
 28    IReadOnlyList<ProfitLigaPaymentMethod> Payments,
 29    IReadOnlyList<ProfitLigaOrderStatus> Statuses)
 30{
 31    public static ProfitLigaOrderParams Empty { get; } = new([], [], [], [], []);
 32
 33    /// <summary>Точки доставки и самовывоза одним списком — так их выбирают в настройках и корзине.</summary>
 34    public IReadOnlyList<ProfitLigaPoint> AllPoints => [.. Points, .. PickupPoints];
 35}
 36
 37/// <summary>Строка реальной корзины поставщика (GET /cart/list).</summary>
 38public sealed record ProfitLigaCartLine(
 39    string ArticleId,
 40    string WarehouseId,
 41    string? ProductCode,
 42    string? Article,
 43    string? Brand,
 44    string? Description,
 45    string? WarehouseName,
 46    decimal Quantity,
 47    decimal? Price,
 48    string? ShowDate,
 49    string? Comment)
 50{
 51    /// <summary>Составной ключ строки: /cart/remove адресует позицию парой article_id + warehouse.</summary>
 52    public string Key => ProfitLigaJson.BuildCartKey(ArticleId, WarehouseId);
 53}
 54
 55/// <summary>Лояльный разбор JSON Профит-Лиги: типы в ответах плавают (числа приходят строками и наоборот),
 56/// а коллекции сериализуются то массивом, то объектом с ключами.</summary>
 57public static class ProfitLigaJson
 58{
 59    public static string BuildCartKey(string? articleId, string? warehouseId) =>
 60        $"{articleId?.Trim()}|{warehouseId?.Trim()}";
 61
 62    /// <summary>PHP-сериализация отдаёт пустую коллекцию массивом, а непустую — объектом.
 63    /// Обе формы разворачиваются в один список объектов.</summary>
 64    public static IEnumerable<JObject> Objects(JToken? token) => token switch
 65    {
 66        JArray array => array.OfType<JObject>(),
 67        JObject map => map.Properties().Select(x => x.Value).OfType<JObject>(),
 68        _ => []
 69    };
 70
 71    /// <summary>То же, но с сохранением ключа: у предложений ключ словаря — устойчивый хеш строки.</summary>
 72    public static IEnumerable<(string? Key, JObject Value)> KeyedObjects(JToken? token) => token switch
 73    {
 74        JArray array => array.OfType<JObject>().Select(x => ((string?)null, x)),
 75        JObject map => map.Properties()
 76            .Where(x => x.Value is JObject)
 77            .Select(x => ((string?)x.Name, (JObject)x.Value)),
 78        _ => []
 79    };
 80
 81    public static string? String(JObject source, string name)
 82    {
 83        var value = source[name];
 84        return value is null || value.Type is JTokenType.Null ? null : value.ToString().Trim();
 85    }
 86
 87    public static decimal? Decimal(JObject source, string name)
 88    {
 89        var value = source[name];
 90        return value?.Type switch
 91        {
 92            JTokenType.Integer or JTokenType.Float => value.Value<decimal>(),
 93            // Знак «не менее» («>10», «10>») в остатке отбрасываем: иначе позиция уходила в проценку с нулём.
 94            JTokenType.String => decimal.TryParse(value.Value<string>()?.Trim().Trim('>', '<', '~', '='),
 95                System.Globalization.NumberStyles.Any,
 96                System.Globalization.CultureInfo.InvariantCulture, out var parsed) ? parsed : null,
 97            _ => null
 98        };
 99    }
 100
 101    public static int? Int(JObject source, string name)
 102    {
 103        var parsed = Decimal(source, name);
 104        return parsed is null ? null : (int)Math.Round(parsed.Value, MidpointRounding.AwayFromZero);
 105    }
 106
 107    /// <summary>Флаги приходят и булевыми, и строками "0"/"1".</summary>
 108    public static bool Bool(JObject source, string name)
 109    {
 110        var value = source[name];
 111        return value?.Type switch
 112        {
 113            JTokenType.Boolean => value.Value<bool>(),
 114            JTokenType.Integer or JTokenType.Float => value.Value<decimal>() != 0m,
 115            JTokenType.String => value.Value<string>() is var text
 116                && !string.IsNullOrWhiteSpace(text)
 117                && !string.Equals(text, "0", StringComparison.Ordinal)
 118                && !string.Equals(text, "false", StringComparison.OrdinalIgnoreCase),
 119            _ => false
 120        };
 121    }
 122}

Methods/Properties

get_Id()