| | | 1 | | using System.Text; |
| | | 2 | | using OzonDomains.Models; |
| | | 3 | | |
| | | 4 | | namespace Services.AiAssistant; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// Хронология заказа для развёрнутого ответа ассистента. |
| | | 8 | | /// </summary> |
| | | 9 | | public static class AiOrderTimelineFormatter |
| | | 10 | | { |
| | | 11 | | public static string Format(Order order, IReadOnlyList<OrderHistory> histories) |
| | | 12 | | { |
| | 23 | 13 | | var sb = new StringBuilder(); |
| | 23 | 14 | | sb.AppendLine("=== Хронология заказа (для развёрнутого ответа) ==="); |
| | 23 | 15 | | OrderRussianFieldFormatter.AppendKeyPartiesBlock(sb, order); |
| | 23 | 16 | | OrderRussianFieldFormatter.AppendOrderQuantityBlock(sb, order); |
| | | 17 | | |
| | 23 | 18 | | var events = new List<(DateTime When, string Text)>(); |
| | | 19 | | |
| | 23 | 20 | | if (order.ProcessingDate.HasValue) |
| | | 21 | | { |
| | 6 | 22 | | events.Add(( |
| | 6 | 23 | | order.ProcessingDate.Value, |
| | 6 | 24 | | $"Заказ принят в обработку (ProcessingDate), номер {order.ShipmentNumber}")); |
| | | 25 | | } |
| | | 26 | | |
| | 97 | 27 | | foreach (var h in histories.OrderBy(x => x.ChangedAt)) |
| | | 28 | | { |
| | 17 | 29 | | var field = !string.IsNullOrWhiteSpace(h.ColumnDisplayName) |
| | 17 | 30 | | ? h.ColumnDisplayName |
| | 17 | 31 | | : h.ColumnName ?? "поле"; |
| | 17 | 32 | | var who = string.IsNullOrWhiteSpace(h.ChangedBy) ? "система" : h.ChangedBy!.Trim(); |
| | 17 | 33 | | events.Add(( |
| | 17 | 34 | | h.ChangedAt, |
| | 17 | 35 | | $"{who} изменил «{field}»: «{h.FormattedOldValue}» → «{h.FormattedNewValue}»")); |
| | | 36 | | } |
| | | 37 | | |
| | 23 | 38 | | if (order.LastStatusChangeDate.HasValue && |
| | 31 | 39 | | !events.Any(e => e.Text.Contains("статус", StringComparison.OrdinalIgnoreCase))) |
| | | 40 | | { |
| | 3 | 41 | | events.Add(( |
| | 3 | 42 | | order.LastStatusChangeDate.Value, |
| | 3 | 43 | | $"Последнее изменение статуса (LastStatusChangeDate), AppStatus={order.AppStatus?.Name ?? "—"}, Ozon={or |
| | | 44 | | } |
| | | 45 | | |
| | 23 | 46 | | if (events.Count == 0) |
| | | 47 | | { |
| | 1 | 48 | | sb.AppendLine("Явных событий в orders_history нет. Опирайся на поля заказа и синхронизации."); |
| | 1 | 49 | | return sb.ToString().TrimEnd(); |
| | | 50 | | } |
| | | 51 | | |
| | 122 | 52 | | foreach (var (when, text) in events.OrderBy(e => e.When)) |
| | 26 | 53 | | sb.AppendLine($" {when:dd.MM.yyyy HH:mm} UTC — {text}"); |
| | | 54 | | |
| | 22 | 55 | | sb.AppendLine(); |
| | 22 | 56 | | sb.AppendLine("Текущий статус в отчёте: «" + (order.AppStatus?.Name ?? "Не указан") + "»"); |
| | 22 | 57 | | sb.AppendLine("Текущий статус Ozon: «" + (order.ClientStatus?.Name ?? "Не указан") + "»"); |
| | | 58 | | |
| | 22 | 59 | | return sb.ToString().TrimEnd(); |
| | | 60 | | } |
| | | 61 | | } |