From cd2fb57bca246ad8fb7c587da23d77cd6cdd08ee Mon Sep 17 00:00:00 2001 From: Exest Date: Sat, 8 Aug 2026 11:54:43 +0300 Subject: [PATCH] =?UTF-8?q?Avalonia:=20=D1=87=D0=B5=D1=80=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=B8=D0=BA=D0=B8=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B0?= =?UTF-8?q?=D1=8E=D1=82=20=D1=80=D0=B5=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9?= =?UTF-8?q?=20=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=20EX-#######=20(=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=20=D0=B2=20WinForms)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - при «Сохранить заказ» резервируется настоящий номер через GET /api/buyer/global-sign/next (fallback ЧРН-… если офлайн) - при отправке черновика этот EX-номер передаётся в заказ (global_sign), заказ сохраняет тот же номер - ApiClient.NextGlobalSignAsync, BuyerOrderCreateRequest.GlobalSign - DraftStore: номер задаёт вызывающий Проверено: черновик = EX-0000018, статус «Не отправлен». Co-Authored-By: Claude Opus 4.8 --- .../ViewModels/OrdersViewModel.cs | 1 + .../ViewModels/PriceListViewModel.cs | 47 +++++++++++-------- src/Elfisa.Core/ApiClient.cs | 13 +++++ src/Elfisa.Core/DraftStore.cs | 4 +- src/Elfisa.Core/Dtos.cs | 1 + 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/Elfisa.Avalonia/ViewModels/OrdersViewModel.cs b/src/Elfisa.Avalonia/ViewModels/OrdersViewModel.cs index ca2320c..5c4435f 100644 --- a/src/Elfisa.Avalonia/ViewModels/OrdersViewModel.cs +++ b/src/Elfisa.Avalonia/ViewModels/OrdersViewModel.cs @@ -134,6 +134,7 @@ public partial class OrdersViewModel : ViewModelBase Busy = true; var req = new BuyerOrderCreateRequest { + GlobalSign = d.Number.StartsWith("EX-", StringComparison.OrdinalIgnoreCase) ? d.Number : null, LocationId = d.LocationId, Comment = d.Comment, Items = d.Items.Select(i => new BuyerOrderItemReq diff --git a/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs b/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs index 3dec96f..7c14ea7 100644 --- a/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs +++ b/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs @@ -88,28 +88,37 @@ public partial class PriceListViewModel : ViewModelBase private void RemoveFromCart(CartItem? item) => _cart.Remove(item!); [RelayCommand] - private void SaveDraft() + private async Task SaveDraftAsync() { if (_cart.Count == 0) { Status = "Заказ пуст — добавьте позиции."; return; } - - var draft = new DraftOrder + try { - LocationId = SelectedLocation?.BuyerLocationId, - LocationAddress = SelectedLocation?.Address, - Comment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(), - Items = _cart.Items.Select(c => new DraftItem + Busy = true; + // Резервируем настоящий номер заказа EX-####### (как в WinForms) + var sign = await _api.NextGlobalSignAsync(); + + var draft = new DraftOrder { - SupplierPriceId = c.Source.SupplierPriceId ?? "", - Name = c.Name, - Supplier = c.Supplier, - Barcode = c.Source.Barcode, - Price = c.Price, - Qty = c.Qty - }).ToList() - }; - var saved = DraftStore.Add(draft); - _cart.Clear(); - Comment = ""; - Status = $"Заказ сохранён как черновик {saved.Number} → раздел «Заказы» (не отправлен)."; + Number = string.IsNullOrWhiteSpace(sign) ? $"ЧРН-{DateTime.Now:HHmmss}" : sign!, + LocationId = SelectedLocation?.BuyerLocationId, + LocationAddress = SelectedLocation?.Address, + Comment = string.IsNullOrWhiteSpace(Comment) ? null : Comment.Trim(), + Items = _cart.Items.Select(c => new DraftItem + { + SupplierPriceId = c.Source.SupplierPriceId ?? "", + Name = c.Name, + Supplier = c.Supplier, + Barcode = c.Source.Barcode, + Price = c.Price, + Qty = c.Qty + }).ToList() + }; + DraftStore.Add(draft); + _cart.Clear(); + Comment = ""; + Status = $"Заказ сохранён: {draft.Number} → раздел «Заказы» (не отправлен)."; + } + catch (Exception ex) { Status = "Ошибка сохранения: " + ex.Message; } + finally { Busy = false; } } } diff --git a/src/Elfisa.Core/ApiClient.cs b/src/Elfisa.Core/ApiClient.cs index 5237428..ffdf340 100644 --- a/src/Elfisa.Core/ApiClient.cs +++ b/src/Elfisa.Core/ApiClient.cs @@ -129,6 +129,19 @@ public sealed class ApiClient return JsonSerializer.Deserialize(text, Json) ?? new BuyerOrderResponse(); } + /// Резервирует следующий номер заказа EX-####### (как в WinForms до создания заказа). + public async Task NextGlobalSignAsync() + { + EnsureAuth(); + var text = await AuthorizedGetAsync("/api/buyer/global-sign/next", "резервирование номера").ConfigureAwait(false); + try + { + using var doc = JsonDocument.Parse(text); + return doc.RootElement.TryGetProperty("global_sign", out var v) ? v.GetString() : null; + } + catch { return null; } + } + /// Адреса-грузополучатели покупателя. public async Task> GetBuyerLocationsAsync() { diff --git a/src/Elfisa.Core/DraftStore.cs b/src/Elfisa.Core/DraftStore.cs index 98e53d5..4ada41a 100644 --- a/src/Elfisa.Core/DraftStore.cs +++ b/src/Elfisa.Core/DraftStore.cs @@ -29,7 +29,7 @@ public sealed class DraftOrder /// Локальные черновики заказов (%APPDATA%\ElfisaAvalonia\drafts.json). public static class DraftStore { - private sealed class Box { public int Seq { get; set; } public List Drafts { get; set; } = new(); } + private sealed class Box { public List Drafts { get; set; } = new(); } private static readonly string Dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ElfisaAvalonia"); @@ -62,8 +62,6 @@ public static class DraftStore public static DraftOrder Add(DraftOrder draft) { - _box.Seq++; - draft.Number = $"ЧРН-{_box.Seq:0000}"; _box.Drafts.Insert(0, draft); Save(); return draft; diff --git a/src/Elfisa.Core/Dtos.cs b/src/Elfisa.Core/Dtos.cs index d09a197..6abb356 100644 --- a/src/Elfisa.Core/Dtos.cs +++ b/src/Elfisa.Core/Dtos.cs @@ -94,6 +94,7 @@ public sealed class BuyerOrderCreateRequest { [JsonPropertyName("location_id")] public string? LocationId { get; set; } [JsonPropertyName("comment")] public string? Comment { get; set; } + [JsonPropertyName("global_sign")] public string? GlobalSign { get; set; } [JsonPropertyName("items")] public List Items { get; set; } = new(); }