using System.Reflection; using GB5Shared.GOP.Qualifier; using Dapr; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.EntityHandler; using GB5Shared.ExcelExport; using GB5Shared.Export; using GB5Shared.Export.CSVExport; using GB5Shared.Export.HybridReport; using GB5Shared.Export.Pivot; using GB5Shared.GB5Library.Qualifier; using GB5Shared.GenerateAutoNumber; using GB5Shared.Hosting; using GB5Shared.ListQuery; using GB5Shared.ScanIdentifier; using GB5Shared.PubSub.OutBox; using GB5Shared.WorkFlow.WorkFlowEngine; using GB5Shared.WorkFlow.WorkFlowRunTime; using Microsoft.AspNetCore.ResponseCompression; using MMDAL.DTO.Scheduling; using MMSL.Hubs; using MMSL.Services; using Newtonsoft.Json; namespace MMSL; public class MMModule : IModule { public void Register(IServiceCollection services, IConfiguration configuration) { services.AddHttpContextAccessor(); services.AddHttpClient(); services.AddScoped(sp => { var httpContext = sp.GetRequiredService().HttpContext; if (httpContext != null && httpContext.Request.Headers.TryGetValue("Login", out var loginHeader)) return JsonConvert.DeserializeObject(loginHeader!)!; return new LoginDTO(); }); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(typeof(BaseEntityAppService<>), typeof(BaseEntityAppService<>)); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddGB5QualifierEngine(); services.AddScoped(); services.AddScoped(); // Generic Scan-Identifier & Label Platform (GB5Shared/ScanIdentifier) — the dispatcher // only; MM's own IScanTargetResolver implementations (IndentDetailResolver) are picked up // by the broader MMBLL/MMDAL assembly Scan() below already, so passing an assembly here // would double-register them (same gotcha found/fixed in WiModule.Register()). services.AddScanTargetResolvers(); services.AddScoped(); services.AddSignalR(options => { options.EnableDetailedErrors = true; options.MaximumReceiveMessageSize = 32 * 1024; options.ClientTimeoutInterval = TimeSpan.FromSeconds(60); options.KeepAliveInterval = TimeSpan.FromSeconds(15); }); services.AddSingleton(); services.AddSingleton(); services.AddHostedService(); services.AddResponseCompression(o => { o.EnableForHttps = true; o.Providers.Add(); }); var mmBLLAssembly = Assembly.Load("MMBLL"); var mmDALAssembly = Assembly.Load("MMDAL"); var adminBLLAssembly = Assembly.Load("AdminBLL"); var adminDALAssembly = Assembly.Load("AdminDAL"); services.Scan(scan => scan .FromAssemblies(mmBLLAssembly, mmDALAssembly, adminBLLAssembly, adminDALAssembly) .AddClasses(c => c.Where(t => !t.IsAbstract && !t.IsInterface && t.Namespace != null && !t.Namespace.Contains(".DTO") && !typeof(Exception).IsAssignableFrom(t) && t.GetMethod("$") == null)) .AsImplementedInterfaces() .WithScopedLifetime()); services.AddListInfrastructure(mmDALAssembly); } public void MapEndpoints(WebApplication app) { app.MapHub("/hubs/mrprun"); app.MapHub("/hubs/schedulingrun"); app.MapHub("/hubs/operatorconsole"); app.MapPost("/scheduling/trigger", [Topic("pubsub", "schedulingrun.trigger")] async (SchedulingRunTriggerDTO dto, SchedulingRunProcessingService svc, CancellationToken ct) => await svc.ProcessAsync(dto, ct)); } }