< Summary

Information
Class: OzonOrdersWeb.Areas.Studio2.ViewModels.SupplierCart.SupplierCartRow
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/ViewModels/SupplierCart/SupplierCartSection.cs
Line coverage
81%
Covered lines: 27
Uncovered lines: 6
Coverable lines: 33
Total lines: 179
Line coverage: 81.8%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/ViewModels/SupplierCart/SupplierCartSection.cs

#LineLine coverage
 1using Services.ApiServices.AvdApi;
 2using OzonDomains.Models;
 3
 4namespace OzonOrdersWeb.Areas.Studio2.ViewModels.SupplierCart;
 5
 6public sealed record class SupplierCartSection
 7{
 8    public string ProviderKey { get; init; } = string.Empty;
 9    public string DisplayName { get; init; } = string.Empty;
 10    public string LogoUrl { get; init; } = string.Empty;
 11    public string CurrencyCode { get; init; } = "RUB";
 12    public IReadOnlyList<SupplierCartRow> Rows { get; init; } = Array.Empty<SupplierCartRow>();
 13    public IReadOnlyList<AvdOrder> Orders { get; init; } = Array.Empty<AvdOrder>();
 14    public IReadOnlyList<ArmtekOrder> ArmtekOrders { get; init; } = Array.Empty<ArmtekOrder>();
 15    public IReadOnlyList<ArmtekApiOrderRow> ArmtekApiOrders { get; init; } = Array.Empty<ArmtekApiOrderRow>();
 16    public IReadOnlyList<MlAutoOrder> MlAutoOrders { get; init; } = Array.Empty<MlAutoOrder>();
 17    public IReadOnlyList<MlAutoApiOrderRow> MlAutoApiOrders { get; init; } = Array.Empty<MlAutoApiOrderRow>();
 18    public IReadOnlyList<ForumAutoOrder> ForumAutoOrders { get; init; } = Array.Empty<ForumAutoOrder>();
 19    public IReadOnlyList<ForumAutoApiOrderRow> ForumAutoApiOrders { get; init; } = Array.Empty<ForumAutoApiOrderRow>();
 20    public IReadOnlyList<FavoritPartsApiOrderRow> FavoritPartsApiOrders { get; init; } = Array.Empty<FavoritPartsApiOrde
 21    public IReadOnlyList<MoskvorechieIstraApiOrderRow> MoskvorechieIstraOrders { get; init; } = Array.Empty<Moskvorechie
 22    public IReadOnlyList<MotexApiOrderRow> MotexOrders { get; init; } = Array.Empty<MotexApiOrderRow>();
 23    public IReadOnlyList<ShateMApiOrderRow> ShateMOrders { get; init; } = Array.Empty<ShateMApiOrderRow>();
 24    public IReadOnlyList<ProfitLigaApiOrderRow> ProfitLigaOrders { get; init; } = Array.Empty<ProfitLigaApiOrderRow>();
 25    public IReadOnlyList<NikeiApiOrderRow> NikeiOrders { get; init; } = Array.Empty<NikeiApiOrderRow>();
 26    public IReadOnlyList<JapartsApiOrderRow> JapartsOrders { get; init; } = Array.Empty<JapartsApiOrderRow>();
 27    public IReadOnlyList<BergApiOrderRow> BergOrders { get; init; } = Array.Empty<BergApiOrderRow>();
 28    public IReadOnlyList<ZZapApiOrderRow> ZZapOrders { get; init; } = Array.Empty<ZZapApiOrderRow>();
 29    /// <summary>Связанные заказы Studio2 по номеру оформленного заказа поставщика.</summary>
 30    public IReadOnlyDictionary<string, IReadOnlyList<SupplierCartStudioOrderLink>> StudioOrderLinksBySupplierOrder { get
 31        = new Dictionary<string, IReadOnlyList<SupplierCartStudioOrderLink>>(StringComparer.Ordinal);
 32    public IReadOnlyList<MlAutoDeliveryOption> MlAutoDeliveryOptions { get; init; } = Array.Empty<MlAutoDeliveryOption>(
 33    /// <summary>Пары «покупатель + адрес доставки» Armtek для выбора в строке корзины.</summary>
 34    public IReadOnlyList<ArmtekDeliveryOption> ArmtekDeliveryOptions { get; init; } = Array.Empty<ArmtekDeliveryOption>(
 35    public string? ArmtekDeliveryOptionsError { get; init; }
 36    public string? Error { get; init; }
 37    public string? OrdersError { get; init; }
 38
 39    public static SupplierCartSection Failed(string providerKey, string displayName, string logoUrl, string error) =>
 40        new() { ProviderKey = providerKey, DisplayName = displayName, LogoUrl = logoUrl, Error = error };
 41}
 42
 43public sealed record MlAutoDeliveryOption(string Id, string DisplayName);
 44
 45public sealed record SupplierCartStudioOrderLink(int OrderId, string? ShipmentNumber, string? ClientName);
 46public sealed record MoskvorechieIstraApiOrderRow(long Id, string? Number, DateTime CreatedAt, string Status, int ItemsC
 47public sealed record MotexApiOrderRow(long Id, string? ExternalId, string ClientOrderNum, string Status, DateTime Create
 48public sealed record JapartsApiOrderRow(string GlobalId, string OrderNumber, string Brand, string Article, string Produc
 49    decimal QuantityOrdered, decimal QuantityBought, decimal? QuantityArrived, decimal? QuantityShipped, decimal Price,
 50    string Status, string Country, DateTime? LastUpdated, string Comment);
 51/// <summary>Заказ Berg из ordering/states: статус живёт на строке, поэтому строки вложены.</summary>
 52public sealed record BergApiOrderRow(long Id, long? Reference, bool IsTest, DateTime? CreatedAt, DateTime? DispatchAt,
 53    string? ShipmentAddress, string? Comment, IReadOnlyList<BergApiOrderItemRow> Items)
 54{
 55    public decimal Amount => Items.Sum(x => (x.Price ?? 0m) * (x.Quantity ?? 0m));
 56
 57    /// <summary>Сводный статус шапки: пока строки в разных состояниях, показываем «смешанный».</summary>
 58    public string Status => Items.Select(x => x.StateName).Distinct().Count() == 1
 59        ? Items[0].StateName ?? string.Empty
 60        : "Разные статусы";
 61}
 62
 63public sealed record BergApiOrderItemRow(int Sequence, string? Article, string? Brand, string? Name,
 64    string? WarehouseName, decimal? Quantity, decimal? Price, int? StateId, string? StateName,
 65    DateTime? AssuredTime, string? Comment, int? StudioOrderId, string? StudioOrderNumber);
 66
 67public sealed record ShateMApiOrderRow(long Id, string? ExternalId, string Status, DateTime CreatedAt, int ItemsCount, d
 68
 69/// <summary>Заказ ZZap: одна позиция = один заказ у продавца (code_order). Статус — живой из GET /orders,
 70/// связь с заказом Studio2 — из зеркала ZZapCartItems по тому же code_order.</summary>
 71public sealed record ZZapApiOrderRow(long CodeOrder, DateTime? CreatedAt, string? Article, string? Brand, string? Produc
 72    string? SellerName, string? SellerPhone, decimal? Price, string? Quantity, int? StatusCode, string Status, string? M
 73    DateTime? StatusChangedAt, int? StudioOrderId, string? StudioOrderNumber, string? StudioClientName)
 74{
 75    /// <summary>Отменить из Studio2 можно только свой заказ и только пока продавец его не закрыл.</summary>
 76    public bool CanCancel => StudioOrderId.HasValue && StatusCode is not (11 or 153 or 10 or 142 or 169);
 77}
 78
 79/// <summary>Заказ Профит-Лиги: номер из orders[], состав и статусы позиций — из GET /orders/list.</summary>
 80public sealed record ProfitLigaApiOrderRow(long Id, string OrderNumber, string Status, DateTime CreatedAt,
 81    string? PointName, string? DeliveryDate, int ItemsCount, decimal Amount,
 82    IReadOnlyList<ProfitLigaApiOrderItemRow> Items);
 83
 84public sealed record ProfitLigaApiOrderItemRow(string Article, string Brand, string? ProductName,
 85    decimal Quantity, decimal? Price, string? Status, string? WarehouseName, string? ShowDate);
 86
 87public sealed record NikeiApiOrderRow(string Invoice, int? Id, string Article, string Brand, string? ProductName,
 88    decimal? Quantity, decimal? Price, string Status, string? ShippingName, string? ShippingAddress, DateTime? CreatedAt
 89    int? StudioOrderId, string? StudioOrderNumber);
 90
 91/// <summary>Заказ ML-Auto: шапка собирается из GetMyOrders, состав и статусы — из GetOrderByNumber.</summary>
 92public sealed record MlAutoApiOrderRow(
 93    string Number,
 94    DateTime? CreatedAt,
 95    string Status,
 96    string PaymentType,
 97    int ItemsCount,
 98    decimal Quantity,
 99    decimal? Amount,
 100    DateTime? DeliveryFrom,
 101    DateTime? DeliveryTo,
 102    string Comment,
 103    IReadOnlyList<MlAutoApiOrderItemRow> Items,
 104    string? DetailsError)
 105{
 106    public string DeliveryRange => DeliveryFrom is null
 107        ? "—"
 108        : DeliveryTo is null || DeliveryFrom.Value.Date == DeliveryTo.Value.Date
 109            ? DeliveryFrom.Value.ToString("dd.MM.yyyy")
 110            : $"{DeliveryFrom.Value:dd.MM.yyyy} — {DeliveryTo.Value:dd.MM.yyyy}";
 111
 112    public string SearchText => string.Join(' ',
 113        new[] { Number, Comment, Status, PaymentType }
 114            .Concat(Items.Select(x => $"{x.Brand} {x.Pin} {x.Comment}")));
 115}
 116
 117public sealed record MlAutoApiOrderItemRow(
 118    string Pin,
 119    string Brand,
 120    decimal Quantity,
 121    decimal? Price,
 122    decimal? Sum,
 123    string Status,
 124    string StatusCode,
 125    DateTime? EstimatedDelivery,
 126    string Comment,
 127    bool Rejected);
 128
 129public sealed class SupplierCartRow
 130{
 9131    public long? LocalCartItemId { get; init; }
 17132    public string ApiItemId { get; init; } = string.Empty;
 22133    public string ApiCatalogName { get; init; } = string.Empty;
 20134    public string ApiItemName { get; init; } = string.Empty;
 22135    public string ApiItemNumber { get; init; } = string.Empty;
 20136    public decimal? ApiPrice { get; init; }
 12137    public decimal? ApiQuantity { get; init; }
 19138    public string ApiRegion { get; init; } = string.Empty;
 44139    public string ApiSupplierName { get; init; } = string.Empty;
 9140    public int? ApiPeriod { get; init; }
 17141    public string ApiComment { get; init; } = string.Empty;
 4142    public DateTime? AddedAt { get; init; }
 143
 10144    public int? StudioOrderId { get; init; }
 2145    public string? StudioOrderNumber { get; init; }
 10146    public string? StudioProductName { get; init; }
 9147    public string? StudioArticle { get; init; }
 9148    public string? StudioManufacturer { get; init; }
 11149    public string? StudioProductImageUrl { get; init; }
 1150    public string? StudioClientName { get; init; }
 151
 152    /// <summary>KUNRG/KUNZA, зафиксированные при добавлении в корзину; уходят в createOrder как есть.</summary>
 5153    public string? ArmtekBuyerKunnr { get; init; }
 4154    public string? ArmtekDeliveryAddressKunnr { get; init; }
 3155    public string? ArmtekDeliveryAddressName { get; init; }
 2156    public bool ArmtekDeliveryMappingLinked { get; init; }
 0157    public string? MlAutoDeliveryAddressId { get; init; }
 0158    public string? MlAutoDeliveryAddressName { get; init; }
 0159    public string? MlAutoShipmentWarehouseName { get; init; }
 160
 161    /// <summary>Торговая точка Профит-Лиги, в которую уйдёт заказ по этой строке.</summary>
 0162    public string? ProfitLigaPointName { get; init; }
 0163    public bool MlAutoDeliveryMappingLinked { get; init; }
 164
 165    /// <summary>ZZap: code_order позиции у поставщика и её живое состояние из GET /cart (null — API недоступен).</summa
 7166    public long? ZZapCodeOrder { get; init; }
 5167    public bool? ZZapInApiCart { get; init; }
 0168    public decimal? ZZapApiPrice { get; init; }
 1169    public string? ZZapApiDeliveryText { get; init; }
 170
 9171    public decimal? Sum => ApiPrice.HasValue && ApiQuantity.HasValue ? ApiPrice.Value * ApiQuantity.Value : null;
 172}
 173
 174/// <summary>Вариант доставки Armtek: покупатель <c>RG_TAB.KUNNR</c> и его адрес <c>ZA_TAB.KUNNR</c>.</summary>
 175public sealed record ArmtekDeliveryOption(string BuyerKunnr, string BuyerName, string AddressKunnr, string AddressName)
 176{
 177    public string Value => $"{BuyerKunnr}|{AddressKunnr}";
 178    public string DisplayName => $"{BuyerName} · {AddressName}";
 179}