| | | 1 | | using Services.ApiServices.OpenRouterApi.Models; |
| | | 2 | | |
| | | 3 | | namespace Services.AiAssistant; |
| | | 4 | | |
| | | 5 | | public sealed class AiChatEnrichmentDto |
| | | 6 | | { |
| | | 7 | | public string? ProductImageUrl { get; set; } |
| | | 8 | | public string? ProductName { get; set; } |
| | | 9 | | public string? Article { get; set; } |
| | | 10 | | public AiBitrixSyncUiDto? BitrixSync { get; set; } |
| | | 11 | | public AiWarehouseStockUiDto? StockTable { get; set; } |
| | | 12 | | public AiMovementMapUiDto? MovementMap { get; set; } |
| | | 13 | | public AiOzonLiveUiDto? OzonLive { get; set; } |
| | | 14 | | } |
| | | 15 | | |
| | | 16 | | // ── Ozon Live (Seller API) ──────────────────────────────────────────────────── |
| | | 17 | | |
| | | 18 | | public sealed class AiOzonLiveUiDto |
| | | 19 | | { |
| | | 20 | | public string Article { get; set; } = string.Empty; |
| | | 21 | | public string? CheckedAtMsk { get; set; } |
| | | 22 | | public List<AiOzonLiveClientUiDto> Clients { get; set; } = []; |
| | | 23 | | } |
| | | 24 | | |
| | | 25 | | public sealed class AiOzonLiveClientUiDto |
| | | 26 | | { |
| | | 27 | | public string ClientName { get; set; } = string.Empty; |
| | | 28 | | public bool Found { get; set; } |
| | | 29 | | public string? OfferId { get; set; } |
| | | 30 | | public string? ProductName { get; set; } |
| | | 31 | | public long? ProductId { get; set; } |
| | | 32 | | public bool IsArchived { get; set; } |
| | | 33 | | public string? ImageUrl { get; set; } |
| | | 34 | | public string? Description { get; set; } |
| | | 35 | | public string? CategoryName { get; set; } |
| | | 36 | | public List<AiOzonStockRowUiDto> Stocks { get; set; } = []; |
| | | 37 | | public AiOzonPriceUiDto? Price { get; set; } |
| | | 38 | | } |
| | | 39 | | |
| | | 40 | | public sealed class AiOzonStockRowUiDto |
| | | 41 | | { |
| | | 42 | | public string WarehouseType { get; set; } = string.Empty; |
| | | 43 | | /// <summary>Название конкретного склада FBS (из stocks-by-warehouse/fbs). Null = агрегированный тип.</summary> |
| | | 44 | | public string? WarehouseName { get; set; } |
| | | 45 | | public int Present { get; set; } |
| | | 46 | | public int Reserved { get; set; } |
| | | 47 | | } |
| | | 48 | | |
| | | 49 | | public sealed class AiOzonPriceUiDto |
| | | 50 | | { |
| | 0 | 51 | | public decimal Price { get; set; } |
| | 0 | 52 | | public decimal? OldPrice { get; set; } |
| | 0 | 53 | | public decimal? MarketingPrice { get; set; } |
| | 0 | 54 | | public decimal? MinPrice { get; set; } |
| | 0 | 55 | | public AiPriceIndexUiDto? PriceIndex { get; set; } |
| | | 56 | | } |
| | | 57 | | |
| | | 58 | | public sealed class AiBitrixSyncUiDto |
| | | 59 | | { |
| | | 60 | | public string Article { get; set; } = string.Empty; |
| | | 61 | | public int TotalReportCount { get; set; } |
| | | 62 | | public List<AiBitrixSyncReportUiDto> Reports { get; set; } = []; |
| | | 63 | | } |
| | | 64 | | |
| | | 65 | | public sealed class AiBitrixSyncReportUiDto |
| | | 66 | | { |
| | | 67 | | public string ReportIdShort { get; set; } = string.Empty; |
| | | 68 | | public string GeneratedAtMsk { get; set; } = string.Empty; |
| | | 69 | | public string ClientName { get; set; } = string.Empty; |
| | | 70 | | public List<AiBitrixSyncRowUiDto> Rows { get; set; } = []; |
| | | 71 | | } |
| | | 72 | | |
| | | 73 | | public sealed class AiBitrixSyncRowUiDto |
| | | 74 | | { |
| | | 75 | | public string OneCStore { get; set; } = string.Empty; |
| | | 76 | | public string OzonWarehouse { get; set; } = string.Empty; |
| | | 77 | | public int OneCQty { get; set; } |
| | | 78 | | public int OzonQty { get; set; } |
| | | 79 | | public int? TargetQty { get; set; } |
| | | 80 | | public int? OzonQtyAfter { get; set; } |
| | | 81 | | public string DeltaItog { get; set; } = string.Empty; |
| | | 82 | | public string DeltaItogTone { get; set; } = "muted"; |
| | | 83 | | public string ActionLabel { get; set; } = string.Empty; |
| | | 84 | | public string ActionIcon { get; set; } = string.Empty; |
| | | 85 | | public string ApplyStatus { get; set; } = string.Empty; |
| | | 86 | | public string ApplyTone { get; set; } = "muted"; |
| | | 87 | | public decimal? OneCPrice { get; set; } |
| | | 88 | | public string DeltaC0 { get; set; } = string.Empty; |
| | | 89 | | public string DeltaC0Tone { get; set; } = "muted"; |
| | | 90 | | public decimal? OzonPrice { get; set; } |
| | | 91 | | public decimal? SellingPrice { get; set; } |
| | | 92 | | public AiPriceIndexUiDto? PriceIndex { get; set; } |
| | | 93 | | public AiPricePushUiDto? PricePush { get; set; } |
| | | 94 | | } |
| | | 95 | | |
| | | 96 | | public sealed class AiPriceIndexUiDto |
| | | 97 | | { |
| | | 98 | | public string Key { get; set; } = string.Empty; |
| | | 99 | | public string Label { get; set; } = string.Empty; |
| | | 100 | | public string Bg { get; set; } = "#E9ECEF"; |
| | | 101 | | public string Fg { get; set; } = "#6C757D"; |
| | | 102 | | } |
| | | 103 | | |
| | | 104 | | public sealed class AiPricePushUiDto |
| | | 105 | | { |
| | | 106 | | public decimal? OldPrice { get; set; } |
| | | 107 | | public decimal? NewPrice { get; set; } |
| | | 108 | | public string? Status { get; set; } |
| | | 109 | | public string Tone { get; set; } = "muted"; |
| | | 110 | | public AiPriceIndexUiDto? IndexBefore { get; set; } |
| | | 111 | | public AiPriceIndexUiDto? IndexAfter { get; set; } |
| | | 112 | | public decimal? MarkupPct { get; set; } |
| | | 113 | | public string? PushedAtMsk { get; set; } |
| | | 114 | | } |
| | | 115 | | |
| | | 116 | | public sealed class AiWarehouseStockUiDto |
| | | 117 | | { |
| | | 118 | | public string Article { get; set; } = string.Empty; |
| | | 119 | | public List<AiWarehouseStockRowUiDto> Rows { get; set; } = []; |
| | | 120 | | } |
| | | 121 | | |
| | | 122 | | public sealed class AiWarehouseStockRowUiDto |
| | | 123 | | { |
| | | 124 | | public string Article { get; set; } = string.Empty; |
| | | 125 | | public string? Manufacturer { get; set; } |
| | | 126 | | public string? ProductName { get; set; } |
| | | 127 | | public decimal? M2Qty { get; set; } |
| | | 128 | | public decimal? M3Qty { get; set; } |
| | | 129 | | public decimal? B1Qty { get; set; } |
| | | 130 | | public decimal? B2Qty { get; set; } |
| | | 131 | | public decimal? C0 { get; set; } |
| | | 132 | | public string? SaleFlag { get; set; } |
| | | 133 | | public string? SyncedAtMsk { get; set; } |
| | | 134 | | } |
| | | 135 | | |
| | | 136 | | public sealed class AiMovementMapUiDto |
| | | 137 | | { |
| | | 138 | | public string Article { get; set; } = string.Empty; |
| | | 139 | | public string NomenclatureName { get; set; } = string.Empty; |
| | | 140 | | public List<AiMovementBalanceUiDto> Balances { get; set; } = []; |
| | | 141 | | public List<AiMovementItemUiDto> Items { get; set; } = []; |
| | | 142 | | } |
| | | 143 | | |
| | | 144 | | public sealed class AiMovementBalanceUiDto |
| | | 145 | | { |
| | | 146 | | public string Warehouse { get; set; } = string.Empty; |
| | | 147 | | public decimal Quantity { get; set; } |
| | | 148 | | } |
| | | 149 | | |
| | | 150 | | public sealed class AiMovementItemUiDto |
| | | 151 | | { |
| | | 152 | | public string DateMsk { get; set; } = string.Empty; |
| | | 153 | | public string Kind { get; set; } = string.Empty; |
| | | 154 | | public string DocType { get; set; } = string.Empty; |
| | | 155 | | public string DocNumber { get; set; } = string.Empty; |
| | | 156 | | public decimal Quantity { get; set; } |
| | | 157 | | public decimal Price { get; set; } |
| | | 158 | | public string? WarehouseFrom { get; set; } |
| | | 159 | | public string? WarehouseTo { get; set; } |
| | | 160 | | } |
| | | 161 | | |
| | | 162 | | public sealed class AiQueryResult |
| | | 163 | | { |
| | | 164 | | public string Context { get; init; } = string.Empty; |
| | | 165 | | public List<OrderSummaryDto> Orders { get; init; } = []; |
| | | 166 | | public AiChatEnrichmentDto? Enrichment { get; init; } |
| | | 167 | | /// <summary>EF Core SQL (ToQueryString) для отображения в UI.</summary> |
| | | 168 | | public string? SqlQuery { get; init; } |
| | | 169 | | /// <summary>Структурированные данные Ozon Live API для enrichment-панели.</summary> |
| | | 170 | | public AiOzonLiveUiDto? OzonLiveUi { get; init; } |
| | | 171 | | /// <summary>Предложение write-действия для карточки подтверждения в UI.</summary> |
| | | 172 | | public Services.ApiServices.OpenRouterApi.Models.AiActionProposalDto? ActionProposal { get; init; } |
| | | 173 | | /// <summary>Несколько предложений (batch) — несколько заказов в одном запросе.</summary> |
| | | 174 | | public List<Services.ApiServices.OpenRouterApi.Models.AiActionProposalDto>? ActionProposals { get; init; } |
| | | 175 | | /// <summary>true → запрос выполнен инструментом orders_filter, показывать стилизованную search-карточку.</summary> |
| | | 176 | | public bool IsSearchResult { get; init; } |
| | | 177 | | /// <summary>Описание применённых критериев фильтра на русском.</summary> |
| | | 178 | | public string? AppliedFiltersDescription { get; init; } |
| | | 179 | | /// <summary>Всего найдено записей (до лимита).</summary> |
| | | 180 | | public int? TotalFound { get; init; } |
| | | 181 | | /// <summary>Критерии поиска — для кнопки "Открыть в таблице" с предзаполненными фильтрами.</summary> |
| | | 182 | | public AiOrderFilterCriteria? AppliedCriteria { get; init; } |
| | | 183 | | /// <summary>Ослабленные критерии при 0 результатах основного поиска.</summary> |
| | | 184 | | public AiOrderFilterCriteria? RelaxedSuggestion { get; init; } |
| | | 185 | | public int? RelaxedCount { get; init; } |
| | | 186 | | public string? SuggestionQuery { get; init; } |
| | | 187 | | /// <summary>Текст спецификации из студии запроса (склад / клиент / период).</summary> |
| | | 188 | | public string? FilterSpecification { get; init; } |
| | | 189 | | } |