Register Enova database from SQL connection string
This commit is contained in:
@@ -13,9 +13,9 @@ Dedykowana usługa Windows zastępująca proces Node na stanowiskach z enova365.
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
Plik `config/enova.json` zawiera portal WAMP, ścieżkę instalacji, alias bazy, operatora wraz z hasłem, connection string SQL, definicję dokumentu, magazyn domyślny, tryb zapisu oraz DSN Sentry. Repozytorium oraz paczka zawierają tylko `config/enova.json.sample`. Skrypt instalacyjny kopiuje wzorzec do `config/enova.json` wyłącznie wtedy, gdy lokalna konfiguracja jeszcze nie istnieje.
|
||||
Plik `config/enova.json` zawiera portal WAMP, ścieżkę instalacji, alias bazy używany wewnątrz procesu, operatora wraz z hasłem, connection string SQL, definicję dokumentu, magazyn domyślny, tryb zapisu oraz DSN Sentry. Repozytorium oraz paczka zawierają tylko `config/enova.json.sample`. Skrypt instalacyjny kopiuje wzorzec do `config/enova.json` wyłącznie wtedy, gdy lokalna konfiguracja jeszcze nie istnieje.
|
||||
|
||||
Uzupełnij pola `enova.operator`, `enova.password` i `sql.connectionString` bezpośrednio w lokalnym pliku `config/enova.json`. Parametr `sentry.dsn` wskazuje projekt Sentry; pusty lub pominięty DSN wyłącza wysyłanie błędów. Jeżeli operator lub hasło Enovy nie są podane, usługa nie loguje się do bazy Enovy i nie rejestruje endpointu `eu.smartb2b.place_order`; endpoint SQL oraz diagnostyka pozostają dostępne. Po zmianie konfiguracji trzeba zrestartować usługę. Connection string powinien używać konta SQL o możliwie najmniejszych uprawnieniach; `sql_raw` celowo dopuszcza również polecenia modyfikujące dane dla zgodności z obecną usługą.
|
||||
Uzupełnij pola `enova.operator`, `enova.password` i `sql.connectionString` bezpośrednio w lokalnym pliku `config/enova.json`. Adapter rejestruje bazę Enovy tylko w pamięci procesu na podstawie `sql.connectionString`; baza nie musi być wcześniej dodana do listy baz w profilu użytkownika Windows, a dane połączenia nie są przez usługę zapisywane w plikach Enovy. Pole `enova.database` jest nazwą tego wpisu w procesie i może odpowiadać nazwie bazy z connection stringa. Parametr `sentry.dsn` wskazuje projekt Sentry; pusty lub pominięty DSN wyłącza wysyłanie błędów. Jeżeli operator lub hasło Enovy nie są podane, usługa nie loguje się do bazy Enovy i nie rejestruje endpointu `eu.smartb2b.place_order`; endpoint SQL oraz diagnostyka pozostają dostępne. Po zmianie konfiguracji trzeba zrestartować usługę. Konto z `sql.connectionString` musi mieć uprawnienia wymagane do pracy Enovy oraz do zapytań `sql_raw`; `sql_raw` celowo dopuszcza również polecenia modyfikujące dane dla zgodności z obecną usługą.
|
||||
|
||||
## Budowanie i testy
|
||||
|
||||
@@ -46,7 +46,7 @@ Skrypt odtwarza katalog `release` z hostem, adapterem, wzorcem konfiguracji i Wi
|
||||
1. Skopiuj katalog `release` na komputer produkcyjny. Możesz skopiować `release/config/enova.json.sample` do `release/config/enova.json` i uzupełnić go przed instalacją; jeżeli tego nie zrobisz, `install.cmd` utworzy plik automatycznie.
|
||||
2. Uzupełnij w `release/config/enova.json` hasło operatora i connection string SQL.
|
||||
3. Zatrzymaj starą usługę Node dla tego samego portalu WAMP.
|
||||
4. Skonfiguruj usługę do pracy pod dedykowanym kontem Windows, które potrafi uruchomić Enovę, widzi jej bazę i licencję.
|
||||
4. Skonfiguruj usługę do pracy pod dedykowanym kontem Windows, które potrafi uruchomić Enovę i ma dostęp do jej licencji. Lista baz zapisana w profilu tego konta nie jest wymagana.
|
||||
5. Jako administrator uruchom `release/daemon/install.cmd`.
|
||||
|
||||
Jeżeli usługa ma działać pod innym kontem niż `LocalSystem`, po instalacji ustaw je w `services.msc` albo poleceniem administracyjnym `sc.exe config smartb2bsync-enova obj= "DOMENA\\Użytkownik" password= "..."`, a następnie uruchom usługę ponownie.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -18,18 +18,14 @@ public sealed class EnovaOrderAdapter : IEnovaOrderAdapter
|
||||
private static readonly object RuntimeLock = new();
|
||||
private static bool _runtimeLoaded;
|
||||
private EnovaAdapterConfiguration? _configuration;
|
||||
private Database? _database;
|
||||
|
||||
public EnovaAdapterInfo Initialize(EnovaAdapterConfiguration configuration)
|
||||
{
|
||||
ValidateConfiguration(configuration);
|
||||
EnsureRuntimeLoaded();
|
||||
|
||||
_ = BusApplication.Instance[configuration.Connection.DatabaseName]
|
||||
?? throw new EnovaOperationException(
|
||||
"eu.smartb2b.erp.database_not_found",
|
||||
$"Nie znaleziono zarejestrowanej bazy enova365 '{configuration.Connection.DatabaseName}'.",
|
||||
new Dictionary<string, object?> { ["database"] = configuration.Connection.DatabaseName });
|
||||
|
||||
_database = RegisterDatabase(configuration.Connection);
|
||||
_configuration = configuration;
|
||||
|
||||
return new EnovaAdapterInfo(
|
||||
@@ -43,6 +39,8 @@ public sealed class EnovaOrderAdapter : IEnovaOrderAdapter
|
||||
{
|
||||
var configuration = _configuration
|
||||
?? throw new InvalidOperationException("Adapter Enovy nie został zainicjalizowany.");
|
||||
var database = _database
|
||||
?? throw new InvalidOperationException("Połączenie z bazą Enovy nie zostało zainicjalizowane.");
|
||||
|
||||
var errors = OrderValidator.Validate(request);
|
||||
if (errors.Count > 0)
|
||||
@@ -58,11 +56,6 @@ public sealed class EnovaOrderAdapter : IEnovaOrderAdapter
|
||||
var sessionState = SessionState.Create();
|
||||
using var attachedSessionState = sessionState.Attach();
|
||||
|
||||
var database = BusApplication.Instance[configuration.Connection.DatabaseName]
|
||||
?? throw new EnovaOperationException(
|
||||
"eu.smartb2b.erp.database_not_found",
|
||||
$"Nie znaleziono zarejestrowanej bazy enova365 '{configuration.Connection.DatabaseName}'.");
|
||||
|
||||
using var login = database.Login(
|
||||
winAuth: false,
|
||||
user: configuration.Connection.OperatorName,
|
||||
@@ -225,6 +218,26 @@ public sealed class EnovaOrderAdapter : IEnovaOrderAdapter
|
||||
}
|
||||
}
|
||||
|
||||
private static Database RegisterDatabase(EnovaConnectionOptions connection)
|
||||
{
|
||||
var application = BusApplication.Instance;
|
||||
var existing = application[connection.DatabaseName, throwError: false];
|
||||
if (existing is not null)
|
||||
{
|
||||
application.Remove(existing, save: false);
|
||||
}
|
||||
|
||||
var database = new MsSqlDatabase
|
||||
{
|
||||
Name = connection.DatabaseName,
|
||||
UseConnectionString = true,
|
||||
ConnectionString = connection.SqlConnectionString
|
||||
};
|
||||
|
||||
application.Add(database, save: false);
|
||||
return database;
|
||||
}
|
||||
|
||||
private static void ValidateConfiguration(EnovaAdapterConfiguration configuration)
|
||||
{
|
||||
var errors = new List<string>();
|
||||
@@ -238,6 +251,11 @@ public sealed class EnovaOrderAdapter : IEnovaOrderAdapter
|
||||
errors.Add("Nazwa operatora enova365 jest wymagana.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(configuration.Connection.SqlConnectionString))
|
||||
{
|
||||
errors.Add("Connection string SQL dla bazy Enovy jest wymagany.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(configuration.DocumentDefinition))
|
||||
{
|
||||
errors.Add("Definicja dokumentu jest wymagana.");
|
||||
|
||||
@@ -9,7 +9,8 @@ public enum OrderSaveMode
|
||||
public sealed record EnovaConnectionOptions(
|
||||
string DatabaseName,
|
||||
string OperatorName,
|
||||
string Password);
|
||||
string Password,
|
||||
string SqlConnectionString);
|
||||
|
||||
public sealed record EnovaAdapterConfiguration(
|
||||
EnovaConnectionOptions Connection,
|
||||
|
||||
@@ -57,7 +57,11 @@ public sealed class ServiceSettings
|
||||
if (!string.IsNullOrWhiteSpace(Enova.Operator) && Enova.Password is not null)
|
||||
{
|
||||
enovaConfiguration = new EnovaAdapterConfiguration(
|
||||
new EnovaConnectionOptions(Enova.Database, Enova.Operator, Enova.Password),
|
||||
new EnovaConnectionOptions(
|
||||
Enova.Database,
|
||||
Enova.Operator,
|
||||
Enova.Password,
|
||||
Sql.ConnectionString),
|
||||
Enova.DocumentDefinition,
|
||||
Enova.DefaultWarehouseCode,
|
||||
Enova.SaveMode);
|
||||
|
||||
@@ -255,6 +255,10 @@ static Task SecretsComeFromConfigurationFile()
|
||||
"Server=db;Database=enova;User ID=user;Password=sql-z-pliku",
|
||||
runtime.SqlConnectionString,
|
||||
"connection string SQL");
|
||||
AssertEqual(
|
||||
runtime.SqlConnectionString,
|
||||
runtime.EnovaConfiguration?.Connection.SqlConnectionString,
|
||||
"connection string rejestracji bazy Enovy");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
finally
|
||||
@@ -321,7 +325,11 @@ static RpcInvocation CreateInvocation() => new(
|
||||
});
|
||||
|
||||
static EnovaAdapterConfiguration CreateConfiguration() => new(
|
||||
new EnovaConnectionOptions("Firma demo", "Administrator", ""),
|
||||
new EnovaConnectionOptions(
|
||||
"Firma demo",
|
||||
"Administrator",
|
||||
"",
|
||||
"Server=localhost;Database=enova;Integrated Security=true;TrustServerCertificate=true"),
|
||||
"ZO",
|
||||
null,
|
||||
OrderSaveMode.Buffer);
|
||||
|
||||
Reference in New Issue
Block a user