import { MiddlewareConsumer, Module, OnApplicationBootstrap, } from "@nestjs/common"; import { ConfigModule, ConfigService } from "@nestjs/config"; import { TypeOrmModule, TypeOrmModuleOptions } from "@nestjs/typeorm"; import { ScheduleModule } from "@nestjs/schedule"; import { EventEmitterModule } from "@nestjs/event-emitter"; import { DataSource, DataSourceOptions } from "typeorm"; import { ensurePostgresSchemas } from "./config/ensure-postgres-schemas"; import { IamModule, DataSeeder } from "@tria-plc/iamapi-common"; import { SharedAuthModule } from "@tria-plc/api-common/modules/auth/shared-auth.module"; import appConfig from "./config/app.config"; import databaseConfig from "./config/database.config"; import telebirrConfig from "./config/telebirr.config"; import rabbitmqConfig from "./config/rabbitmq.config"; import faydaConfig from "./config/fayda.config"; import { BookingsModule } from "./modules/bookings/bookings.module"; import { ContractsModule } from "./modules/contracts/contracts.module"; import { SignaturesModule } from "./modules/signatures/signatures.module"; import { FilesModule } from "./modules/files/files.module"; import { ConsignmentsModule } from "./modules/consignments/consignments.module"; // import { TrainsModule } from "./modules/trains/trains.module"; import { LocomotivesModule } from "./modules/locomotives/locomotives.module"; import { WagonTypesModule } from "./modules/wagon-types/wagon-types.module"; import { TrainSetsModule } from "./modules/train-sets/train-sets.module"; import { TrainSchedulesModule } from "./modules/train-schedules/train-schedules.module"; import { TrainSchedulingModule } from "./modules/train-scheduling/train-scheduling.module"; import { SchedulingRescheduleModule } from "./modules/scheduling-reschedule/scheduling-reschedule.module"; import { CompaniesModule } from "./modules/companies/companies.module"; import { TrackingModule } from "./modules/tracking/tracking.module"; import { BillingModule } from "./modules/billing/billing.module"; import { NotificationsModule } from "./modules/notifications/notifications.module"; import { NotificationInboxModule } from "./modules/notification-inbox/notification-inbox.module"; import { FileUploadSettingsModule } from "./modules/file-upload-settings/file-upload-settings.module"; import { DropdownSettingsModule } from "./modules/dropdown-settings/dropdown-settings.module"; import { OtpModule } from "./modules/otp/otp.module"; import { RuleEngineModule } from "./modules/rule-engine/rule-engine.module"; import { BackofficeModule } from "./modules/backoffice/backoffice.module"; import { DemoPermissionsModule } from "./modules/demo-permissions/demo-permissions.module"; import { FreightAuthModule } from "./modules/auth/freight-auth.module"; import { EDR_FREIGHT_APPLICATION, EDR_FREIGHT_PERMISSIONS, } from "./seed/edr-freight.seed"; import { EdrOrgSeeder } from "./seed/edr-org.seeder"; import { FreightPositionsSeeder } from "./seed/freight-positions.seeder"; import { DemoUsersSeeder } from "./seed/demo-users.seeder"; import { FreightStaffUsersSeeder } from "./seed/freight-staff-users.seeder"; import { PaymentModule } from "./modules/payment/payment.module"; import { PricingDataSeeder } from "./seed/pricing-data.seeder"; import { FileUploadSettingsSeeder } from "./seed/file-upload-settings.seeder"; import { IndodeFacilitySeeder } from "./seed/indode-facility.seeder"; import { Batch14TestDataSeeder } from "./seed/batch1-4-test-data.seeder"; import { Batch5TestDataSeeder } from "./seed/batch5-test-data.seeder"; import { Batch7TestDataSeeder } from "./seed/batch7-test-data.seeder"; import { Batch8TestDataSeeder } from "./seed/batch8-test-data.seeder"; import { WarehouseDemoSeeder } from "./seed/warehouse-demo.seeder"; import { ExportDjiboutiInterchangeDemoSeeder } from "./seed/export-djibouti-interchange-demo.seeder"; import { MarshallingDemoTrainsSeeder } from "./seed/marshalling-demo-trains.seeder"; import { FreightPermissionKeyMigrationSeeder } from "./seed/freight-permission-key-migration.seeder"; import { DemoFreightDataSeeder } from "./seed/demo-freight-data.seeder"; import { GovCompaniesSeeder } from "./seed/gov-companies.seeder"; import { ApprovedFirstLastMileDemoBookingsSeeder } from "./seed/approved-first-lastmile-demo-bookings.seeder"; import { PaidImportExportMileDemoSeeder } from "./seed/paid-import-export-mile-demo.seeder"; //New Trains, Wagons, Container and Cargo management modules import { TrainsModule } from "./modules/trains/trains.module"; import { VerifaydaModule } from './modules/verifayda/verifayda.module'; import { FleetHistoryModule } from './modules/fleet-history/fleet-history.module'; import { WagonsModule } from "./modules/wagons/wagons.module"; import { ContainersModule } from "./modules/container-management/containers.module"; import { CargoesModule } from "./modules/cargoes/cargoes.module"; import { RoutesModule } from "./modules/routes/routes.module"; import { WarehousesModule } from "./modules/warehouses/warehouses.module"; import { OverviewModule } from "./modules/overview/overview.module"; import { VehiclesModule } from "./modules/vehicles/vehicles.module"; import { DriversModule } from "./modules/drivers/drivers.module"; import { FuelModule } from "./modules/fuel/fuel.module"; import { MaintenanceModule } from "./modules/maintenance/maintenance.module"; import { FirstMileModule } from "./modules/first-mile/first-mile.module"; import { LastMileModule } from "./modules/last-mile/last-mile.module"; import { InterchangeDocumentsModule } from "./modules/interchange-documents/interchange-documents.module"; import { ImportOperationsModule } from "./modules/import-operations/import-operations.module"; import { LoggerMiddleware } from "./logger.middleware"; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, load: [appConfig, databaseConfig, telebirrConfig, rabbitmqConfig, faydaConfig], }), ScheduleModule.forRoot(), EventEmitterModule.forRoot(), TypeOrmModule.forRootAsync({ inject: [ConfigService], useFactory: (config: ConfigService): TypeOrmModuleOptions => config.get("database")!, dataSourceFactory: async (options) => { if (!options) { throw new Error("Missing TypeORM DataSource options"); } await ensurePostgresSchemas(options as DataSourceOptions); const dataSource = new DataSource(options as DataSourceOptions); return dataSource.initialize(); }, }), SharedAuthModule, IamModule.forRoot({ applications: [EDR_FREIGHT_APPLICATION], permissions: EDR_FREIGHT_PERMISSIONS, }), BookingsModule, ContractsModule, SignaturesModule, FilesModule, ConsignmentsModule, LocomotivesModule, WagonTypesModule, TrainSetsModule, TrainSchedulesModule, TrainSchedulingModule, SchedulingRescheduleModule, CompaniesModule, TrackingModule, BillingModule, NotificationsModule, NotificationInboxModule, FileUploadSettingsModule, DropdownSettingsModule, OtpModule, RuleEngineModule, BackofficeModule, DemoPermissionsModule, FreightAuthModule, PaymentModule, //New Modules TrainsModule, WagonsModule, ContainersModule, CargoesModule, RoutesModule, WarehousesModule, OverviewModule, VehiclesModule, DriversModule, FuelModule, MaintenanceModule, FirstMileModule, LastMileModule, InterchangeDocumentsModule, ImportOperationsModule, VerifaydaModule, FleetHistoryModule, ], providers: [ EdrOrgSeeder, FreightPositionsSeeder, DemoUsersSeeder, FreightStaffUsersSeeder, PricingDataSeeder, FileUploadSettingsSeeder, FreightPermissionKeyMigrationSeeder, DemoFreightDataSeeder, GovCompaniesSeeder, IndodeFacilitySeeder, Batch14TestDataSeeder, Batch5TestDataSeeder, Batch7TestDataSeeder, Batch8TestDataSeeder, WarehouseDemoSeeder, ExportDjiboutiInterchangeDemoSeeder, MarshallingDemoTrainsSeeder, ApprovedFirstLastMileDemoBookingsSeeder, PaidImportExportMileDemoSeeder, ], }) export class AppModule implements OnApplicationBootstrap { constructor( private readonly seeder: DataSeeder, private readonly edrOrgSeeder: EdrOrgSeeder, private readonly freightPositionsSeeder: FreightPositionsSeeder, private readonly demoUsersSeeder: DemoUsersSeeder, private readonly freightStaffUsersSeeder: FreightStaffUsersSeeder, private readonly pricingDataSeeder: PricingDataSeeder, private readonly fileUploadSettingsSeeder: FileUploadSettingsSeeder, private readonly indodeFacilitySeeder: IndodeFacilitySeeder, private readonly batch14TestDataSeeder: Batch14TestDataSeeder, private readonly batch5TestDataSeeder: Batch5TestDataSeeder, private readonly batch7TestDataSeeder: Batch7TestDataSeeder, private readonly batch8TestDataSeeder: Batch8TestDataSeeder, private readonly warehouseDemoSeeder: WarehouseDemoSeeder, private readonly exportDjiboutiInterchangeDemoSeeder: ExportDjiboutiInterchangeDemoSeeder, private readonly marshallingDemoTrainsSeeder: MarshallingDemoTrainsSeeder, private readonly freightPermissionKeyMigrationSeeder: FreightPermissionKeyMigrationSeeder, private readonly demoFreightDataSeeder: DemoFreightDataSeeder, private readonly govCompaniesSeeder: GovCompaniesSeeder, ) { } async onApplicationBootstrap() { await this.freightPermissionKeyMigrationSeeder.run(); await this.seeder.run(); await this.edrOrgSeeder.run(); await this.freightPositionsSeeder.run(); await this.demoUsersSeeder.run(); await this.freightStaffUsersSeeder.run(); await this.pricingDataSeeder.run(); await this.fileUploadSettingsSeeder.run(); await this.indodeFacilitySeeder.run(); await this.batch14TestDataSeeder.run(); await this.batch5TestDataSeeder.run(); await this.batch7TestDataSeeder.run(); await this.batch8TestDataSeeder.run(); await this.warehouseDemoSeeder.run(); await this.exportDjiboutiInterchangeDemoSeeder.run(); await this.marshallingDemoTrainsSeeder.run(); // Idempotent demo data: ≥100 wagons/type, approval chains, 4 staff users. // Each block self-guards on an empty-table check, so this is safe every boot. // Demo data seeds (DemoBookingsSeeder, PricingDataSeeder, // FileUploadSettingsSeeder) are intentionally disabled — they stay // registered as providers but are not run. Re-inject + call .run() to enable. // demoFreightDataSeeder now seeds ONLY the 4 staff users (wagons + approval // rules are disabled inside the seeder). Kept running for the staff users. await this.demoFreightDataSeeder.run(); // Government entities (with importer/exporter profiles) that government // bookings bill to. Idempotent — keyed by fixed IDs. await this.govCompaniesSeeder.run(); } configure(consumer: MiddlewareConsumer) { consumer.apply(LoggerMiddleware).forRoutes("*"); } }