| | | 1 | | using OzonDomains; |
| | | 2 | | using OzonOrdersWeb.WebServices.Orders.Grid; |
| | | 3 | | using OzonOrdersWeb.WebServices.Transactions.Grid.Definitions; |
| | | 4 | | using Services.ApiServices.OzonApi; |
| | | 5 | | |
| | | 6 | | namespace OzonOrdersWeb.WebServices.Transactions.Grid.Contracts; |
| | | 7 | | |
| | | 8 | | /// <summary>Ответ <c>POST /Studio2/TransactionsGrid/{slug}/Load</c>: строки, справочники и параметры страницы.</summary |
| | | 9 | | public sealed class TransactionGridPageDto |
| | | 10 | | { |
| | | 11 | | public required TransactionDefinitionDto Definition { get; init; } |
| | | 12 | | public List<TransactionGridRowDto> Rows { get; init; } = new(); |
| | | 13 | | public required TransactionGridLookups Lookups { get; init; } |
| | | 14 | | |
| | | 15 | | /// <summary>Предупреждения уровня страницы (смешанные поставщики/склады, недоступные заказы).</summary> |
| | | 16 | | public List<string> Warnings { get; init; } = new(); |
| | | 17 | | |
| | | 18 | | /// <summary>Заказы из ссылки, недоступные пользователю или не найденные.</summary> |
| | | 19 | | public List<int> SkippedIds { get; init; } = new(); |
| | | 20 | | |
| | | 21 | | /// <summary>Ключ сессии учёта времени — возвращается в Commit.</summary> |
| | | 22 | | public string? TrackingKey { get; init; } |
| | | 23 | | |
| | | 24 | | /// <summary>Пользователь — администратор (свободный выбор складов и т.п.).</summary> |
| | | 25 | | public bool IsAdmin { get; init; } |
| | | 26 | | } |
| | | 27 | | |
| | | 28 | | /// <summary>Строка грида: базовые колонки заказа (как в OrdersGrid) + редактируемая часть.</summary> |
| | | 29 | | public sealed class TransactionGridRowDto |
| | | 30 | | { |
| | | 31 | | public required OrderGridRowDto Base { get; init; } |
| | | 32 | | public required TransactionGridRowEdit Edit { get; init; } |
| | | 33 | | } |
| | | 34 | | |
| | | 35 | | /// <summary>Определение транзакции в виде, пригодном для клиента (без делегатов).</summary> |
| | | 36 | | public sealed class TransactionDefinitionDto |
| | | 37 | | { |
| | | 38 | | public int Type { get; init; } |
| | | 39 | | public string Slug { get; init; } = string.Empty; |
| | | 40 | | public string Title { get; init; } = string.Empty; |
| | | 41 | | public string? ShortName { get; init; } |
| | | 42 | | public string Icon { get; init; } = string.Empty; |
| | | 43 | | public string Color { get; init; } = string.Empty; |
| | | 44 | | public string Group { get; init; } = string.Empty; |
| | | 45 | | public string? Hint { get; init; } |
| | | 46 | | public string? TargetStatusName { get; init; } |
| | | 47 | | public int? TargetStatusId { get; init; } |
| | | 48 | | public IReadOnlyList<string> AllowedSourceStatuses { get; init; } = Array.Empty<string>(); |
| | | 49 | | public IReadOnlyList<string> StatusOnlyWhenAlreadyIn { get; init; } = Array.Empty<string>(); |
| | | 50 | | public string OneCMode { get; init; } = "none"; |
| | | 51 | | public string OneCDocument { get; init; } = "none"; |
| | | 52 | | public string WarehouseMode { get; init; } = "none"; |
| | | 53 | | public string ZeroQuantityPolicy { get; init; } = "none"; |
| | | 54 | | public bool CheckStockBefore1C { get; init; } |
| | | 55 | | public bool SupportsQuantitySplit { get; init; } |
| | | 56 | | public bool ClearPurchasePriceOnLoad { get; init; } |
| | | 57 | | public bool RequiresPurchasePrice { get; init; } |
| | | 58 | | public bool PurchasePriceOptional { get; init; } |
| | | 59 | | public bool AutoFillPurchasePriceFromC0 { get; init; } |
| | | 60 | | public bool OzonCancelPanel { get; init; } |
| | | 61 | | public bool OzonCancelPreselected { get; init; } |
| | | 62 | | public bool ProcessingGroupOpen { get; init; } |
| | | 63 | | public bool ShipInOzon { get; init; } |
| | | 64 | | public bool SupplierOffers { get; init; } |
| | | 65 | | public bool SupplierCarts { get; init; } |
| | | 66 | | public bool PriceEditingOnly { get; init; } |
| | | 67 | | public bool RequirePriorOneCGuid { get; init; } |
| | | 68 | | public bool RequireWsStock { get; init; } |
| | | 69 | | public bool SupportsBulkFromFile { get; init; } |
| | | 70 | | public bool ReceiptDocumentFields { get; init; } |
| | | 71 | | public bool ExpenseDocumentFields { get; init; } |
| | | 72 | | public bool CountryAndGtdFields { get; init; } |
| | | 73 | | public bool RequireSingleSupplierAndWarehouse { get; init; } |
| | | 74 | | public IReadOnlyList<string> EditableFields { get; init; } = Array.Empty<string>(); |
| | | 75 | | public string? DefaultsJson { get; init; } |
| | | 76 | | public string LegacyEndpoint { get; init; } = string.Empty; |
| | | 77 | | |
| | | 78 | | public static TransactionDefinitionDto From(TransactionDefinition d, int? targetStatusId) => new() |
| | | 79 | | { |
| | | 80 | | Type = (int)d.Type, |
| | | 81 | | Slug = d.Slug, |
| | | 82 | | Title = d.Title, |
| | | 83 | | ShortName = d.ShortName, |
| | | 84 | | Icon = d.Icon, |
| | | 85 | | Color = d.Color, |
| | | 86 | | Group = d.Group, |
| | | 87 | | Hint = d.Hint, |
| | | 88 | | TargetStatusName = d.TargetStatusName, |
| | | 89 | | TargetStatusId = targetStatusId, |
| | | 90 | | AllowedSourceStatuses = d.AllowedSourceStatuses, |
| | | 91 | | StatusOnlyWhenAlreadyIn = d.StatusOnlyWhenAlreadyIn, |
| | | 92 | | OneCMode = Camel(d.OneCMode), |
| | | 93 | | OneCDocument = Camel(d.OneCDocument), |
| | | 94 | | WarehouseMode = Camel(d.WarehouseMode), |
| | | 95 | | ZeroQuantityPolicy = Camel(d.ZeroQuantityPolicy), |
| | | 96 | | CheckStockBefore1C = d.CheckStockBefore1C, |
| | | 97 | | SupportsQuantitySplit = d.SupportsQuantitySplit, |
| | | 98 | | ClearPurchasePriceOnLoad = d.ClearPurchasePriceOnLoad, |
| | | 99 | | RequiresPurchasePrice = d.RequiresPurchasePrice, |
| | | 100 | | PurchasePriceOptional = d.PurchasePriceOptional, |
| | | 101 | | AutoFillPurchasePriceFromC0 = d.AutoFillPurchasePriceFromC0, |
| | | 102 | | OzonCancelPanel = d.OzonCancelPanel, |
| | | 103 | | OzonCancelPreselected = d.OzonCancelPreselected, |
| | | 104 | | ProcessingGroupOpen = d.ProcessingGroupOpen, |
| | | 105 | | ShipInOzon = d.ShipInOzon, |
| | | 106 | | SupplierOffers = d.SupplierOffers, |
| | | 107 | | SupplierCarts = d.SupplierCarts, |
| | | 108 | | PriceEditingOnly = d.PriceEditingOnly, |
| | | 109 | | RequirePriorOneCGuid = d.RequirePriorOneCGuid, |
| | | 110 | | RequireWsStock = d.RequireWsStock, |
| | | 111 | | SupportsBulkFromFile = d.SupportsBulkFromFile, |
| | | 112 | | ReceiptDocumentFields = d.ReceiptDocumentFields, |
| | | 113 | | ExpenseDocumentFields = d.ExpenseDocumentFields, |
| | | 114 | | CountryAndGtdFields = d.CountryAndGtdFields, |
| | | 115 | | RequireSingleSupplierAndWarehouse = d.RequireSingleSupplierAndWarehouse, |
| | | 116 | | EditableFields = d.EditableFields, |
| | | 117 | | DefaultsJson = d.DefaultsJson, |
| | | 118 | | LegacyEndpoint = d.LegacyEndpoint |
| | | 119 | | }; |
| | | 120 | | |
| | | 121 | | private static string Camel<T>(T value) where T : struct, Enum |
| | | 122 | | { |
| | | 123 | | var s = value.ToString(); |
| | | 124 | | return char.ToLowerInvariant(s[0]) + s[1..]; |
| | | 125 | | } |
| | | 126 | | } |
| | | 127 | | |
| | | 128 | | /// <summary>Справочники страницы; тяжёлые (склады 1С, договоры) грузятся лениво через <c>Lookups</c>.</summary> |
| | | 129 | | public sealed class TransactionGridLookups |
| | | 130 | | { |
| | 0 | 131 | | public List<StatusOption> Statuses { get; init; } = new(); |
| | 0 | 132 | | public List<SupplierOption> Suppliers { get; init; } = new(); |
| | 0 | 133 | | public List<IdName> Warehouses { get; init; } = new(); |
| | 0 | 134 | | public List<IdName> ExpenseTypes { get; init; } = new(); |
| | | 135 | | |
| | | 136 | | /// <summary>Значения засыла (названия складов 1С в скоупе пользователя).</summary> |
| | 0 | 137 | | public List<string> ZasylValues { get; init; } = new(); |
| | | 138 | | |
| | | 139 | | /// <summary>Причины отмены Ozon по заказу (только для клиентов OZON при OzonCancelPanel).</summary> |
| | 0 | 140 | | public Dictionary<int, OzonOrderCancelReasonsInfo> CancelReasonsByOrder { get; init; } = new(); |
| | | 141 | | |
| | | 142 | | /// <summary>providerKey → разрешённые склады (Id) для предложений API-поставщиков.</summary> |
| | 0 | 143 | | public Dictionary<string, List<int>> ApiSupplierAllowedWarehouses { get; init; } = new(); |
| | | 144 | | |
| | 0 | 145 | | public decimal RateUsd { get; init; } |
| | 0 | 146 | | public decimal RateEur { get; init; } |
| | 0 | 147 | | public decimal RateByn { get; init; } |
| | | 148 | | |
| | | 149 | | /// <summary>Склады 1С (для режимов GlobalPair/PerOrder*); пусто, если 1С не участвует.</summary> |
| | 0 | 150 | | public List<string> OneCWarehouses { get; init; } = new(); |
| | | 151 | | |
| | | 152 | | /// <summary>Подсказки складов по <c>WarehouseSelectionResolver</c> для режима GlobalPair.</summary> |
| | 0 | 153 | | public string? SuggestedSenderWarehouse { get; set; } |
| | 0 | 154 | | public List<string> SuggestedRecipientWarehouses { get; init; } = new(); |
| | 0 | 155 | | public bool ForceSenderWarehouse { get; init; } |
| | | 156 | | |
| | | 157 | | /// <summary>Страны происхождения из 1С (приходная накладная).</summary> |
| | 0 | 158 | | public List<string> Countries { get; init; } = new(); |
| | | 159 | | |
| | | 160 | | /// <summary>Договоры 1С по ИНН поставщика/клиента (приход/расход); ключ — Ref_Key.</summary> |
| | 0 | 161 | | public List<IdName<string>> Treaties { get; init; } = new(); |
| | 0 | 162 | | public string? TreatiesInn { get; init; } |
| | | 163 | | } |
| | | 164 | | |
| | | 165 | | public sealed record StatusOption(int Id, string Name, string Color, bool IsFinal); |
| | | 166 | | |
| | | 167 | | public sealed record SupplierOption(int Id, string Name, string? Site, CurrencyCode CurrencyCode, decimal? WeightFactor, |
| | | 168 | | |
| | | 169 | | public sealed record IdName(int Id, string Name); |
| | | 170 | | |
| | | 171 | | public sealed record IdName<TId>(TId Id, string Name); |