using System.Data; using System.Reflection; using GB5Shared.Addon; using GB5Shared.DTO.Framework.CommonConfig; using GB5Shared.GenerateAutoNumber; using GB5Shared.Hosting; using Microsoft.Data.SqlClient; using Npgsql; using static GB5Shared.DTO.Framework.Enum.FrameworkEnumDTO; namespace MaintenanceSL; public class MaintenanceModule : IModule { public void Register(IServiceCollection services, IConfiguration configuration) { // GB5Shared classes aren't covered by the assembly scans below, so shared services // consumed here (ClaimBLL -> IEmployeeBLL -> IAddonService, ClaimBLL -> IVoucherBLL -> // VoucherNumberService) must be registered explicitly. services.AddScoped(); services.AddScoped(); // PayRollDAL.EmployeeDAL (pulled in below for ClaimBLL -> IEmployeeBLL) needs its own // DatabaseTypeConfig/IDbConnection - normally set up by PayRollModule.cs, which never runs // on this host. Mirrors that module's identical registration. var gb5Config = configuration.GetSection("Gb5SystemDTO").Get() ?? throw new InvalidOperationException("Gb5SystemDTO configuration section is missing."); var activeDbType = (DatabaseType)gb5Config.DataBaseType; services.AddSingleton(new DatabaseTypeConfig(activeDbType)); AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); services.AddScoped(sp => { var connStr = gb5Config.ActiveConnectionString; return activeDbType switch { DatabaseType.SQL => (IDbConnection)new SqlConnection(connStr), DatabaseType.POSTGRE => (IDbConnection)new NpgsqlConnection(connStr), _ => throw new NotSupportedException($"DataBaseType '{gb5Config.DataBaseType}' not supported.") }; }); var maintenanceBLLAssembly = Assembly.Load("MaintenanceBLL"); var maintenanceDALAssembly = Assembly.Load("MaintenanceDAL"); services.Scan(scan => scan .FromAssemblies(maintenanceBLLAssembly, maintenanceDALAssembly) .AddClasses(c => c.Where(t => !t.IsAbstract && !t.IsInterface && (t.Namespace == null || !t.Namespace.Contains(".DTO")))) .AsImplementedInterfaces() .WithScopedLifetime()); // Cross-module reuse: ClaimBLL needs PayRollBLL's IEmployeeBLL (employee lookups for // claim submission), which itself needs IAddressBLL/IContactBLL (both parameters are // C#-nullable but have no default value, so the DI activator still treats them as // required). PayRollBLL/PayRollDAL are deliberately NOT blanket-scanned - they contain // many other PayRoll-specific services (payroll runs, tax config, etc.) that need // config/DI this host never sets up. Only the Employee/Address/Contact slice is // registered here, narrowed by class name (same pattern as SwModule.cs's // FrameworkBLL.ServerConfigBLL scan). var payRollBLLAssembly = Assembly.Load("PayRollBLL"); var payRollDALAssembly = Assembly.Load("PayRollDAL"); services.Scan(scan => scan .FromAssemblies(payRollBLLAssembly, payRollDALAssembly) .AddClasses(c => c.Where(t => !t.IsAbstract && !t.IsInterface && (t.Name == "EmployeeBLL" || t.Name == "EmployeeDAL" || t.Name == "TRMEmployeeDAL" || t.Name == "AddressBLL" || t.Name == "AddressDAL" || t.Name == "ContactBLL" || t.Name == "ContactDAL"))) .AsImplementedInterfaces() .WithScopedLifetime()); // Cross-module reuse: ClaimBLL also needs AccountsBLL's IVoucherBLL (posts the resolved // claim voucher). Accounts is likewise a different host's module (HRFinanceHost) - only // the Voucher slice is registered here, same narrow-by-class-name approach as above. var accountsBLLAssembly = Assembly.Load("AccountsBLL"); var accountsDALAssembly = Assembly.Load("AccountsDAL"); services.Scan(scan => scan .FromAssemblies(accountsBLLAssembly, accountsDALAssembly) .AddClasses(c => c.Where(t => !t.IsAbstract && !t.IsInterface && (t.Name == "VoucherBLL" || t.Name == "VoucherDAL"))) .AsImplementedInterfaces() .WithScopedLifetime()); } public void MapEndpoints(WebApplication app) { } }