Compare commits
No commits in common. "b10eba0984e025b106e880cc75a2644e131cf225" and "2659de14b923f2d2301a678a11fe311b98cf0afa" have entirely different histories.
b10eba0984
...
2659de14b9
@ -31,6 +31,7 @@ namespace Электронная_Фармация.Classes
|
||||
if (string.IsNullOrWhiteSpace(downloadUrl) ||
|
||||
!downloadUrl.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Prefer zipball if asset missing
|
||||
if (!string.IsNullOrWhiteSpace(downloadUrl) &&
|
||||
!downloadUrl.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@ -74,14 +75,10 @@ namespace Электронная_Фармация.Classes
|
||||
throw new InvalidOperationException("В архиве не найден exe приложения.");
|
||||
}
|
||||
|
||||
var needsElevation = !IsDirectoryWritable(installDir);
|
||||
var updaterBat = Path.Combine(workRoot, "apply-update.cmd");
|
||||
WriteUpdaterScript(updaterBat);
|
||||
|
||||
Report(status, needsElevation
|
||||
? "Нужны права администратора для установки в Program Files..."
|
||||
: "Подготовка перезапуска...");
|
||||
|
||||
Report(status, "Подготовка перезапуска...");
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = updaterBat,
|
||||
@ -89,31 +86,13 @@ namespace Электронная_Фармация.Classes
|
||||
Quote(Path.GetFileName(currentExe)) + " " +
|
||||
Process.GetCurrentProcess().Id,
|
||||
UseShellExecute = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
WorkingDirectory = workRoot,
|
||||
WindowStyle = needsElevation ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden,
|
||||
CreateNoWindow = !needsElevation
|
||||
CreateNoWindow = true
|
||||
};
|
||||
if (needsElevation)
|
||||
{
|
||||
// UAC prompt — без этого robocopy в Program Files молча не заменяет exe.
|
||||
psi.Verb = "runas";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start(psi);
|
||||
}
|
||||
catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 1223)
|
||||
{
|
||||
// ERROR_CANCELLED — пользователь отклонил UAC
|
||||
throw new InvalidOperationException(
|
||||
"Обновление отменено: нужны права администратора " +
|
||||
"(программа установлена в Program Files).",
|
||||
ex);
|
||||
}
|
||||
|
||||
Process.Start(psi);
|
||||
AppDebugLog.Info("AutoUpdater",
|
||||
$"Updater started. elevate={needsElevation}, payload={payloadDir}, install={installDir}, ver={update.LatestVersion}");
|
||||
$"Updater started. payload={payloadDir}, install={installDir}, ver={update.LatestVersion}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -133,21 +112,6 @@ namespace Электронная_Фармация.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsDirectoryWritable(string directory)
|
||||
{
|
||||
try
|
||||
{
|
||||
var probe = Path.Combine(directory, ".elfisa-write-" + Guid.NewGuid().ToString("N"));
|
||||
File.WriteAllText(probe, "ok");
|
||||
File.Delete(probe);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task DownloadAsync(string url, string zipPath)
|
||||
{
|
||||
using (var client = new HttpClient { Timeout = TimeSpan.FromMinutes(10) })
|
||||
@ -179,8 +143,7 @@ namespace Электронная_Фармация.Classes
|
||||
{
|
||||
var name = Path.GetFileName(p) ?? string.Empty;
|
||||
return !name.EndsWith(".vshost.exe", StringComparison.OrdinalIgnoreCase) &&
|
||||
!name.Equals("UpdateCheckSmoke.exe", StringComparison.OrdinalIgnoreCase) &&
|
||||
!name.StartsWith("unins", StringComparison.OrdinalIgnoreCase);
|
||||
!name.Equals("UpdateCheckSmoke.exe", StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
|
||||
return exe == null ? null : Path.GetDirectoryName(exe);
|
||||
@ -188,8 +151,7 @@ namespace Электронная_Фармация.Classes
|
||||
|
||||
private static void WriteUpdaterScript(string path)
|
||||
{
|
||||
// Waits for app exit, force-kills leftovers, renames locked exe,
|
||||
// copies with robocopy, verifies, restarts. Log: %TEMP%\elfisa-updater.log
|
||||
// Waits for app exit (max ~30s, then force-kill), copies files, keeps DB/Logs, restarts.
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("@echo off");
|
||||
sb.AppendLine("setlocal EnableDelayedExpansion");
|
||||
@ -197,49 +159,28 @@ namespace Электронная_Фармация.Classes
|
||||
sb.AppendLine("set \"DST=%~2\"");
|
||||
sb.AppendLine("set \"EXENAME=%~3\"");
|
||||
sb.AppendLine("set \"PID=%~4\"");
|
||||
sb.AppendLine("set \"LOG=%TEMP%\\elfisa-updater.log\"");
|
||||
sb.AppendLine("echo ===== %DATE% %TIME% ===== > \"%LOG%\"");
|
||||
sb.AppendLine("echo SRC=%SRC%>> \"%LOG%\"");
|
||||
sb.AppendLine("echo DST=%DST%>> \"%LOG%\"");
|
||||
sb.AppendLine("echo EXE=%EXENAME% PID=%PID%>> \"%LOG%\"");
|
||||
sb.AppendLine("set \"N=0\"");
|
||||
sb.AppendLine("echo Waiting for PID %PID% ... >> \"%LOG%\"");
|
||||
sb.AppendLine("echo Waiting for PID %PID% ... > \"%TEMP%\\elfisa-updater.log\"");
|
||||
sb.AppendLine(":waitloop");
|
||||
sb.AppendLine("tasklist /FI \"PID eq %PID%\" 2>nul | findstr /C:\" %PID% \" >nul");
|
||||
sb.AppendLine("if errorlevel 1 goto donewait");
|
||||
sb.AppendLine("set /a N+=1");
|
||||
sb.AppendLine("if !N! GEQ 40 (");
|
||||
sb.AppendLine(" echo force kill PID %PID% >> \"%LOG%\"");
|
||||
sb.AppendLine("echo still alive n=!N! >> \"%TEMP%\\elfisa-updater.log\"");
|
||||
sb.AppendLine("if !N! GEQ 30 (");
|
||||
sb.AppendLine(" echo force kill %PID% >> \"%TEMP%\\elfisa-updater.log\"");
|
||||
sb.AppendLine(" taskkill /PID %PID% /F >nul 2>&1");
|
||||
sb.AppendLine(" goto donewait");
|
||||
sb.AppendLine(")");
|
||||
// ping instead of timeout — timeout often hangs in hidden windows
|
||||
sb.AppendLine("ping 127.0.0.1 -n 2 >nul");
|
||||
sb.AppendLine("goto waitloop");
|
||||
sb.AppendLine(":donewait");
|
||||
sb.AppendLine("ping 127.0.0.1 -n 2 >nul");
|
||||
// Kill any leftover instances by image name (locks Program Files exe).
|
||||
sb.AppendLine("echo taskkill by name >> \"%LOG%\"");
|
||||
sb.AppendLine("taskkill /F /IM \"%EXENAME%\" >nul 2>&1");
|
||||
sb.AppendLine("ping 127.0.0.1 -n 2 >nul");
|
||||
// Rename locked/old exe so copy can proceed even if handle lingered.
|
||||
sb.AppendLine("if exist \"%DST%\\%EXENAME%.old\" del /F /Q \"%DST%\\%EXENAME%.old\" >nul 2>&1");
|
||||
sb.AppendLine("if exist \"%DST%\\%EXENAME%\" (");
|
||||
sb.AppendLine(" move /Y \"%DST%\\%EXENAME%\" \"%DST%\\%EXENAME%.old\" >> \"%LOG%\" 2>&1");
|
||||
sb.AppendLine(")");
|
||||
sb.AppendLine("echo Copying update... >> \"%LOG%\"");
|
||||
// /IS /IT — force overwrite even if timestamps look the same
|
||||
sb.AppendLine("robocopy \"%SRC%\" \"%DST%\" /E /IS /IT /R:5 /W:1 /NFL /NDL /NJH /NJS /XF efClient.db *.db /XD Logs");
|
||||
sb.AppendLine("echo Copying update... >> \"%TEMP%\\elfisa-updater.log\"");
|
||||
sb.AppendLine("robocopy \"%SRC%\" \"%DST%\" /E /R:2 /W:1 /NFL /NDL /NJH /NJS /XF efClient.db *.db /XD Logs");
|
||||
sb.AppendLine("set \"RC=!ERRORLEVEL!\"");
|
||||
sb.AppendLine("echo robocopy=!RC! >> \"%LOG%\"");
|
||||
sb.AppendLine("if not exist \"%DST%\\%EXENAME%\" (");
|
||||
sb.AppendLine(" echo COPY FAILED — restoring old exe >> \"%LOG%\"");
|
||||
sb.AppendLine(" if exist \"%DST%\\%EXENAME%.old\" move /Y \"%DST%\\%EXENAME%.old\" \"%DST%\\%EXENAME%\" >nul 2>&1");
|
||||
sb.AppendLine(" echo Не удалось заменить файлы программы. См. %TEMP%\\elfisa-updater.log");
|
||||
sb.AppendLine(" pause");
|
||||
sb.AppendLine(" exit /b 1");
|
||||
sb.AppendLine(")");
|
||||
sb.AppendLine("if exist \"%DST%\\%EXENAME%.old\" del /F /Q \"%DST%\\%EXENAME%.old\" >nul 2>&1");
|
||||
sb.AppendLine("echo Starting \"%DST%\\%EXENAME%\" >> \"%LOG%\"");
|
||||
sb.AppendLine("echo robocopy=!RC! >> \"%TEMP%\\elfisa-updater.log\"");
|
||||
sb.AppendLine("echo Starting \"%DST%\\%EXENAME%\" >> \"%TEMP%\\elfisa-updater.log\"");
|
||||
sb.AppendLine("start \"\" /D \"%DST%\" \"%DST%\\%EXENAME%\"");
|
||||
sb.AppendLine("exit /b 0");
|
||||
File.WriteAllText(path, sb.ToString(), Encoding.Default);
|
||||
|
||||
@ -143,7 +143,6 @@ namespace Электронная_Фармация.Classes
|
||||
string query = @"
|
||||
SELECT
|
||||
Orders.Id_Order,
|
||||
Orders.OrderNumber,
|
||||
Orders.ConsigneeName,
|
||||
OrderItems.supplier_price_id,
|
||||
OrderItems.DrugName,
|
||||
@ -173,9 +172,6 @@ WHERE Orders.OrderState = 'НОВЫЙ'
|
||||
while (reader.Read())
|
||||
{
|
||||
string orderId = reader["Id_Order"].ToString().Trim();
|
||||
string orderNumber = reader["OrderNumber"] == DBNull.Value
|
||||
? string.Empty
|
||||
: reader["OrderNumber"].ToString().Trim();
|
||||
string consigneeName = reader["ConsigneeName"] == DBNull.Value
|
||||
? string.Empty
|
||||
: reader["ConsigneeName"].ToString().Trim();
|
||||
@ -200,9 +196,6 @@ WHERE Orders.OrderState = 'НОВЫЙ'
|
||||
order = new BuyerOrderRequest
|
||||
{
|
||||
LocalOrderId = orderId,
|
||||
GlobalSign = OrderNumberHelper.IsValidEx(orderNumber)
|
||||
? OrderNumberHelper.Normalize(orderNumber)
|
||||
: null,
|
||||
LocationId = locationId,
|
||||
Comment = reader["Comment"] == DBNull.Value ? null : reader["Comment"].ToString()
|
||||
};
|
||||
@ -331,25 +324,10 @@ WHERE Orders.OrderState = 'НОВЫЙ'
|
||||
throw new InvalidOperationException("Сервер не вернул order_id созданного заказа.");
|
||||
}
|
||||
|
||||
// Старые серверы создавали Draft — дожимаем до Placed.
|
||||
var remoteStatus = createdOrder.Status;
|
||||
if (!string.Equals(remoteStatus, "Placed", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
remoteStatus = await PlaceOrderAsync(client, createdOrder.OrderID) ?? remoteStatus;
|
||||
}
|
||||
|
||||
MarkOrderSent(order.LocalOrderId, createdOrder.OrderID, remoteStatus, createdOrder.GlobalSign);
|
||||
AppDebugLog.Info("DataSender",
|
||||
$"Заказ {order.LocalOrderId} отправлен, remote={createdOrder.OrderID}, status={remoteStatus}, sign={createdOrder.GlobalSign}");
|
||||
MarkOrderSent(order.LocalOrderId, createdOrder.OrderID, createdOrder.Status);
|
||||
AppDebugLog.Info("DataSender", $"Заказ {order.LocalOrderId} отправлен");
|
||||
return true;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
stopwatch.Stop();
|
||||
AppDebugLog.Error("DataSender", $"Ошибка отправки заказа {order.LocalOrderId}", ex);
|
||||
ToastNotification.ShowError(ex.Message);
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
stopwatch.Stop();
|
||||
@ -360,67 +338,7 @@ WHERE Orders.OrderState = 'НОВЫЙ'
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> PlaceOrderAsync(HttpClient client, string remoteOrderId)
|
||||
{
|
||||
var placePath = $"{BuyerOrdersEndpoint}/{Uri.EscapeDataString(remoteOrderId)}/place";
|
||||
var fullUrl = new Uri(new Uri(_baseUrl.TrimEnd('/') + "/"), placePath.TrimStart('/')).ToString();
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
AppDebugLog.ApiRequest("POST", fullUrl, string.Empty, $"place={remoteOrderId}");
|
||||
|
||||
try
|
||||
{
|
||||
using (var content = new StringContent(string.Empty, Encoding.UTF8, "application/json"))
|
||||
using (HttpResponseMessage response = await client.PostAsync(placePath, content))
|
||||
{
|
||||
string responseString = await response.Content.ReadAsStringAsync();
|
||||
stopwatch.Stop();
|
||||
AppDebugLog.ApiResponse("POST", fullUrl, (int)response.StatusCode, stopwatch.ElapsedMilliseconds, responseString);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
AppDebugLog.ApiHttpError(
|
||||
"POST",
|
||||
fullUrl,
|
||||
(int)response.StatusCode,
|
||||
responseString,
|
||||
$"place={remoteOrderId}");
|
||||
throw new InvalidOperationException(
|
||||
$"Не удалось оформить заказ на сервере (HTTP {(int)response.StatusCode}). " +
|
||||
"Заказ остался черновиком (Draft).");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var doc = JsonDocument.Parse(responseString))
|
||||
{
|
||||
if (doc.RootElement.TryGetProperty("status", out var statusEl))
|
||||
{
|
||||
return statusEl.GetString();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore parse — place succeeded
|
||||
}
|
||||
|
||||
return "Placed";
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
stopwatch.Stop();
|
||||
AppDebugLog.ApiFailure("POST", fullUrl, stopwatch.ElapsedMilliseconds, ex);
|
||||
throw new InvalidOperationException(
|
||||
$"Не удалось оформить заказ на сервере: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void MarkOrderSent(string localOrderId, string remoteOrderId, string remoteStatus, string globalSign)
|
||||
private static void MarkOrderSent(string localOrderId, string remoteOrderId, string remoteStatus)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(localOrderId))
|
||||
{
|
||||
@ -433,18 +351,12 @@ WHERE Orders.OrderState = 'НОВЫЙ'
|
||||
using (var cmd = new SQLiteCommand(
|
||||
@"UPDATE [Orders]
|
||||
SET [OrderState] = @state,
|
||||
[RemoteOrderId] = @remoteOrderId,
|
||||
[OrderNumber] = CASE
|
||||
WHEN @globalSign IS NOT NULL AND length(trim(@globalSign)) > 0 THEN @globalSign
|
||||
ELSE [OrderNumber]
|
||||
END
|
||||
[RemoteOrderId] = @remoteOrderId
|
||||
WHERE [Id_Order] = @id AND [OrderState] = 'НОВЫЙ'",
|
||||
con))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@state", "ОТПРАВЛЕН");
|
||||
cmd.Parameters.AddWithValue("@remoteOrderId", remoteOrderId ?? string.Empty);
|
||||
cmd.Parameters.AddWithValue("@globalSign",
|
||||
string.IsNullOrWhiteSpace(globalSign) ? (object)DBNull.Value : globalSign.Trim());
|
||||
cmd.Parameters.AddWithValue("@id", localOrderId);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
@ -481,9 +393,6 @@ WHERE Orders.OrderState = 'НОВЫЙ'
|
||||
[JsonPropertyName("location_id")]
|
||||
public string LocationId { get; set; }
|
||||
|
||||
[JsonPropertyName("global_sign")]
|
||||
public string GlobalSign { get; set; }
|
||||
|
||||
[JsonPropertyName("comment")]
|
||||
public string Comment { get; set; }
|
||||
|
||||
@ -513,8 +422,5 @@ WHERE Orders.OrderState = 'НОВЫЙ'
|
||||
|
||||
[JsonPropertyName("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
[JsonPropertyName("global_sign")]
|
||||
public string GlobalSign { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,157 +0,0 @@
|
||||
using System;
|
||||
using System.Data.SQLite;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Электронная_Фармация.Properties;
|
||||
|
||||
namespace Электронная_Фармация.Classes
|
||||
{
|
||||
/// <summary>
|
||||
/// Глобальные номера заказов вида EX-0000001.
|
||||
/// Источник истины — сервер (никогда не повторяются между аптеками).
|
||||
/// Offline fallback — локальный счётчик EX- (потом сервер может заменить при отправке).
|
||||
/// </summary>
|
||||
public static class OrderNumberHelper
|
||||
{
|
||||
private static readonly Regex ExPattern = new Regex(@"^EX-(\d{1,7})$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Выделяет номер для нового локального заказа.
|
||||
/// Сначала пробует сервер /api/buyer/global-sign/next, иначе локальный EX-#######.
|
||||
/// </summary>
|
||||
public static string AllocateForNewOrder()
|
||||
{
|
||||
try
|
||||
{
|
||||
var fromServer = AllocateFromServerAsync().GetAwaiter().GetResult();
|
||||
if (!string.IsNullOrWhiteSpace(fromServer))
|
||||
{
|
||||
return fromServer;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppDebugLog.Info("OrderNumber", $"Сервер недоступен для GlobalSign: {ex.Message}");
|
||||
}
|
||||
|
||||
return AllocateLocalFallback();
|
||||
}
|
||||
|
||||
public static async Task<string> AllocateFromServerAsync()
|
||||
{
|
||||
var token = Settings.Default.stringToken;
|
||||
var baseUrl = AppConfig.ApiBaseUrl;
|
||||
if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var client = new HttpClient { Timeout = TimeSpan.FromSeconds(8) })
|
||||
{
|
||||
client.BaseAddress = new Uri(baseUrl.TrimEnd('/') + "/");
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Trim());
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
using (var response = await client.PostAsync("api/buyer/global-sign/next", new StringContent(string.Empty)).ConfigureAwait(false))
|
||||
{
|
||||
var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
AppDebugLog.Info("OrderNumber", $"global-sign/next HTTP {(int)response.StatusCode}: {body}");
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var doc = JsonDocument.Parse(body))
|
||||
{
|
||||
if (doc.RootElement.TryGetProperty("global_sign", out var el))
|
||||
{
|
||||
var sign = el.GetString();
|
||||
if (IsValidEx(sign))
|
||||
{
|
||||
return Normalize(sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string AllocateLocalFallback()
|
||||
{
|
||||
long max = 0;
|
||||
try
|
||||
{
|
||||
using (var con = new SQLiteConnection(AppConfig.SqliteConnectionString))
|
||||
{
|
||||
con.Open();
|
||||
using (var cmd = new SQLiteCommand(
|
||||
"SELECT OrderNumber FROM Orders WHERE OrderNumber LIKE 'EX-%'", con))
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var n = ParseExNumber(reader[0]?.ToString());
|
||||
if (n > max)
|
||||
{
|
||||
max = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AppDebugLog.Info("OrderNumber", $"Локальный max EX-: {ex.Message}");
|
||||
}
|
||||
|
||||
return FormatEx(max + 1);
|
||||
}
|
||||
|
||||
public static bool IsValidEx(string value)
|
||||
{
|
||||
return ParseExNumber(value) > 0;
|
||||
}
|
||||
|
||||
public static string Normalize(string value)
|
||||
{
|
||||
var n = ParseExNumber(value);
|
||||
return n > 0 ? FormatEx(n) : value?.Trim();
|
||||
}
|
||||
|
||||
public static string FormatEx(long n)
|
||||
{
|
||||
if (n < 1)
|
||||
{
|
||||
n = 1;
|
||||
}
|
||||
|
||||
if (n > 9999999)
|
||||
{
|
||||
return "EX-" + n.ToString();
|
||||
}
|
||||
|
||||
return "EX-" + n.ToString("D7");
|
||||
}
|
||||
|
||||
public static long ParseExNumber(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var m = ExPattern.Match(value.Trim());
|
||||
if (!m.Success)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return long.TryParse(m.Groups[1].Value, out var n) ? n : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,7 +113,6 @@
|
||||
<Compile Include="Classes\ConsigneeHelper.cs" />
|
||||
<Compile Include="Classes\SqlSyntaxHighlighter.cs" />
|
||||
<Compile Include="Classes\DataSender.cs" />
|
||||
<Compile Include="Classes\OrderNumberHelper.cs" />
|
||||
<Compile Include="Classes\ErrorResponse.cs" />
|
||||
<Compile Include="Classes\InvoiceExportService.cs" />
|
||||
<Compile Include="Classes\InvoiceRequestService.cs" />
|
||||
|
||||
@ -32,6 +32,6 @@ using System.Runtime.InteropServices;
|
||||
// пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
|
||||
// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ "*", пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.24.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.24.0")]
|
||||
[assembly: AssemblyVersion("1.0.21.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.21.0")]
|
||||
|
||||
|
||||
@ -554,8 +554,7 @@ group by SupplierName
|
||||
|
||||
void createOrderForNextSuppliers(string SupName)
|
||||
{
|
||||
// Глобальный номер EX-0000001… (сервер / локальный fallback).
|
||||
string OrderNumber = OrderNumberHelper.AllocateForNewOrder();
|
||||
string OrderNumber = $"EP-{DateTime.Now:yyyyMMdd-HHmmss}-{Guid.NewGuid().ToString("N").Substring(0, 6)}";
|
||||
string OrderDate = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
_consigneeName = ParentForm?.ConsigneeName ?? _consigneeName ?? string.Empty;
|
||||
var consigneeSafe = (_consigneeName ?? string.Empty).Replace("'", "''");
|
||||
|
||||
@ -1521,7 +1521,7 @@ BestBefore = '{BestBefore}'
|
||||
{
|
||||
string connectionStringToLocalDB = AppConfig.SqliteConnectionString;
|
||||
|
||||
string OrderNumber = OrderNumberHelper.AllocateForNewOrder();
|
||||
string OrderNumber = $"EP-{DateTime.Now.Millisecond.ToString()}{DateTime.Now.Date.ToString("mmdd")}";
|
||||
string OrderDate = DateTime.Now.ToString("yyyy-MM-dd");//DateTime.Now.ToShortDateString();
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user