elfisa-pharmacy/src/ElectronicPharmacy/Forms/FCheckDatabaseIntegrary.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

649 lines
26 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.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Электроннаяармация.Classes;
using System.IO;
using System.Data.SQLite;
namespace Электроннаяармация.Forms
{
public partial class FCheckDatabaseIntegrary : Form
{
public FCheckDatabaseIntegrary()
{
InitializeComponent();
}
string currentDirectoryPath = (System.IO.Directory.GetCurrentDirectory());
private void FCheckDatabaseIntegrary_Load(object sender, EventArgs e)
{
UiThemeHelper.ApplyToControlTree(this);
checkDatabaseWasExists();
checkTablesExists();
this.Close();
}
void checkDatabaseWasExists()
{
var dbPath = AppConfig.SqliteDbPath;
var dir = Path.GetDirectoryName(dbPath);
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
if (!File.Exists(dbPath))
{
SQLiteConnection.CreateFile(dbPath);
}
}
void checkTablesExists()
{
string connectionStringToLocalDB = AppConfig.SqliteConnectionString;
//MessageBox.Show(connectionStringToLocalDB);
using (SQLiteConnection conForCheckTables = new SQLiteConnection(connectionStringToLocalDB))
{
try
{
conForCheckTables.Open();
string strCheckExistsSuppliers = @"
create table if not exists [Suppliers] (
[idSuppliers] integer primary key AUTOINCREMENT not null,
[codeSuppliers] integer not null,
[SuppliersName] nvarchar(128) not null,
[SuppliersTelephone] nvarchar(64),
[SuppliersEmail] nvarchar(128),
[SuppliersAddress] nvarchar(256),
[MinimalSumOfOrder] real,
[OrdersPath] text
)
";
string strCheckExistsConsignees = @"
create table if not exists [Consignees] (
[idConsignees] integer primary key AUTOINCREMENT not null,
[codeConsignees] integer not null,
[ConsigneesName] nvarchar(128) not null,
[ConsigneesAddress] nvarchar(256) not null,
[ConsigneesUseAsDefault] int(1) not null,
[LocationId] nvarchar(64)
)
";
string strCheckExistsInvoices = @"
create table if not exists [Invoice] (
[idInvoice] integer primary key AUTOINCREMENT not null,
[InvoiceNumber] nvarchar(128) not null,
[InvoiceDate] integer not null,
[CodeSupplier] integer not null,
[CodeConsignees] integer not null,
[SumWithoutNDS] real,
[SumWithNDS] real,
[SumNDS] real
)
";
string strCheckExistsInvoiceItem = @"
create table if not exists [InvoiceItem] (
[idInvoiceItem] integer primary key AUTOINCREMENT not null,
[idGood] integer,
[GoodCode] integer not null,
[Good] nvarchar(256) not null,
[ProducerName] nvarchar(256),
[CountryName] nvarchar(256),
[idInvoice] interger not null,
[GoodsGount] integer not null,
[PriceSupplierWithoutNDS] real,
[PriceSupplierWithNDS] real,
[PriceProducerWithoutNDS] real,
[PriceProducerWithNDS] real,
[NDS] integer,
[JNVLS] int(1),
[PriceReestr] real,
[SumWithoutNDS] real,
[SumWithNDS] real,
[SumNDS] real,
[Serial] nvarchar(24),
[BestBefore] text,
[Sertificate] nvarchar(128),
[Marked] int(1) not null,
[GTIN] nvarchar(14)
)
";
string strCheckExistsTableGoods = @"
create table if not exists [Goods] (
[idGood] integer primary key AUTOINCREMENT not null,
[GoodCode] integer not null,
[GoodName] nvarchar(256) not null,
[idProducer] integer not null,
[JNVLS] int(1),
[CurrentReestrPrice] real,
[idGoodsGroup] integer,
[idGoodsShortNameForSearch] integer
)
";
string strCheckExistsTableProducers = @"
create table if not exists [Producers] (
[idProcuder] integer primary key AUTOINCREMENT not null,
[ProducerCode] integer not null,
[ProducerName] nvarchar(256) not null,
[idCountry] integer not null
)
";
string strCheckExistsTableCountries = @"
create table if not exists [Countries] (
[idCountry] integer primary key AUTOINCREMENT not null,
[CountryCode] integer not null,
[CountryName] nvarchar(256) not null
)
";
string strCheckExistsTableReestrPriceHistory = @"
create table if not exists [ReestrPriceHistoryForGoods] (
[idReestrPriceHistory] integer primary key AUTOINCREMENT not null,
[GoodCode] integer not null,
[ReestrPriceDateCreate] text not null,
[ReestrPrice] real not null,
[ReestrPricePeriodFrom] text,
[ReestrPricePeriodTo] text
)
";
string strCheckExistsTablePriceHistory = @"
create table if not exists [SuppliersPriceHistoryForGoods] (
[idSuppliersPriceHistoryForGoods] integer primary key AUTOINCREMENT not null,
[GoodsCode] integer not null,
[PriceDate] text not null,
[MinPriceForGood] real,
[AvgPriceForGood] real,
[MaxPriceForGood] real
)
";
string strCheckExistsTableGoodsGroup = @"
create table if not exists [GoodsGroup] (
[idGoodsGroup] integer primary key AUTOINCREMENT not null,
[GoodsGroupCode] integer not null,
[GoodsGroupName] nvarchar(256) not null
)
";
string strCheckExistsTableGoodsShortNameForSearch = @"
create table if not exists [GoodsShortNameForSearch] (
[idGoodsShortNameForSearch] integer primary key AUTOINCREMENT not null,
[GoodsShortNameForSearchCode] integer not null,
[GoodsShortNameForSearchCodeName] nvarchar(255) not null
)
";
string strCheckExistsTablePriceListFromSuppliers = @"
create table if not exists [PriceListFromSuppliers] (
[idPriceListSuppliers] integer primary key AUTOINCREMENT not null,
[ConsigneesCode] integer not null,
[CodeSuppliers] integer not null,
[PriceListDate] datetime
)
";
string strCheckExistsTablePriceList = @"
create table if not exists [PriceList] (
[guid_es] nvarchar(36) not null,
[es_code] integer not null,
[supplier_id] nvarchar(36) not null,
[DrugName] nvarchar(256) not null COLLATE NOCASE,
[SupplierName] nvarchar(256) not null,
[Price] nvarchar(32),
[Quantity] integer,
[ExpiryPeriod] nvarchar(64),
[Description] text,
[Zakaz] nvarchar(64),
[SummaZakaza] nvarchar(64),
[id_PriceList_Item] integer primary key AUTOINCREMENT not null,
[supplier_price_id] nvarchar(36)
)
";
#region Старая таблица Прайс-листа
// string strCheckExistsTablePriceList = @"
// create table if not exists [PriceList] (
// [idPriceListSupplier] integer not null,
// [ConsigneesCode] integer not null,
// [idPriceList] integer primary key AUTOINCREMENT not null,
// [GoodCode] integer,
// [GoodName] nvarchar(256) not null COLLATE NOCASE,
// [ProducerName] nvarchar(256),
// [SupplierName] nvarchar(256) not null,
// [BestBefore] text,
// [JNVLS] int(1),
// [PriceReestr] real,
// [AvaibleCount] integer not null,
// [PriceSupplierWithNDS] real not null,
// [CountIWantBuy] integer,
// [SumIWantBuy] real,
// [CountryName] nvarchar(256),
// [NDS] integer,
// [PriceProducer] real,
// [Marked] int(1)
// )
//";
#endregion
string strCheckExistsTableOrders = @"
create table if not exists [Orders] (
[Id_Order] integer primary key AUTOINCREMENT not null,
[OrderNumber] nvarchar(36) not null,
[OrderDate] nvarchar(10) not null,
[Id_Supplier] nvarchar(36) not null,
[SupplierName] nvarchar(256) not null,
[OrderedCountItems] integer,
[SummaZakaza] nvarchar(32),
[OrderState] nvarchar(32),
[Comment] nvarchar(1024),
[ConsigneeName] nvarchar(128),
[RemoteOrderId] nvarchar(36)
)
";
string strCheckExistsTableOrderItems = @"
create table if not exists [OrderItems] (
[Id_Order_Item] integer primary key AUTOINCREMENT not null,
[Id_Order] integer not null,
[guid_es] nvarchar(36),
[es_code] integer,
[DrugName] nvarchar(256) not null COLLATE NOCASE,
[Price] nvarchar(32),
[Zakaz] integer,
[SummaZakaza] nvarchar(32),
[ExpiryPeriod] nvarchar(64),
[RefuseItemsCount] integer,
[supplier_price_id] nvarchar(36)
)
";
#region старые таблицы Orders и OrderItem
// string strCheckExistsTableOrders = @"
// create table if not exists [Orders] (
// [idOrder] integer primary key AUTOINCREMENT not null,
// [OrderNumber] nvarchar(10) not null,
// [OrderDate] integer not null,
// [codeSuppliers] integer not null,
// [codeConsignees] integer not null,
// [OrderedItemsCount] integer not null,
// [OrderSum] real not null,
// [RefuseItemsCount] integer,
// [RefuseSum] real,
// [Comment] text,
// [OrderState] nvarchar(4)
// )
//";
// string strCheckExistsTableOrderItems = @"
// create table if not exists [OrderItems] (
// [idOrderItem] integer primary key AUTOINCREMENT not null,
// [idOrder] integer not null,
// [GoodCode] integer,
// [GoodName] nvarchar(256) not null,
// [OrderedCountItems] integer not null,
// [SupplierPrice] real not null,
// [SumOrderedItems] real not null,
// [RefuseItemsCount] integer,
// [BestBefore] text,
// [ProducerName] nvarchar(256)
// )
//";
#endregion
string strCheckExistsTableTempOrderItems = @"
create table if not exists [TempOrderItems] (
[ConsigneeName] nvarchar(128) not null,
[guid_es] nvarchar(36) not null,
[es_code] integer not null,
[supplier_id] nvarchar(36) not null,
[DrugName] nvarchar(256) not null COLLATE NOCASE,
[SupplierName] nvarchar(256) not null,
[Price] nvarchar(32),
[Quantity] integer,
[ExpiryPeriod] nvarchar(64),
[Description] text,
[Zakaz] real,
[SummaZakaza] nvarchar(64),
[id_PriceList_Item] integer not null,
[supplier_price_id] nvarchar(36),
primary key ([ConsigneeName], [id_PriceList_Item])
)
";
#region Старая временная таблица OrderItem
// string strCheckExistsTableTempOrderItems = @"
// create table if not exists [TempOrderItems] (
// [GoodCode] integer,
// [GoodName] nvarchar(256) not null collate nocase,
// [SupplierName] nvarchar(128) not null,
// [ConsigneesName] nvarchar(128) not null,
// [OrderedCountItems] integer not null,
// [SumOrderedItems] real not null,
// [SupplierPrice] real not null,
// [BestBefore] text
// )
//";
#endregion
SQLiteCommand cmdCreateNotExistingsTables = conForCheckTables.CreateCommand();
cmdCreateNotExistingsTables.CommandText = strCheckExistsSuppliers;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsConsignees;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsInvoices;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsInvoiceItem;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableGoods;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableGoods;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableProducers;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableCountries;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableReestrPriceHistory;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTablePriceHistory;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableGoodsGroup;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableGoodsShortNameForSearch;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTablePriceListFromSuppliers;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTablePriceList;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableOrders;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableOrderItems;
cmdCreateNotExistingsTables.ExecuteNonQuery();
cmdCreateNotExistingsTables.CommandText = strCheckExistsTableTempOrderItems;
cmdCreateNotExistingsTables.ExecuteNonQuery();
// Миграция TempOrderItems под раздельную корзину по аптекам.
// Проверяем наличие ConsigneeName и то, что id_PriceList_Item не является одинарным PK.
bool hasConsigneeName = false;
bool idPriceListItemIsSinglePk = false;
using (var infoCmd = new SQLiteCommand("PRAGMA table_info([TempOrderItems]);", conForCheckTables))
using (var infoReader = infoCmd.ExecuteReader())
{
while (infoReader.Read())
{
var colName = infoReader["name"]?.ToString();
var pk = 0;
try { pk = Convert.ToInt32(infoReader["pk"]); } catch { pk = 0; }
if (string.Equals(colName, "ConsigneeName", StringComparison.OrdinalIgnoreCase))
{
hasConsigneeName = true;
}
if (string.Equals(colName, "id_PriceList_Item", StringComparison.OrdinalIgnoreCase) && pk == 1)
{
idPriceListItemIsSinglePk = true;
}
}
}
if (!hasConsigneeName || idPriceListItemIsSinglePk)
{
string defaultConsignee;
using (var defCmd = new SQLiteCommand(
@"SELECT ifnull((SELECT ConsigneesName
FROM Consignees
WHERE ConsigneesUseAsDefault = 1
LIMIT 1), '')",
conForCheckTables))
{
defaultConsignee = defCmd.ExecuteScalar()?.ToString() ?? string.Empty;
}
using (var tx = conForCheckTables.BeginTransaction())
{
using (var cmd = new SQLiteCommand(conForCheckTables))
{
cmd.Transaction = tx;
cmd.CommandText = @"
CREATE TABLE IF NOT EXISTS [TempOrderItems_new] (
[ConsigneeName] nvarchar(128) not null,
[guid_es] nvarchar(36) not null,
[es_code] integer not null,
[supplier_id] nvarchar(36) not null,
[DrugName] nvarchar(256) not null COLLATE NOCASE,
[SupplierName] nvarchar(256) not null,
[Price] nvarchar(32),
[Quantity] integer,
[ExpiryPeriod] nvarchar(64),
[Description] text,
[Zakaz] real,
[SummaZakaza] nvarchar(64),
[id_PriceList_Item] integer not null,
[supplier_price_id] nvarchar(36),
primary key ([ConsigneeName], [id_PriceList_Item])
);";
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("@defaultConsignee", defaultConsignee.Trim());
cmd.CommandText = @"
INSERT INTO [TempOrderItems_new] (
[ConsigneeName],
[guid_es],
[es_code],
[supplier_id],
[DrugName],
[SupplierName],
[Price],
[Quantity],
[ExpiryPeriod],
[Description],
[Zakaz],
[SummaZakaza],
[id_PriceList_Item],
[supplier_price_id]
)
SELECT
@defaultConsignee,
[guid_es],
[es_code],
[supplier_id],
[DrugName],
[SupplierName],
[Price],
[Quantity],
[ExpiryPeriod],
[Description],
[Zakaz],
[SummaZakaza],
[id_PriceList_Item],
[supplier_price_id]
FROM [TempOrderItems];";
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
cmd.CommandText = @"DROP TABLE [TempOrderItems];";
cmd.ExecuteNonQuery();
cmd.CommandText = @"ALTER TABLE [TempOrderItems_new] RENAME TO [TempOrderItems];";
cmd.ExecuteNonQuery();
}
tx.Commit();
}
}
// Перед seed-вставкой грузополучателей нужно гарантировать наличие LocationId,
// иначе INSERT в Consignees (LocationId) упадёт на старых версиях БД.
TryAddColumn(conForCheckTables, "Consignees", "LocationId", "nvarchar(64)");
// Seed-тестовые грузополучатели (аптеки) для удобства ручного тестирования.
// Вставляем только если таблица пустая.
using (var countConsigneesCmd = new SQLiteCommand(
@"SELECT COUNT(*) FROM Consignees;",
conForCheckTables))
{
var countObj = countConsigneesCmd.ExecuteScalar();
var count = 0;
try { count = Convert.ToInt32(countObj); } catch { count = 0; }
if (count == 0)
{
var testLocationIds = new[]
{
"87368f6d-488b-41a9-b170-edc629522844",
"c4cd845f-820d-45ac-a473-3df1a0b96feb",
"d6187013-00f5-4c1b-b258-c670cf71d115"
};
// Тестовые имена/адреса — можно менять под вашу тестовую среду.
var testNames = new[]
{
"Тестовая аптека 1",
"Тестовая аптека 2",
"Тестовая аптека 3"
};
var testAddresses = new[]
{
"Тестовый адрес 1",
"Тестовый адрес 2",
"Тестовый адрес 3"
};
using (var tx = conForCheckTables.BeginTransaction())
{
int nextCode;
using (var nextCodeCmd = new SQLiteCommand(
@"SELECT ifnull(MAX(codeConsignees), 0) + 1 FROM Consignees;",
conForCheckTables,
tx))
{
nextCode = Convert.ToInt32(nextCodeCmd.ExecuteScalar());
}
for (var i = 0; i < 3; i++)
{
using (var insertCmd = new SQLiteCommand(
@"INSERT INTO Consignees
(codeConsignees, ConsigneesName, ConsigneesAddress, ConsigneesUseAsDefault, LocationId)
VALUES (@code, @name, @address, @isDefault, @loc);",
conForCheckTables,
tx))
{
insertCmd.Parameters.AddWithValue("@code", nextCode + i);
insertCmd.Parameters.AddWithValue("@name", testNames[i]);
insertCmd.Parameters.AddWithValue("@address", testAddresses[i]);
insertCmd.Parameters.AddWithValue("@isDefault", i == 0 ? 1 : 0);
insertCmd.Parameters.AddWithValue("@loc", testLocationIds[i]);
insertCmd.ExecuteNonQuery();
}
}
tx.Commit();
}
}
}
TryAddColumn(conForCheckTables, "Orders", "ConsigneeName", "nvarchar(128)");
TryAddColumn(conForCheckTables, "Invoice", "SupplierName", "nvarchar(256)");
TryAddColumn(conForCheckTables, "Invoice", "ConsigneesName", "nvarchar(128)");
TryAddColumn(conForCheckTables, "Invoice", "InvoiceSum", "nvarchar(64)");
TryAddColumn(conForCheckTables, "Invoice", "RefuseSum", "nvarchar(64)");
TryAddColumn(conForCheckTables, "Invoice", "SourceOrderId", "integer");
TryAddColumn(conForCheckTables, "Invoice", "SourceOrderNumber", "nvarchar(36)");
TryAddColumn(conForCheckTables, "Invoice", "IsRequestedInvoice", "int(1)");
TryAddColumn(conForCheckTables, "Orders", "RemoteOrderId", "nvarchar(36)");
TryAddColumn(conForCheckTables, "PriceList", "TradeName", "nvarchar(256)");
TryAddColumn(conForCheckTables, "PriceList", "Dosage", "nvarchar(128)");
TryAddColumn(conForCheckTables, "PriceList", "MarkupPercent", "real");
TryAddColumn(conForCheckTables, "Consignees", "ClientMarkupPercent", "real");
ConsigneeHelper.MigrateGlobalLocationIdIfNeeded(conForCheckTables);
}
catch (Exception ex)
{
try
{
var logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
Directory.CreateDirectory(logDir);
var logPath = Path.Combine(
logDir,
$"db-integrity-err-{DateTime.Now:yyyy-MM-dd}.log");
File.AppendAllText(
logPath,
$"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} {ex}{Environment.NewLine}{Environment.NewLine}",
Encoding.UTF8);
}
catch
{
// Логирование не должно скрывать исходную ошибку.
}
UiDialogs.ShowError($"Возникла ошибка при проверке локальной базы на целостность.\n{ex}", "Ошибка целостности", this);
}
finally
{
conForCheckTables.Close();
}
}
}
private static void TryAddColumn(SQLiteConnection connection, string tableName, string columnName, string columnType)
{
using (var infoCmd = new SQLiteCommand($"PRAGMA table_info([{tableName}])", connection))
using (var reader = infoCmd.ExecuteReader())
{
while (reader.Read())
{
if (string.Equals(reader["name"].ToString(), columnName, StringComparison.OrdinalIgnoreCase))
{
return;
}
}
}
using (var alterCmd = new SQLiteCommand($"ALTER TABLE [{tableName}] ADD COLUMN [{columnName}] {columnType}", connection))
{
alterCmd.ExecuteNonQuery();
}
}
}
}