Populate Enova database settings from connection string

This commit is contained in:
2026-08-31 23:59:55 +00:00
parent e40f8ccdb1
commit a040a91d1f
10 changed files with 107 additions and 7 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,5 @@
using System.Reflection; using System.Reflection;
using Microsoft.Data.SqlClient;
using SmartB2B.Enova.Contracts; using SmartB2B.Enova.Contracts;
using Soneta.Business; using Soneta.Business;
using Soneta.Business.App; using Soneta.Business.App;
@@ -253,18 +254,50 @@ public sealed class EnovaOrderAdapter : IEnovaOrderAdapter
application.Remove(existing, save: false); application.Remove(existing, save: false);
} }
var database = new MsSqlDatabase var database = CreateDatabase(connection);
{
Name = connection.DatabaseName,
Active = true,
UseConnectionString = true,
ConnectionString = connection.SqlConnectionString
};
application.Add(database, save: false); application.Add(database, save: false);
return database; return database;
} }
private static MsSqlDatabase CreateDatabase(EnovaConnectionOptions connection)
{
var sqlConnection = ParseSqlConnectionString(connection.SqlConnectionString);
return new MsSqlDatabase
{
Name = connection.DatabaseName,
Active = true,
Server = sqlConnection.DataSource,
DatabaseName = sqlConnection.InitialCatalog,
User = sqlConnection.UserID,
Password = sqlConnection.Password,
Trusted = sqlConnection.IntegratedSecurity,
TrustServerCertificate = sqlConnection.TrustServerCertificate,
UseConnectionString = true,
ConnectionString = connection.SqlConnectionString
};
}
private static SqlConnectionSettings ParseSqlConnectionString(string connectionString)
{
var builder = new SqlConnectionStringBuilder(connectionString);
return new SqlConnectionSettings(
builder.DataSource,
builder.InitialCatalog,
builder.UserID,
builder.Password,
builder.IntegratedSecurity,
builder.TrustServerCertificate);
}
private sealed record SqlConnectionSettings(
string DataSource,
string InitialCatalog,
string UserID,
string Password,
bool IntegratedSecurity,
bool TrustServerCertificate);
private static void ValidateConfiguration(EnovaAdapterConfiguration configuration) private static void ValidateConfiguration(EnovaAdapterConfiguration configuration)
{ {
var errors = new List<string>(); var errors = new List<string>();

View File

@@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="../SmartB2B.Enova.Contracts/SmartB2B.Enova.Contracts.csproj" /> <ProjectReference Include="../SmartB2B.Enova.Contracts/SmartB2B.Enova.Contracts.csproj" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
<PackageReference Include="Soneta.Handel" Version="2604.4.4" /> <PackageReference Include="Soneta.Handel" Version="2604.4.4" />
<PackageReference Include="Soneta.Business.Licence" Version="2604.4.4" /> <PackageReference Include="Soneta.Business.Licence" Version="2604.4.4" />
<PackageReference Include="Soneta.Licence.Local.Proxy" Version="1.0.2" /> <PackageReference Include="Soneta.Licence.Local.Proxy" Version="1.0.2" />

View File

@@ -1,5 +1,6 @@
using System.Data.Common; using System.Data.Common;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader;
using SmartB2B.Enova.Contracts; using SmartB2B.Enova.Contracts;
using SmartB2B.Enova.Service; using SmartB2B.Enova.Service;
using SmartB2B.Enova.Service.Configuration; using SmartB2B.Enova.Service.Configuration;
@@ -36,6 +37,7 @@ var tests = new (string Name, Func<Task> Run)[]
("Parametr /debug włącza szczegółowe logowanie", DebugSwitchEnablesVerboseLogging), ("Parametr /debug włącza szczegółowe logowanie", DebugSwitchEnablesVerboseLogging),
("Parametr /verbose można wyłączyć", VerboseSwitchCanBeDisabled), ("Parametr /verbose można wyłączyć", VerboseSwitchCanBeDisabled),
("Tryb szczegółowy jest przekazywany do adaptera", VerboseModeReachesAdapter), ("Tryb szczegółowy jest przekazywany do adaptera", VerboseModeReachesAdapter),
("Rejestracja bazy przenosi parametry connection stringa", DatabaseRegistrationUsesConnectionString),
("Provider SQL działa na bieżącej platformie", SqlProviderIsSupported) ("Provider SQL działa na bieżącej platformie", SqlProviderIsSupported)
}; };
@@ -79,6 +81,69 @@ static Task SqlProviderIsSupported()
return Task.CompletedTask; return Task.CompletedTask;
} }
static Task DatabaseRegistrationUsesConnectionString()
{
var directory = new DirectoryInfo(AppContext.BaseDirectory);
string? installationPath = null;
while (directory is not null)
{
var candidate = Path.Combine(directory.FullName, "enova365 2604.4.4");
if (File.Exists(Path.Combine(candidate, "Soneta.Business.dll")))
{
installationPath = candidate;
break;
}
directory = directory.Parent;
}
if (installationPath is null)
{
throw new InvalidOperationException("Nie znaleziono lokalnej instalacji enova365 do testu adaptera.");
}
Assembly? ResolveSonetaAssembly(AssemblyLoadContext context, AssemblyName name)
{
var candidate = Path.Combine(installationPath, $"{name.Name}.dll");
return File.Exists(candidate) ? context.LoadFromAssemblyPath(candidate) : null;
}
AssemblyLoadContext.Default.Resolving += ResolveSonetaAssembly;
var adapterAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(
Path.Combine(AppContext.BaseDirectory, "SmartB2B.Enova.Adapter.dll"));
var adapterType = adapterAssembly.GetType("SmartB2B.Enova.Adapter.EnovaOrderAdapter", throwOnError: true)
?? throw new InvalidOperationException("Nie znaleziono typu adaptera Enovy.");
var parseConnectionString = adapterType.GetMethod(
"ParseSqlConnectionString",
BindingFlags.Static | BindingFlags.NonPublic)
?? throw new InvalidOperationException("Nie znaleziono metody analizującej connection string Enovy.");
object settings;
try
{
settings = parseConnectionString.Invoke(
null,
["Server=sql01;Database=Moms_Care;User ID=smartb2b;Password=haslo-sql;TrustServerCertificate=True"])
?? throw new InvalidOperationException("Adapter nie odczytał konfiguracji połączenia Enovy.");
}
catch (TargetInvocationException exception) when (exception.InnerException is not null)
{
throw exception.InnerException;
}
AssertEqual("sql01", GetProperty(settings, "DataSource"), "serwer SQL");
AssertEqual("Moms_Care", GetProperty(settings, "InitialCatalog"), "nazwa bazy SQL");
AssertEqual("smartb2b", GetProperty(settings, "UserID"), "użytkownik SQL");
AssertEqual("haslo-sql", GetProperty(settings, "Password"), "hasło SQL");
AssertEqual(false, GetProperty(settings, "IntegratedSecurity"), "uwierzytelnianie zintegrowane");
AssertEqual(true, GetProperty(settings, "TrustServerCertificate"), "zaufanie certyfikatowi SQL");
return Task.CompletedTask;
}
static object? GetProperty(object instance, string name) =>
instance.GetType().GetProperty(name)?.GetValue(instance)
?? throw new InvalidOperationException($"Nie znaleziono wartości właściwości '{name}'.");
static Task ValidFractionalDiscount() static Task ValidFractionalDiscount()
{ {
AssertNoErrors(CreateValidRequest(12.5m)); AssertNoErrors(CreateValidRequest(12.5m));

View File

@@ -6,6 +6,7 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="../../src/SmartB2B.Enova.Adapter/SmartB2B.Enova.Adapter.csproj" />
<ProjectReference Include="../../src/SmartB2B.Enova.Contracts/SmartB2B.Enova.Contracts.csproj" /> <ProjectReference Include="../../src/SmartB2B.Enova.Contracts/SmartB2B.Enova.Contracts.csproj" />
<ProjectReference Include="../../src/SmartB2B.Enova.Service/SmartB2B.Enova.Service.csproj" /> <ProjectReference Include="../../src/SmartB2B.Enova.Service/SmartB2B.Enova.Service.csproj" />
</ItemGroup> </ItemGroup>