diff --git a/src/Elfisa.Avalonia/Styles/Elfisa.axaml b/src/Elfisa.Avalonia/Styles/Elfisa.axaml index a56e3e1..70529ab 100644 --- a/src/Elfisa.Avalonia/Styles/Elfisa.axaml +++ b/src/Elfisa.Avalonia/Styles/Elfisa.axaml @@ -123,8 +123,8 @@ diff --git a/src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs b/src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs new file mode 100644 index 0000000..b8fd1e5 --- /dev/null +++ b/src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using Elfisa.Core; + +namespace Elfisa.Avalonia.ViewModels; + +/// «Загрузить» — скачивание актуального прайса с сервера в память. +public partial class LoadPriceViewModel : ViewModelBase +{ + private readonly ApiClient _api = new(); + + [ObservableProperty] private bool _busy; + [ObservableProperty] private double _progress; // 0..100 + [ObservableProperty] private string _progressText = ""; + [ObservableProperty] private string? _result; + + public string LastLoaded => + PriceCache.LoadedAt is { } dt + ? $"Последняя загрузка: {dt:dd.MM.yyyy HH:mm} — {PriceCache.Items.Count} позиций" + : "Прайс ещё не загружался в этой сессии."; + + public LoadPriceViewModel() + { + _api.SetToken(Session.Current.Token); + } + + [RelayCommand] + private async Task LoadAsync() + { + Result = null; + try + { + Busy = true; + Progress = 0; + ProgressText = "Соединение с сервером…"; + + var all = new List(); + const int page = 500; + int offset = 0, total = 0; + + while (true) + { + var resp = await _api.GetPriceSummaryAsync(null, limit: page, offset: offset); + var batch = resp.Summary ?? new(); + if (resp.TotalDrugs > 0) total = resp.TotalDrugs; + all.AddRange(batch); + + Progress = total > 0 ? Math.Min(100.0, all.Count * 100.0 / total) : 0; + ProgressText = total > 0 + ? $"Загружено {all.Count} из {total} позиций…" + : $"Загружено {all.Count} позиций…"; + + offset += batch.Count; + if (batch.Count < page || (total > 0 && all.Count >= total) || offset > 30000) + break; + } + + PriceCache.Items = all; + PriceCache.LoadedAt = DateTime.Now; + Progress = 100; + ProgressText = "Готово."; + + var suppliers = all.Select(x => x.SupplierName).Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().Count(); + Result = $"Прайс загружен: {all.Count} позиций от {suppliers} поставщик(ов)."; + OnPropertyChanged(nameof(LastLoaded)); + } + catch (Exception ex) + { + Result = "Ошибка загрузки: " + ex.Message; + ProgressText = ""; + } + finally { Busy = false; } + } +} diff --git a/src/Elfisa.Avalonia/ViewModels/ShellViewModel.cs b/src/Elfisa.Avalonia/ViewModels/ShellViewModel.cs index 24b8851..060acba 100644 --- a/src/Elfisa.Avalonia/ViewModels/ShellViewModel.cs +++ b/src/Elfisa.Avalonia/ViewModels/ShellViewModel.cs @@ -46,6 +46,7 @@ public partial class ShellViewModel : ViewModelBase new("Заказы", "🛒", () => new OrdersViewModel()), new("Накладные", "📄", () => new InvoicesViewModel()), new("Отчёты", "📊", () => new ReportsViewModel()), + new("Загрузить", "📥", () => new LoadPriceViewModel()), new("Отправить", "📤", () => new SendOrderViewModel()), new("Отказы", "⛔", () => new PlaceholderPageViewModel("Отказы", "Отказные позиции по заказам. Нужен серверный эндпоинт: данные (RefuseItemsCount) сейчас есть только в локальной БД WinForms-клиента.")), diff --git a/src/Elfisa.Avalonia/Views/LoadPriceView.axaml b/src/Elfisa.Avalonia/Views/LoadPriceView.axaml new file mode 100644 index 0000000..77737a0 --- /dev/null +++ b/src/Elfisa.Avalonia/Views/LoadPriceView.axaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + +