| | | 1 | | using OzonDomains; |
| | | 2 | | using OzonDomains.Models; |
| | | 3 | | using OzonOrdersWeb.Areas.Studio2.Helpers; |
| | | 4 | | |
| | | 5 | | namespace OzonOrdersWeb.WebServices.Directories; |
| | | 6 | | |
| | | 7 | | /// <summary>Логотип API-поставщика в строке справочника.</summary> |
| | | 8 | | public sealed record ApiProviderBadge(string Key, string Name, string? LogoUrl, string? Tag, string Mark); |
| | | 9 | | |
| | | 10 | | /// <summary>Контрагент 1С, найденный по ИНН: <c>ok</c> — найден, <c>missing</c> — ИНН задан, но в 1С нет, <c>none</c> — |
| | | 11 | | public sealed record CounterpartyMatch(string State, string? Name, string? FullName) |
| | | 12 | | { |
| | | 13 | | public static readonly CounterpartyMatch None = new("none", null, null); |
| | | 14 | | } |
| | | 15 | | |
| | | 16 | | /// <summary>Строка грида поставщиков (Supplier/Index): поля для правки в ячейках и вычисленные признаки.</summary> |
| | 2 | 17 | | public sealed record SupplierGridRow( |
| | 4 | 18 | | int Id, |
| | 0 | 19 | | string? Name, |
| | 0 | 20 | | decimal? CostFactor, |
| | 1 | 21 | | string CurrencyCode, |
| | 0 | 22 | | decimal? WeightFactor, |
| | 1 | 23 | | string WeightFactorCurrencyCode, |
| | 0 | 24 | | string? CsvUrl, |
| | 0 | 25 | | string? Site, |
| | 0 | 26 | | int? AdditionalTerm, |
| | 1 | 27 | | int? ExpectedDeliveryHours, |
| | 0 | 28 | | string? InnCode, |
| | 0 | 29 | | bool IsVatApplicable, |
| | 0 | 30 | | bool IsReSeller, |
| | 2 | 31 | | CounterpartyMatch Counterparty, |
| | 4 | 32 | | IReadOnlyList<ApiProviderBadge> ApiProviders); |
| | | 33 | | |
| | | 34 | | /// <summary>Строка грида клиентов (OzonClients/Index). API Key в строку не попадает — только признак, что он задан.</su |
| | | 35 | | public sealed record OzonClientGridRow( |
| | | 36 | | int Id, |
| | | 37 | | string ClientType, |
| | | 38 | | string? Name, |
| | | 39 | | string? ClientId, |
| | | 40 | | bool HasApiKey, |
| | | 41 | | string CurrencyCode, |
| | | 42 | | string? InnCode, |
| | | 43 | | string? WarehouseName, |
| | | 44 | | CounterpartyMatch Owner); |
| | | 45 | | |
| | | 46 | | /// <summary>Связь склада Ozon со складом 1С в строке грида складов.</summary> |
| | | 47 | | public sealed record WarehouseMappingBadge(string? OzonWarehouseId, string? BitrixWarehouseName, string? ClientName, int |
| | | 48 | | |
| | | 49 | | /// <summary>Строка грида складов (Warehouse/Index): системный признак и связи из справочника маппинга по названию склад |
| | | 50 | | public sealed record WarehouseGridRow(int Id, string? Name, bool IsSystem, IReadOnlyList<WarehouseMappingBadge> Mappings |
| | | 51 | | |
| | | 52 | | /// <summary> |
| | | 53 | | /// Строки справочников для гридов AG Grid: то, что раньше считалось в Razor по строке (контрагент 1С по ИНН, |
| | | 54 | | /// логотипы API-поставщиков), считается здесь — по этим значениям грид сортирует и фильтрует. |
| | | 55 | | /// </summary> |
| | | 56 | | public static class DirectoryGridRows |
| | | 57 | | { |
| | | 58 | | public static CounterpartyMatch MatchCounterparty(string? inn, IReadOnlyDictionary<string, SupplierResponse> counter |
| | | 59 | | { |
| | | 60 | | if (string.IsNullOrWhiteSpace(inn)) return CounterpartyMatch.None; |
| | | 61 | | return counterpartiesByInn.TryGetValue(inn, out var found) |
| | | 62 | | ? new CounterpartyMatch("ok", found.Name ?? found.FullName, found.FullName) |
| | | 63 | | : new CounterpartyMatch("missing", null, null); |
| | | 64 | | } |
| | | 65 | | |
| | | 66 | | /// <summary>Индекс контрагентов 1С по ИНН (первый при дублях — как <c>FirstOrDefault</c> в старой разметке).</summa |
| | | 67 | | public static IReadOnlyDictionary<string, SupplierResponse> IndexByInn(IEnumerable<SupplierResponse>? counterparties |
| | | 68 | | { |
| | | 69 | | var index = new Dictionary<string, SupplierResponse>(StringComparer.Ordinal); |
| | | 70 | | foreach (var item in counterparties ?? []) |
| | | 71 | | { |
| | | 72 | | if (!string.IsNullOrEmpty(item.Unp)) index.TryAdd(item.Unp, item); |
| | | 73 | | } |
| | | 74 | | return index; |
| | | 75 | | } |
| | | 76 | | |
| | | 77 | | public static List<SupplierGridRow> BuildSuppliers( |
| | | 78 | | IEnumerable<Supplier> suppliers, |
| | | 79 | | IEnumerable<SupplierResponse>? counterparties, |
| | | 80 | | IReadOnlyDictionary<int, string[]> apiProvidersBySupplierId) |
| | | 81 | | { |
| | | 82 | | var byInn = IndexByInn(counterparties); |
| | | 83 | | return suppliers |
| | | 84 | | .Select(s => new SupplierGridRow( |
| | | 85 | | s.Id, |
| | | 86 | | s.Name, |
| | | 87 | | s.CostFactor, |
| | | 88 | | s.CurrencyCode.ToString(), |
| | | 89 | | s.WeightFactor, |
| | | 90 | | s.WeightFactorCurrencyCode.ToString(), |
| | | 91 | | s.CsvUrl, |
| | | 92 | | s.Site, |
| | | 93 | | s.AdditionalTerm, |
| | | 94 | | s.ExpectedDeliveryHours, |
| | | 95 | | s.INNCode, |
| | | 96 | | s.IsVatApplicable, |
| | | 97 | | s.IsReSeller, |
| | | 98 | | MatchCounterparty(s.INNCode, byInn), |
| | | 99 | | (apiProvidersBySupplierId.GetValueOrDefault(s.Id) ?? []) |
| | | 100 | | .Select(key => new ApiProviderBadge(key, ApiProviderBrand.Name(key), ApiProviderBrand.LogoUrl(key), |
| | | 101 | | ApiProviderBrand.DirectionTag(key), ApiProviderBrand.TextMark(key))) |
| | | 102 | | .ToList())) |
| | | 103 | | .ToList(); |
| | | 104 | | } |
| | | 105 | | |
| | | 106 | | public static List<OzonClientGridRow> BuildOzonClients(IEnumerable<OzonClient> clients, IEnumerable<SupplierResponse |
| | | 107 | | { |
| | | 108 | | var byInn = IndexByInn(counterparties); |
| | | 109 | | return clients |
| | | 110 | | .Select(c => new OzonClientGridRow( |
| | | 111 | | c.Id, |
| | | 112 | | c.ClientType switch { OzonDomains.ClientType.OZON => "Ozon", OzonDomains.ClientType.YANDEX => "Yandex", |
| | | 113 | | c.Name, |
| | | 114 | | c.DecryptClientId, |
| | | 115 | | !string.IsNullOrEmpty(c.ApiKey), |
| | | 116 | | c.CurrencyCode.ToString(), |
| | | 117 | | c.INNCode, |
| | | 118 | | c.WarehouseName, |
| | | 119 | | MatchCounterparty(c.INNCode, byInn))) |
| | | 120 | | .ToList(); |
| | | 121 | | } |
| | | 122 | | |
| | | 123 | | /// <summary>Системный склад «Не указан» — на него переводятся заказы удалённых складов, удалять его нельзя.</summar |
| | | 124 | | public const string SystemWarehouseName = "Не указан"; |
| | | 125 | | |
| | | 126 | | public static List<WarehouseGridRow> BuildWarehouses(IEnumerable<Warehouse> warehouses, IEnumerable<WarehouseMapping |
| | | 127 | | { |
| | | 128 | | var byOzonName = mappings |
| | | 129 | | .GroupBy(m => m.OzonWarehouseName) |
| | | 130 | | .ToDictionary(g => g.Key, g => g.ToList()); |
| | | 131 | | return warehouses |
| | | 132 | | .Select(w => new WarehouseGridRow( |
| | | 133 | | w.Id, |
| | | 134 | | w.Name, |
| | | 135 | | w.Name == SystemWarehouseName, |
| | | 136 | | (w.Name != null && byOzonName.TryGetValue(w.Name, out var list) ? list : []) |
| | | 137 | | .Select(m => new WarehouseMappingBadge(m.OzonWarehouseId, m.BitrixWarehouseName, m.OzonClient?.Name, |
| | | 138 | | .ToList())) |
| | | 139 | | .ToList(); |
| | | 140 | | } |
| | | 141 | | } |