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>
382 lines
14 KiB
C#
382 lines
14 KiB
C#
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();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|