< Summary

Information
Class: Services.SupplierStatusServices.Providers.ZZapSupplierStatusProvider
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/SupplierStatusServices/Providers/ZZapSupplierStatusProvider.cs
Line coverage
100%
Covered lines: 49
Uncovered lines: 0
Coverable lines: 49
Total lines: 98
Line coverage: 100%
Branch coverage
100%
Covered branches: 32
Total branches: 32
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
get_ProviderKey()100%11100%
FetchCartAsync(...)100%11100%
FetchOrderAsync()100%2424100%
IsFinalTrackCode(...)100%22100%
ReadCodeOrder(...)100%66100%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/SupplierStatusServices/Providers/ZZapSupplierStatusProvider.cs

#LineLine coverage
 1using System.Globalization;
 2using Microsoft.EntityFrameworkCore;
 3using Newtonsoft.Json.Linq;
 4using OzonDomains.Models;
 5using OzonDomains.Models.SupplierStatuses;
 6using OzonRepositories.Context;
 7using Services.ApiServices.ZZapApi;
 8
 9namespace Services.SupplierStatusServices.Providers;
 10
 11/// <summary>
 12/// Статусы ZZap. Корзина — из зеркала ZZapCartItems (сверка с живой корзиной делается на странице корзины,
 13/// а не в джобе: ZZap не чаще одного запроса в 3 секунды). Заказ — GET /orders/{code_order}:
 14/// code_track/class_track из справочника /orders/status, конечные статусы закрывают отслеживание.
 15/// </summary>
 16public sealed class ZZapSupplierStatusProvider : ISupplierStatusProvider
 17{
 18    /// <summary>Конечные статусы ZZap: выполнен, получен, отменён покупателем/продавцом, архив.</summary>
 119    private static readonly HashSet<int> FinalTrackCodes = [11, 153, 10, 142, 169];
 20
 21    private readonly ApplicationDbContext _db;
 22    private readonly ZZapDataManager _api;
 23    private readonly LocalCartStatusReader _cartReader;
 24
 3425    public ZZapSupplierStatusProvider(ApplicationDbContext db, ZZapDataManager api, LocalCartStatusReader cartReader) =>
 3426        (_db, _api, _cartReader) = (db, api, cartReader);
 27
 3528    public string ProviderKey => ApiSupplierSettings.ZZapMoscowProviderKey;
 29
 30    public Task<IReadOnlyList<SupplierStatusSnapshot>> FetchCartAsync(IReadOnlyList<OrderSupplierStateRef> states, Cance
 431        _cartReader.ReadAsync(ProviderKey, states, ct);
 32
 33    public async Task<IReadOnlyList<SupplierStatusSnapshot>> FetchOrderAsync(IReadOnlyList<OrderSupplierStateRef> states
 34    {
 2935        var result = new List<SupplierStatusSnapshot>();
 5936        var orderIds = states.Select(x => x.OrderId).ToList();
 2937        var rows = await _db.ZZapCartItems
 2938            .Where(x => x.ProviderKey == ProviderKey && x.Status == ZZapCartItemStatus.Ordered && orderIds.Contains(x.St
 2939            .ToListAsync(ct);
 40
 11841        foreach (var state in states)
 42        {
 3043            var code = ReadCodeOrder(state);
 5644            var row = rows.Where(x => x.StudioOrderId == state.OrderId).OrderByDescending(x => x.OrderedAtUtc).FirstOrDe
 4045            if (code <= 0) code = row?.CodeOrder ?? 0;
 3046            if (code <= 0)
 47            {
 548                result.Add(new SupplierStatusSnapshot { OrderId = state.OrderId, Kind = SupplierStatusKind.Order, Status
 549                continue;
 50            }
 51
 52            try
 53            {
 2554                var order = (await _api.GetOrderAsync(code, ct))["result"] as JObject;
 2055                var trackCode = order?.Value<int?>("code_track");
 2056                var trackName = order?.Value<string>("class_track");
 2057                if (order is null || string.IsNullOrWhiteSpace(trackName))
 58                {
 559                    result.Add(new SupplierStatusSnapshot { OrderId = state.OrderId, Kind = SupplierStatusKind.Order, St
 560                    continue;
 61                }
 62
 1563                if (row is not null)
 64                {
 1065                    row.ExternalStatusCode = trackCode;
 1066                    row.ExternalStatusName = trackName.Length > 120 ? trackName[..120] : trackName;
 1067                    row.UpdatedAtUtc = DateTime.UtcNow;
 68                }
 69
 1570                result.Add(new SupplierStatusSnapshot
 1571                {
 1572                    OrderId = state.OrderId,
 1573                    Kind = SupplierStatusKind.Order,
 1574                    ExternalCode = trackCode?.ToString(CultureInfo.InvariantCulture),
 1575                    StatusName = trackName,
 1576                    ExternalOrderNumber = code.ToString(CultureInfo.InvariantCulture),
 1577                    ExternalOrderId = code.ToString(CultureInfo.InvariantCulture),
 1578                    QuantityConfirmed = decimal.TryParse(order.Value<string>("qty_order"), NumberStyles.Number, CultureI
 1579                    StatusChangedAt = order.Value<DateTime?>("create_track")
 1580                });
 1581            }
 582            catch (Exception ex) when (ex is ZZapApiException or HttpRequestException or TaskCanceledException)
 83            {
 584                result.Add(new SupplierStatusSnapshot { OrderId = state.OrderId, Kind = SupplierStatusKind.Order, Status
 585            }
 2086        }
 87
 2988        await _db.SaveChangesAsync(ct);
 2989        return result;
 2990    }
 91
 92    /// <summary>Конечен ли статус по коду ZZap — для сида справочника; резолвер сам IsFinal не ставит.</summary>
 2093    public static bool IsFinalTrackCode(int? code) => code.HasValue && FinalTrackCodes.Contains(code.Value);
 94
 95    private static long ReadCodeOrder(OrderSupplierStateRef state) =>
 3096        long.TryParse(state.ExternalOrderId ?? state.ExternalOrderNumber ?? state.ExternalBasketItemId, NumberStyles.Int
 3097            CultureInfo.InvariantCulture, out var id) ? id : 0;
 98}