elfisa-pharmacy/src/ElectronicPharmacy/Classes/InvoiceRequestService.cs
Magomed c447048b66 Add invoice request from orders and fix overlapping context menus.
Enable Получить накладную for sent orders, build local invoices without refusals, and stop the tab close menu from covering dedicated grid menus. Also fix price-list Backspace search and refresh the Release dist binaries.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-16 14:00:50 +03:00

341 lines
11 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;
using System.Globalization;
namespace Электроннаяармация.Classes
{
public sealed class InvoiceRequestService
{
public string CreateOrUpdateFromOrder(string orderId)
{
if (string.IsNullOrWhiteSpace(orderId))
{
throw new ArgumentException("Не указан заказ для формирования накладной.", nameof(orderId));
}
using (var con = new SQLiteConnection(AppConfig.SqliteConnectionString))
{
con.Open();
string orderNumber;
string supplierName;
string consigneeName;
string orderState;
using (var cmd = new SQLiteCommand(@"
select
o.[OrderNumber],
o.[SupplierName],
ifnull(o.[ConsigneeName], '') as [ConsigneeName],
ifnull(o.[OrderState], '') as [OrderState]
from [Orders] o
where o.[Id_Order] = @orderId;", con))
{
cmd.Parameters.AddWithValue("@orderId", orderId);
using (var reader = cmd.ExecuteReader())
{
if (!reader.Read())
{
throw new InvalidOperationException("Выбранный заказ не найден.");
}
orderNumber = reader["OrderNumber"]?.ToString() ?? string.Empty;
supplierName = reader["SupplierName"]?.ToString() ?? string.Empty;
consigneeName = reader["ConsigneeName"]?.ToString() ?? string.Empty;
orderState = reader["OrderState"]?.ToString() ?? string.Empty;
}
}
if (!string.Equals(orderState, "ОТПРАВЛЕН", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("Получить накладную можно только для заказа со статусом ОТПРАВЛЕН.");
}
var items = new List<InvoiceOrderItem>();
using (var cmd = new SQLiteCommand(@"
select
ifnull([es_code], 0) as [GoodCode],
[DrugName],
[Price],
ifnull([Zakaz], 0) as [Zakaz],
ifnull([RefuseItemsCount], 0) as [RefuseItemsCount],
ifnull([ExpiryPeriod], '') as [ExpiryPeriod]
from [OrderItems]
where [Id_Order] = @orderId
order by [DrugName];", con))
{
cmd.Parameters.AddWithValue("@orderId", orderId);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int orderedQty = SafeInt(reader["Zakaz"]);
int refusedQty = SafeInt(reader["RefuseItemsCount"]);
int arrivedQty = Math.Max(orderedQty - refusedQty, 0);
if (arrivedQty <= 0)
{
continue;
}
var price = SafeDecimal(reader["Price"]);
items.Add(new InvoiceOrderItem
{
GoodCode = SafeInt(reader["GoodCode"]),
GoodName = reader["DrugName"]?.ToString() ?? string.Empty,
Price = price,
ArrivedQty = arrivedQty,
ExpiryPeriod = reader["ExpiryPeriod"]?.ToString() ?? string.Empty
});
}
}
}
if (items.Count == 0)
{
throw new InvalidOperationException("Для этого заказа нет фактически пришедших позиций.");
}
int invoiceId;
string invoiceNumber;
using (var findCmd = new SQLiteCommand(@"
select [idInvoice], [InvoiceNumber]
from [Invoice]
where [SourceOrderId] = @orderId
limit 1;", con))
{
findCmd.Parameters.AddWithValue("@orderId", orderId);
using (var reader = findCmd.ExecuteReader())
{
if (reader.Read())
{
invoiceId = Convert.ToInt32(reader["idInvoice"]);
invoiceNumber = reader["InvoiceNumber"]?.ToString() ?? string.Empty;
}
else
{
invoiceId = 0;
invoiceNumber = $"НКЛ-{orderNumber}";
}
}
}
var invoiceDate = DateTime.Now.ToString("yyyy-MM-dd");
var invoiceSum = 0m;
foreach (var item in items)
{
invoiceSum += item.Price * item.ArrivedQty;
}
if (invoiceId == 0)
{
using (var insertCmd = new SQLiteCommand(@"
insert into [Invoice]
(
[InvoiceNumber],
[InvoiceDate],
[CodeSupplier],
[CodeConsignees],
[SumWithoutNDS],
[SumWithNDS],
[SumNDS],
[SupplierName],
[ConsigneesName],
[InvoiceSum],
[RefuseSum],
[SourceOrderId],
[SourceOrderNumber],
[IsRequestedInvoice]
)
values
(
@number,
@date,
0,
0,
@sum,
@sum,
0,
@supplier,
@consignee,
@invoiceSum,
0,
@sourceOrderId,
@sourceOrderNumber,
1
);
select last_insert_rowid();", con))
{
insertCmd.Parameters.AddWithValue("@number", invoiceNumber);
insertCmd.Parameters.AddWithValue("@date", invoiceDate);
insertCmd.Parameters.AddWithValue("@sum", invoiceSum);
insertCmd.Parameters.AddWithValue("@supplier", supplierName);
insertCmd.Parameters.AddWithValue("@consignee", consigneeName);
insertCmd.Parameters.AddWithValue("@invoiceSum", invoiceSum);
insertCmd.Parameters.AddWithValue("@sourceOrderId", orderId);
insertCmd.Parameters.AddWithValue("@sourceOrderNumber", orderNumber);
invoiceId = Convert.ToInt32(insertCmd.ExecuteScalar());
}
}
else
{
using (var updateCmd = new SQLiteCommand(@"
update [Invoice]
set
[InvoiceDate] = @date,
[SumWithoutNDS] = @sum,
[SumWithNDS] = @sum,
[SumNDS] = 0,
[SupplierName] = @supplier,
[ConsigneesName] = @consignee,
[InvoiceSum] = @invoiceSum,
[RefuseSum] = 0,
[SourceOrderNumber] = @sourceOrderNumber,
[IsRequestedInvoice] = 1
where [idInvoice] = @invoiceId;", con))
{
updateCmd.Parameters.AddWithValue("@date", invoiceDate);
updateCmd.Parameters.AddWithValue("@sum", invoiceSum);
updateCmd.Parameters.AddWithValue("@supplier", supplierName);
updateCmd.Parameters.AddWithValue("@consignee", consigneeName);
updateCmd.Parameters.AddWithValue("@invoiceSum", invoiceSum);
updateCmd.Parameters.AddWithValue("@sourceOrderNumber", orderNumber);
updateCmd.Parameters.AddWithValue("@invoiceId", invoiceId);
updateCmd.ExecuteNonQuery();
}
using (var deleteItemsCmd = new SQLiteCommand("delete from [InvoiceItem] where [idInvoice] = @invoiceId;", con))
{
deleteItemsCmd.Parameters.AddWithValue("@invoiceId", invoiceId);
deleteItemsCmd.ExecuteNonQuery();
}
}
foreach (var item in items)
{
decimal lineSum = item.Price * item.ArrivedQty;
using (var itemCmd = new SQLiteCommand(@"
insert into [InvoiceItem]
(
[idGood],
[GoodCode],
[Good],
[ProducerName],
[CountryName],
[idInvoice],
[GoodsGount],
[PriceSupplierWithoutNDS],
[PriceSupplierWithNDS],
[PriceProducerWithoutNDS],
[PriceProducerWithNDS],
[NDS],
[JNVLS],
[PriceReestr],
[SumWithoutNDS],
[SumWithNDS],
[SumNDS],
[Serial],
[BestBefore],
[Sertificate],
[Marked],
[GTIN]
)
values
(
null,
@goodCode,
@good,
'',
'',
@invoiceId,
@qty,
@price,
@price,
null,
null,
0,
0,
null,
@sum,
@sum,
0,
'',
@bestBefore,
'',
0,
''
);", con))
{
itemCmd.Parameters.AddWithValue("@goodCode", item.GoodCode);
itemCmd.Parameters.AddWithValue("@good", item.GoodName);
itemCmd.Parameters.AddWithValue("@invoiceId", invoiceId);
itemCmd.Parameters.AddWithValue("@qty", item.ArrivedQty);
itemCmd.Parameters.AddWithValue("@price", item.Price);
itemCmd.Parameters.AddWithValue("@sum", lineSum);
itemCmd.Parameters.AddWithValue("@bestBefore", item.ExpiryPeriod);
itemCmd.ExecuteNonQuery();
}
}
return orderId;
}
}
private static int SafeInt(object value)
{
if (value == null || value == DBNull.Value)
{
return 0;
}
int result;
return int.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result)
|| int.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.CurrentCulture, out result)
? result
: 0;
}
private static decimal SafeDecimal(object value)
{
if (value == null || value == DBNull.Value)
{
return 0m;
}
var text = value.ToString()?.Trim();
if (string.IsNullOrWhiteSpace(text))
{
return 0m;
}
decimal result;
if (decimal.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out result))
{
return result;
}
text = text.Replace(',', '.');
if (decimal.TryParse(text, NumberStyles.Number, CultureInfo.InvariantCulture, out result))
{
return result;
}
if (decimal.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out result))
{
return result;
}
return 0m;
}
private sealed class InvoiceOrderItem
{
public int GoodCode { get; set; }
public string GoodName { get; set; }
public decimal Price { get; set; }
public int ArrivedQty { get; set; }
public string ExpiryPeriod { get; set; }
}
}
}