Files
edr-platform/apps/edr-freight-api/src/seed/indode-facility.seeder.ts
2026-06-16 09:25:47 +00:00

187 lines
6.1 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { Facility } from '../modules/facilities/entities/facility.entity';
import { Warehouse } from '../modules/warehouses/entities/warehouse.entity';
import { WarehouseYard, type WarehouseYardType } from '../modules/warehouses/entities/warehouse-yard.entity';
import { WarehouseZone, type WarehouseZoneType } from '../modules/warehouses/entities/warehouse-zone.entity';
const INDODE_FACILITY = {
code: 'INDODE_DRY_PORT',
name: 'Indode Multipurpose Dry Port',
description: 'Main facility for container and cargo handling',
facilityType: 'DRY_PORT' as const,
facilityStatus: 'ACTIVE' as const,
locationName: 'Indode',
country: 'Djibouti',
city: 'Djibouti',
address: 'Indode, Djibouti',
latitude: 11.5447,
longitude: 43.145,
capacity: 50000,
isActive: true,
notes: 'Primary dry port for container consolidation and distribution',
};
const WAREHOUSES = [
{
name: 'Open Warehouse - Indode',
code: 'INDODE_OPEN',
type: 'OPEN_WAREHOUSE' as const,
locationName: 'Indode Open',
capacityWeight: 25000,
capacityContainers: 500,
maxWeight: 25000,
maxVolume: 5000,
status: 'ACTIVE' as const,
isActive: true,
},
{
name: 'Closed Warehouse - Indode',
code: 'INDODE_CLOSED',
type: 'CLOSED_WAREHOUSE' as const,
locationName: 'Indode Closed',
capacityWeight: 20000,
capacityContainers: 400,
maxWeight: 20000,
maxVolume: 4000,
status: 'ACTIVE' as const,
isActive: true,
},
];
const YARD_TYPES = [
'CONTAINER_YARD',
'BULK_YARD',
'GENERAL_CARGO_YARD',
'HAZARDOUS_YARD',
'COLD_STORAGE_YARD',
] as const;
@Injectable()
export class IndodeFacilitySeeder {
private readonly logger = new Logger(IndodeFacilitySeeder.name);
constructor(private readonly dataSource: DataSource) {}
async run(): Promise<void> {
try {
await this.dataSource.transaction(async (manager) => {
const facilityRepo = manager.getRepository(Facility);
const warehouseRepo = manager.getRepository(Warehouse);
const yardRepo = manager.getRepository(WarehouseYard);
const zoneRepo = manager.getRepository(WarehouseZone);
// Ensure facility exists
const facility = await facilityRepo.findOne({
where: { code: INDODE_FACILITY.code },
});
if (facility) {
this.logger.log('Indode facility already exists, skipping seed');
return;
}
const newFacility = facilityRepo.create(INDODE_FACILITY);
const savedFacility = await facilityRepo.save(newFacility);
this.logger.log(`Created facility: ${savedFacility.code}`);
// Create warehouses for the facility
for (const warehouseData of WAREHOUSES) {
try {
const warehouse = await warehouseRepo.findOne({
where: { code: warehouseData.code },
});
if (warehouse) {
this.logger.log(`Warehouse ${warehouseData.code} already exists, skipping`);
continue;
}
const newWarehouse = warehouseRepo.create({
...warehouseData,
facilityId: savedFacility.id,
});
const savedWarehouse = await warehouseRepo.save(newWarehouse);
this.logger.log(`Created warehouse: ${savedWarehouse.code} under facility ${savedFacility.code}`);
// Create 11 yards per warehouse
await this.createYardsForWarehouse(yardRepo, zoneRepo, savedWarehouse);
} catch (warehouseError) {
this.logger.warn(
`Failed to create warehouse ${warehouseData.code}: ${warehouseError instanceof Error ? warehouseError.message : String(warehouseError)}`,
);
}
}
this.logger.log(
'Indode Multipurpose Dry Port facility seeded successfully with 2 warehouses and 11 yards each',
);
});
} catch (error) {
this.logger.error(
`IndodeFacilitySeeder error: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
private async createYardsForWarehouse(
yardRepo: any,
zoneRepo: any,
warehouse: Warehouse,
): Promise<void> {
const baseCapacityWeight = 5000;
const baseCapacityContainers = 100;
const yardCount = 11;
for (let i = 0; i < yardCount; i++) {
const yardType: WarehouseYardType = i < YARD_TYPES.length ? YARD_TYPES[i] : 'GENERAL_CARGO_YARD';
const yardCode = `${warehouse.code}_YARD_${String(i + 1).padStart(2, '0')}`;
const existingYard = await yardRepo.findOne({ where: { code: yardCode } });
if (existingYard) {
this.logger.log(`Yard ${yardCode} already exists, skipping`);
continue;
}
const yardData = {
warehouseId: warehouse.id,
name: `${warehouse.code} ${yardType.replace(/_/g, ' ')} ${String(i + 1).padStart(2, '0')}`,
code: yardCode,
type: yardType,
capacityWeight: baseCapacityWeight,
capacityContainers: baseCapacityContainers,
maxWeight: baseCapacityWeight,
maxVolume: baseCapacityWeight / 2,
status: 'ACTIVE' as const,
isActive: true,
};
const newYard = yardRepo.create(yardData);
const savedYard = (await yardRepo.save(newYard)) as WarehouseYard;
this.logger.log(`Created yard: ${savedYard.code}`);
// Create default zone for the yard
const zoneType: WarehouseZoneType = yardType.replace('_YARD', '_ZONE') as WarehouseZoneType;
const zoneCode = `${savedYard.code}_ZONE_A`;
const zoneData = {
yardId: savedYard.id,
name: `${savedYard.name} Zone A`,
code: zoneCode,
type: zoneType,
capacityWeight: (baseCapacityWeight ?? 1000) / 2,
capacityContainers: (baseCapacityContainers ?? 100) / 2,
maxWeight: (baseCapacityWeight ?? 1000) / 2,
maxVolume: (baseCapacityWeight ?? 500) / 2,
status: 'ACTIVE' as const,
isActive: true,
};
const newZone = zoneRepo.create(zoneData);
await zoneRepo.save(newZone);
this.logger.log(`Created zone: ${zoneCode}`);
}
}
}