diff --git a/installer/ElfisaPharmacy.iss b/installer/ElfisaPharmacy.iss
index 2b1a93b..01b9edb 100644
--- a/installer/ElfisaPharmacy.iss
+++ b/installer/ElfisaPharmacy.iss
@@ -3,7 +3,7 @@
#define MyAppName "Электронная Фармация"
#define MyAppBrand "ЭльФиСА"
-#define MyAppVersion "2.0.0"
+#define MyAppVersion "2.0.1"
#define MyAppPublisher "PharmData"
#define MyAppURL "https://cdn.24pharmdata.ru"
#define MyAppSupportURL "https://24pharmdata.ru"
diff --git a/src/Elfisa.Avalonia/Elfisa.Avalonia.csproj b/src/Elfisa.Avalonia/Elfisa.Avalonia.csproj
index 12a6401..5c3ec40 100644
--- a/src/Elfisa.Avalonia/Elfisa.Avalonia.csproj
+++ b/src/Elfisa.Avalonia/Elfisa.Avalonia.csproj
@@ -5,9 +5,9 @@
enable
app.manifest
true
- 2.0.0
- 2.0.0.0
- 2.0.0.0
+ 2.0.1
+ 2.0.1.0
+ 2.0.1.0
ЭльФиСА — Электронная Фармация
PharmData
diff --git a/src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs b/src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs
index b8fd1e5..aa5f9c9 100644
--- a/src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs
+++ b/src/Elfisa.Avalonia/ViewModels/LoadPriceViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -8,15 +9,19 @@ using Elfisa.Core;
namespace Elfisa.Avalonia.ViewModels;
-/// «Загрузить» — скачивание актуального прайса с сервера в память.
+/// «Загрузить» — скачивание подключённых прайсов с сервера в память.
public partial class LoadPriceViewModel : ViewModelBase
{
private readonly ApiClient _api = new();
+ /// Прайсы, подключённые покупателю (какие именно скачиваем).
+ public ObservableCollection PriceLists { get; } = new();
+
[ObservableProperty] private bool _busy;
[ObservableProperty] private double _progress; // 0..100
[ObservableProperty] private string _progressText = "";
[ObservableProperty] private string? _result;
+ [ObservableProperty] private string _priceListsInfo = "Загрузка списка прайсов…";
public string LastLoaded =>
PriceCache.LoadedAt is { } dt
@@ -26,6 +31,23 @@ public partial class LoadPriceViewModel : ViewModelBase
public LoadPriceViewModel()
{
_api.SetToken(Session.Current.Token);
+ if (Session.Current.IsAuthenticated)
+ _ = LoadPriceListsAsync();
+ }
+
+ /// Тянет список подключённых прайсов — чтобы было видно, что именно скачиваем.
+ private async Task LoadPriceListsAsync()
+ {
+ try
+ {
+ var lists = await _api.GetBuyerPriceListsAsync();
+ PriceLists.Clear();
+ foreach (var pl in lists) PriceLists.Add(pl);
+ PriceListsInfo = lists.Count == 0
+ ? "Прайсы пока не подключены — обратитесь к менеджеру."
+ : $"Подключено прайсов: {lists.Count}";
+ }
+ catch { PriceListsInfo = "Не удалось получить список подключённых прайсов."; }
}
[RelayCommand]
diff --git a/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs b/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs
index 9f7fe96..5b1f018 100644
--- a/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs
+++ b/src/Elfisa.Avalonia/ViewModels/PriceListViewModel.cs
@@ -49,8 +49,11 @@ public partial class PriceListViewModel : ViewModelBase
public ObservableCollection Cart => _cart.Items;
public ObservableCollection Locations { get; } = new();
+ public ObservableCollection MyPriceLists { get; } = new();
[ObservableProperty] private string _search = "";
+ [ObservableProperty] private BuyerPriceListDto? _selectedPriceList;
+ [ObservableProperty] private bool _hasMultiplePriceLists;
[ObservableProperty] private string? _selectedBaseName;
[ObservableProperty] private string? _selectedMg;
[ObservableProperty] private OfferRow? _selectedOffer;
@@ -68,11 +71,39 @@ public partial class PriceListViewModel : ViewModelBase
Recalc();
if (Session.Current.IsAuthenticated)
{
- _ = SearchAsync();
+ _ = LoadPriceListsAsync(); // грузит «Мои прайсы» → ставит выбор → запускает поиск
_ = LoadLocationsAsync();
}
}
+ private bool _suppressPriceListSearch;
+
+ /// Загружает подключённые покупателю прайсы в дропдаун «Мои прайсы».
+ private async Task LoadPriceListsAsync()
+ {
+ List lists;
+ try { lists = await _api.GetBuyerPriceListsAsync(); }
+ catch { lists = new(); }
+
+ MyPriceLists.Clear();
+ MyPriceLists.Add(new BuyerPriceListDto { PriceListId = null, Name = "Все прайсы" });
+ foreach (var pl in lists) MyPriceLists.Add(pl);
+ HasMultiplePriceLists = lists.Count > 1;
+
+ _suppressPriceListSearch = true;
+ // Один подключён — выбираем его; несколько или ни одного — «Все прайсы».
+ SelectedPriceList = lists.Count == 1 ? MyPriceLists[1] : MyPriceLists[0];
+ _suppressPriceListSearch = false;
+
+ await SearchAsync();
+ }
+
+ partial void OnSelectedPriceListChanged(BuyerPriceListDto? value)
+ {
+ if (_suppressPriceListSearch) return;
+ _ = SearchAsync();
+ }
+
private void Recalc() => CartTotal = _cart.Total;
private async Task LoadLocationsAsync()
@@ -97,7 +128,7 @@ public partial class PriceListViewModel : ViewModelBase
try
{
Busy = true;
- var resp = await _api.GetPriceSummaryAsync(Search, limit: 300);
+ var resp = await _api.GetPriceSummaryAsync(Search, limit: 300, priceListId: SelectedPriceList?.PriceListId);
RebuildIndex(resp.Summary ?? new());
Total = resp.TotalDrugs;
}
diff --git a/src/Elfisa.Avalonia/Views/LoadPriceView.axaml b/src/Elfisa.Avalonia/Views/LoadPriceView.axaml
index 77737a0..e935150 100644
--- a/src/Elfisa.Avalonia/Views/LoadPriceView.axaml
+++ b/src/Elfisa.Avalonia/Views/LoadPriceView.axaml
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:Elfisa.Avalonia.ViewModels"
xmlns:conv="using:Avalonia.Data.Converters"
+ xmlns:core="using:Elfisa.Core"
x:Class="Elfisa.Avalonia.Views.LoadPriceView"
x:DataType="vm:LoadPriceViewModel">
@@ -20,6 +21,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Elfisa.Avalonia/Views/PriceListView.axaml b/src/Elfisa.Avalonia/Views/PriceListView.axaml
index 133f9dd..3245cf8 100644
--- a/src/Elfisa.Avalonia/Views/PriceListView.axaml
+++ b/src/Elfisa.Avalonia/Views/PriceListView.axaml
@@ -6,11 +6,20 @@
x:DataType="vm:PriceListViewModel">
-
-
+
+
+
+
+
+
+
+
+
Сводный прайс (то же, что грузит WinForms-десктоп). Поиск по q (от 2 символов).
- public async Task GetPriceSummaryAsync(string? q = null, int limit = 200, int offset = 0)
+ public async Task GetPriceSummaryAsync(string? q = null, int limit = 200, int offset = 0, string? priceListId = null)
{
EnsureAuth();
var path = $"/api/supplier-prices/summary?limit={limit}&offset={offset}";
if (!string.IsNullOrWhiteSpace(q) && q.Trim().Length >= 2)
path += "&q=" + Uri.EscapeDataString(q.Trim());
+ if (!string.IsNullOrWhiteSpace(priceListId))
+ path += "&price_list_id=" + Uri.EscapeDataString(priceListId);
var text = await AuthorizedGetAsync(path, "загрузку прайса").ConfigureAwait(false);
return JsonSerializer.Deserialize(text, Json) ?? new PriceSummaryResponse();
}
+ /// Прайс-листы, подключённые текущему покупателю (для выбора «Мои прайсы»).
+ public async Task> GetBuyerPriceListsAsync()
+ {
+ EnsureAuth();
+ var text = await AuthorizedGetAsync("/api/buyer/price-lists", "загрузку прайсов").ConfigureAwait(false);
+ try { return JsonSerializer.Deserialize>(text, Json) ?? new(); }
+ catch { return new(); }
+ }
+
/// Создаёт заказ (Placed). ВНИМАНИЕ: создаёт реальный заказ у поставщика.
public async Task CreateOrderAsync(BuyerOrderCreateRequest request)
{
diff --git a/src/Elfisa.Core/Dtos.cs b/src/Elfisa.Core/Dtos.cs
index 6abb356..aec5775 100644
--- a/src/Elfisa.Core/Dtos.cs
+++ b/src/Elfisa.Core/Dtos.cs
@@ -82,6 +82,19 @@ public sealed class BuyerLocationDto
public override string ToString() => Address ?? "";
}
+/// Подключённый покупателю прайс-лист («Мои прайсы»).
+public sealed class BuyerPriceListDto
+{
+ [JsonPropertyName("price_list_id")] public string? PriceListId { get; set; }
+ [JsonPropertyName("name")] public string? Name { get; set; }
+ [JsonPropertyName("supplier_name")] public string? SupplierName { get; set; }
+ [JsonPropertyName("markup_pct")] public double MarkupPct { get; set; }
+ [JsonPropertyName("default_markup_pct")] public double DefaultMarkupPct { get; set; }
+ public override string ToString() =>
+ string.IsNullOrWhiteSpace(SupplierName) ? (Name ?? "Прайс")
+ : $"{Name} · {SupplierName}";
+}
+
public sealed class BuyerOrderItemReq
{
[JsonPropertyName("supplier_price_id")] public string SupplierPriceId { get; set; } = "";