elfisa-pharmacy/src/ElectronicPharmacy/Classes/ConsigneeHelper.cs
Magomed d68155b8ef Persist per-pharmacy markup percent and simplify consignee picker UI.
Store client markup on each Consignee so it survives restarts and price refresh; show only name and address in the selection dialog with a wider window.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-30 14:53:28 +03:00

382 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Data.SQLite;
namespace Электроннаяармация.Classes
{
/// <summary>
/// Аптека = грузополучатель + LocationId. Прайс общий, заказы уходят с location_id выбранной аптеки.
/// </summary>
public static class ConsigneeHelper
{
public static string GetDefaultConsigneeName()
{
try
{
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"SELECT ConsigneesName
FROM Consignees
ORDER BY ConsigneesUseAsDefault DESC, ConsigneesName
LIMIT 1",
connection))
{
var result = command.ExecuteScalar();
return result == null || result == DBNull.Value
? string.Empty
: result.ToString().Trim();
}
}
}
catch
{
return string.Empty;
}
}
public static string GetLocationIdByName(string consigneeName)
{
if (string.IsNullOrWhiteSpace(consigneeName))
{
return string.Empty;
}
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"SELECT ifnull(LocationId, '')
FROM Consignees
WHERE ConsigneesName = @name
LIMIT 1",
connection))
{
command.Parameters.AddWithValue("@name", consigneeName.Trim());
var result = command.ExecuteScalar();
return result == null || result == DBNull.Value
? string.Empty
: result.ToString().Trim();
}
}
}
public static string ResolveLocationId(string consigneeName)
{
var fromConsignee = GetLocationIdByName(consigneeName);
if (!string.IsNullOrWhiteSpace(fromConsignee))
{
return fromConsignee;
}
return AppConfig.LocationId ?? string.Empty;
}
/// <summary>
/// Помечает аптеку активной и синхронизирует AppConfig.LocationId.
/// </summary>
public static void SetActiveConsignee(string consigneeName)
{
if (string.IsNullOrWhiteSpace(consigneeName))
{
return;
}
var name = consigneeName.Trim();
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var tx = connection.BeginTransaction())
{
using (var clear = new SQLiteCommand(
"UPDATE Consignees SET ConsigneesUseAsDefault = 0",
connection,
tx))
{
clear.ExecuteNonQuery();
}
using (var setDefault = new SQLiteCommand(
@"UPDATE Consignees
SET ConsigneesUseAsDefault = 1
WHERE ConsigneesName = @name",
connection,
tx))
{
setDefault.Parameters.AddWithValue("@name", name);
setDefault.ExecuteNonQuery();
}
tx.Commit();
}
var locationId = GetLocationIdByName(name);
if (!string.IsNullOrWhiteSpace(locationId))
{
AppConfig.SetLocationId(locationId);
}
}
}
public static void SetLocationId(string consigneeName, string locationId)
{
if (string.IsNullOrWhiteSpace(consigneeName))
{
return;
}
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"UPDATE Consignees
SET LocationId = @loc
WHERE ConsigneesName = @name",
connection))
{
command.Parameters.AddWithValue("@loc", (locationId ?? string.Empty).Trim());
command.Parameters.AddWithValue("@name", consigneeName.Trim());
command.ExecuteNonQuery();
}
}
}
public static void MigrateGlobalLocationIdIfNeeded(SQLiteConnection connection)
{
var global = AppConfig.LocationId;
if (string.IsNullOrWhiteSpace(global))
{
return;
}
using (var command = new SQLiteCommand(
@"UPDATE Consignees
SET LocationId = @loc
WHERE (LocationId IS NULL OR trim(LocationId) = '')
AND (
ConsigneesUseAsDefault = 1
OR (SELECT COUNT(*) FROM Consignees) = 1
)",
connection))
{
command.Parameters.AddWithValue("@loc", global.Trim());
command.ExecuteNonQuery();
}
}
public static void ApplyLocationIdToEmptyConsignees(string locationId)
{
if (string.IsNullOrWhiteSpace(locationId))
{
return;
}
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"UPDATE Consignees
SET LocationId = @loc
WHERE LocationId IS NULL OR trim(LocationId) = ''",
connection))
{
command.Parameters.AddWithValue("@loc", locationId.Trim());
command.ExecuteNonQuery();
}
}
}
public static IList<string> GetKnownSupplierIds()
{
var result = new List<string>();
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"SELECT DISTINCT trim(supplier_id)
FROM PriceList
WHERE supplier_id IS NOT NULL AND trim(supplier_id) <> ''
ORDER BY 1",
connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var id = reader.GetString(0);
if (!string.IsNullOrWhiteSpace(id))
{
result.Add(id);
}
}
}
}
return result;
}
/// <summary>
/// Процент наценки, который клиент задал вручную для аптеки.
/// null = ещё не сохраняли, брать fallback.
/// </summary>
public static decimal? GetClientMarkupPercent(string consigneeName)
{
if (string.IsNullOrWhiteSpace(consigneeName))
{
return null;
}
try
{
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"SELECT ClientMarkupPercent
FROM Consignees
WHERE ConsigneesName = @name
LIMIT 1",
connection))
{
command.Parameters.AddWithValue("@name", consigneeName.Trim());
var result = command.ExecuteScalar();
if (result == null || result == DBNull.Value)
{
return null;
}
if (result is decimal d)
{
return d;
}
if (decimal.TryParse(
Convert.ToString(result, System.Globalization.CultureInfo.InvariantCulture),
System.Globalization.NumberStyles.Any,
System.Globalization.CultureInfo.InvariantCulture,
out var parsed))
{
return parsed;
}
return null;
}
}
}
catch
{
return null;
}
}
/// <summary>
/// Сохраняет процент наценки клиента для конкретной аптеки.
/// Не сбрасывается при обновлении прайса.
/// </summary>
public static void SetClientMarkupPercent(string consigneeName, decimal markupPercent)
{
if (string.IsNullOrWhiteSpace(consigneeName))
{
return;
}
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"UPDATE Consignees
SET ClientMarkupPercent = @pct
WHERE ConsigneesName = @name",
connection))
{
command.Parameters.AddWithValue("@pct", markupPercent);
command.Parameters.AddWithValue("@name", consigneeName.Trim());
command.ExecuteNonQuery();
}
}
}
/// <summary>
/// Если у аптеки ещё нет сохранённого процента — записать стартовое значение с сервера.
/// Уже введённые клиентом значения не трогаем.
/// </summary>
public static void SeedClientMarkupPercentIfEmpty(decimal? serverMarkupPercent)
{
if (!serverMarkupPercent.HasValue)
{
return;
}
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var command = new SQLiteCommand(
@"UPDATE Consignees
SET ClientMarkupPercent = @pct
WHERE ClientMarkupPercent IS NULL",
connection))
{
command.Parameters.AddWithValue("@pct", serverMarkupPercent.Value);
command.ExecuteNonQuery();
}
}
}
/// <summary>
/// Синхронизирует поля заказа в `PriceList` (Zakaz/SummaZakaza) с корзиной выбранной аптеки.
/// Данные корзины хранятся в TempOrderItems с фильтром по ConsigneeName, а PriceList обновляется
/// только для текущего активного просмотра.
/// </summary>
public static void SyncCartToPriceList(string consigneeName)
{
var consignee = (consigneeName ?? string.Empty).Trim().Replace("'", "''");
using (var connection = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
connection.Open();
using (var tx = connection.BeginTransaction())
{
using (var clear = new SQLiteCommand(
@"UPDATE [PriceList]
SET [Zakaz] = NULL, [SummaZakaza] = NULL;", connection, tx))
{
clear.ExecuteNonQuery();
}
using (var sync = new SQLiteCommand(
@"UPDATE [PriceList]
SET
[Zakaz] = (
SELECT t.[Zakaz]
FROM [TempOrderItems] t
WHERE t.[ConsigneeName] = @consignee
AND t.[id_PriceList_Item] = [PriceList].[id_PriceList_Item]
LIMIT 1
),
[SummaZakaza] = (
SELECT t.[SummaZakaza]
FROM [TempOrderItems] t
WHERE t.[ConsigneeName] = @consignee
AND t.[id_PriceList_Item] = [PriceList].[id_PriceList_Item]
LIMIT 1
)
WHERE EXISTS (
SELECT 1
FROM [TempOrderItems] t
WHERE t.[ConsigneeName] = @consignee
AND t.[id_PriceList_Item] = [PriceList].[id_PriceList_Item]
);",
connection,
tx))
{
sync.Parameters.AddWithValue("@consignee", consignee);
sync.ExecuteNonQuery();
}
tx.Commit();
}
}
}
}
}