| | | 1 | | using Services.ApiServices.OpenRouterApi.Models; |
| | | 2 | | |
| | | 3 | | namespace Services.AiAssistant; |
| | | 4 | | |
| | | 5 | | /// <summary> |
| | | 6 | | /// Чипы для контекста «заказ». |
| | | 7 | | /// Синие (read) — история заказа, данные по заказу. |
| | | 8 | | /// Серые (nav) — открыть в таблице, архив. |
| | | 9 | | /// |
| | | 10 | | /// ПРАВИЛО: добавляй сюда новые read-действия для заказа. |
| | | 11 | | /// Каждый чип должен открывать данные, а не инициировать изменение. |
| | | 12 | | /// </summary> |
| | | 13 | | public sealed class AiOrderActionSuggestor : IAiActionSuggestor |
| | | 14 | | { |
| | 1 | 15 | | private static readonly HashSet<string> DetailTools = new(StringComparer.Ordinal) |
| | 1 | 16 | | { |
| | 1 | 17 | | "order_detail", "order_history", "order_product" |
| | 1 | 18 | | }; |
| | | 19 | | |
| | 1 | 20 | | private static readonly HashSet<string> PresetTools = new(StringComparer.Ordinal) |
| | 1 | 21 | | { |
| | 1 | 22 | | "orders_today", "cancelled_orders_today", "unprofitable_orders", "no_supplier_orders" |
| | 1 | 23 | | }; |
| | | 24 | | |
| | 1 | 25 | | private static readonly HashSet<string> HistoryNavTools = new(StringComparer.Ordinal) |
| | 1 | 26 | | { |
| | 1 | 27 | | "user_actions_today", "order_history_recent" |
| | 1 | 28 | | }; |
| | | 29 | | |
| | | 30 | | public IEnumerable<AiActionLinkDto> Suggest(AiSuggestionContext ctx) |
| | | 31 | | { |
| | 22 | 32 | | var toolName = ctx.ToolName ?? ""; |
| | 22 | 33 | | var orders = ctx.Orders; |
| | | 34 | | |
| | | 35 | | // Журнал изменений для истории-инструментов (без заказов в ответе) |
| | 22 | 36 | | if (HistoryNavTools.Contains(toolName)) |
| | | 37 | | { |
| | 2 | 38 | | yield return new AiActionLinkDto |
| | 2 | 39 | | { |
| | 2 | 40 | | Label = "Журнал изменений", |
| | 2 | 41 | | Url = "/OrderHistory/Index", |
| | 2 | 42 | | Kind = "orders", |
| | 2 | 43 | | IsNav = true |
| | 2 | 44 | | }; |
| | 2 | 45 | | yield break; |
| | | 46 | | } |
| | | 47 | | |
| | 21 | 48 | | if (orders.Count == 0) yield break; |
| | | 49 | | |
| | 19 | 50 | | var distinct = AiOrderAnalysisService.DeduplicateSummaries(orders); |
| | 52 | 51 | | var ids = string.Join(",", distinct.Select(o => o.Id)); |
| | 19 | 52 | | var usePreset = PresetTools.Contains(toolName); |
| | | 53 | | |
| | | 54 | | // ── Nav: открыть в таблице (серый) ────────────────────────────────── |
| | 19 | 55 | | yield return new AiActionLinkDto |
| | 19 | 56 | | { |
| | 19 | 57 | | Label = distinct.Count == 1 |
| | 19 | 58 | | ? "Открыть заказ в таблице" |
| | 19 | 59 | | : $"Открыть {distinct.Count} заказ(ов) в таблице", |
| | 19 | 60 | | Url = "/Orders/Index?page=1", |
| | 19 | 61 | | Kind = "orders", |
| | 19 | 62 | | FilterIds = usePreset ? null : ids, |
| | 19 | 63 | | FilterPreset = usePreset ? toolName : null, |
| | 19 | 64 | | IsNav = true |
| | 19 | 65 | | }; |
| | | 66 | | |
| | | 67 | | // ── Для одного заказа — history (read/синий) ───────────────────────── |
| | 19 | 68 | | if (distinct.Count == 1 && DetailTools.Contains(toolName)) |
| | | 69 | | { |
| | 4 | 70 | | yield return new AiActionLinkDto |
| | 4 | 71 | | { |
| | 4 | 72 | | Label = "История заказа", |
| | 4 | 73 | | Url = $"/OrderHistory/GetOrderHistory?orderId={distinct[0].Id}", |
| | 4 | 74 | | Kind = "history" |
| | 4 | 75 | | }; |
| | | 76 | | |
| | 4 | 77 | | if (distinct[0].IsArchived) |
| | | 78 | | { |
| | 1 | 79 | | yield return new AiActionLinkDto |
| | 1 | 80 | | { |
| | 1 | 81 | | Label = "Архив заказов", |
| | 1 | 82 | | Url = "/Studio2/OrderArchive", |
| | 1 | 83 | | Kind = "archive", |
| | 1 | 84 | | IsNav = true |
| | 1 | 85 | | }; |
| | | 86 | | } |
| | | 87 | | } |
| | | 88 | | |
| | | 89 | | // ── Открыть в таблице для прочих тулов ─────────────────────────────── |
| | 19 | 90 | | if (!usePreset && orders.Count > 0 && !DetailTools.Contains(toolName) && |
| | 19 | 91 | | toolName is not "orders_summary" and not "transaction_types_info" and not "orders_filter" |
| | 19 | 92 | | and not "ozon_live_product" and not "bitrix_stock_article" and not "") |
| | | 93 | | { |
| | 4 | 94 | | yield return new AiActionLinkDto |
| | 4 | 95 | | { |
| | 4 | 96 | | Label = "Открыть в таблице заказов", |
| | 4 | 97 | | Url = "/Orders/Index?page=1", |
| | 4 | 98 | | Kind = "orders", |
| | 4 | 99 | | FilterPreset = toolName, |
| | 4 | 100 | | IsNav = true |
| | 4 | 101 | | }; |
| | | 102 | | } |
| | 19 | 103 | | } |
| | | 104 | | } |