mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 14:50:57 +00:00
Merge branch 'freight/develop' of github.com:Tria-plc/edr-platform into freight_feature/priority
This commit is contained in:
170
apps/edr-freight-api/src/seed/batch1-4-test-data.seeder.ts
Normal file
170
apps/edr-freight-api/src/seed/batch1-4-test-data.seeder.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
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 { WarehouseInventory } from '../modules/warehouses/entities/warehouse-inventory.entity';
|
||||
import { WarehouseYard } from '../modules/warehouses/entities/warehouse-yard.entity';
|
||||
import { WarehouseZone } from '../modules/warehouses/entities/warehouse-zone.entity';
|
||||
|
||||
/**
|
||||
* Test data seeder for Batch 1-4 warehouse system.
|
||||
* Creates Indode facility with warehouses, yards, zones, and sample inventory
|
||||
* in all status states (RECEIVED, STORED, RESERVED, READY_FOR_LOADING, LOADED, DISPATCHED).
|
||||
*/
|
||||
@Injectable()
|
||||
export class Batch14TestDataSeeder {
|
||||
private readonly logger = new Logger(Batch14TestDataSeeder.name);
|
||||
|
||||
constructor(private readonly dataSource: DataSource) {}
|
||||
|
||||
async run(): Promise<void> {
|
||||
try {
|
||||
const facilityRepo = this.dataSource.getRepository(Facility);
|
||||
const warehouseRepo = this.dataSource.getRepository(Warehouse);
|
||||
const yardRepo = this.dataSource.getRepository(WarehouseYard);
|
||||
const zoneRepo = this.dataSource.getRepository(WarehouseZone);
|
||||
const inventoryRepo = this.dataSource.getRepository(WarehouseInventory);
|
||||
|
||||
// Check if facility already exists
|
||||
const existingFacility = await facilityRepo.findOne({
|
||||
where: { code: 'INDODE_TEST' },
|
||||
});
|
||||
|
||||
if (existingFacility) {
|
||||
this.logger.log('Batch 1-4 test data already seeded, skipping');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Facility
|
||||
const facility = await facilityRepo.save(
|
||||
facilityRepo.create({
|
||||
code: 'INDODE_TEST',
|
||||
name: 'Indode Test Facility',
|
||||
facilityType: 'DRY_PORT',
|
||||
facilityStatus: 'ACTIVE',
|
||||
locationName: 'Indode',
|
||||
country: 'Djibouti',
|
||||
city: 'Djibouti',
|
||||
isActive: true,
|
||||
capacity: 100000,
|
||||
}),
|
||||
);
|
||||
this.logger.log(`Created facility: ${facility.code}`);
|
||||
|
||||
// Create Warehouse
|
||||
const warehouse = await warehouseRepo.save(
|
||||
warehouseRepo.create({
|
||||
code: 'TEST_WH_001',
|
||||
name: 'Test Warehouse 1',
|
||||
type: 'OPEN_WAREHOUSE',
|
||||
locationName: 'Test Location',
|
||||
status: 'ACTIVE',
|
||||
isActive: true,
|
||||
facilityId: facility.id,
|
||||
capacityWeight: 50000,
|
||||
capacityContainers: 500,
|
||||
maxWeight: 50000,
|
||||
maxVolume: 10000,
|
||||
}),
|
||||
);
|
||||
this.logger.log(`Created warehouse: ${warehouse.code}`);
|
||||
|
||||
// Create Yards
|
||||
const yard1 = await yardRepo.save(
|
||||
yardRepo.create({
|
||||
warehouseId: warehouse.id,
|
||||
code: 'YARD_001',
|
||||
name: 'Container Yard 1',
|
||||
type: 'CONTAINER_YARD',
|
||||
status: 'ACTIVE',
|
||||
isActive: true,
|
||||
capacityWeight: 25000,
|
||||
capacityContainers: 250,
|
||||
maxWeight: 25000,
|
||||
maxVolume: 5000,
|
||||
}),
|
||||
);
|
||||
|
||||
const yard2 = await yardRepo.save(
|
||||
yardRepo.create({
|
||||
warehouseId: warehouse.id,
|
||||
code: 'YARD_002',
|
||||
name: 'Bulk Yard 1',
|
||||
type: 'BULK_YARD',
|
||||
status: 'ACTIVE',
|
||||
isActive: true,
|
||||
capacityWeight: 25000,
|
||||
capacityContainers: 100,
|
||||
maxWeight: 25000,
|
||||
maxVolume: 5000,
|
||||
}),
|
||||
);
|
||||
this.logger.log(`Created yards: ${yard1.code}, ${yard2.code}`);
|
||||
|
||||
// Create Zones
|
||||
const zone1 = await zoneRepo.save(
|
||||
zoneRepo.create({
|
||||
yardId: yard1.id,
|
||||
code: 'ZONE_001',
|
||||
name: 'Container Zone A',
|
||||
type: 'CONTAINER_ZONE',
|
||||
status: 'ACTIVE',
|
||||
isActive: true,
|
||||
capacityWeight: 12500,
|
||||
capacityContainers: 125,
|
||||
maxWeight: 12500,
|
||||
maxVolume: 2500,
|
||||
}),
|
||||
);
|
||||
|
||||
const zone2 = await zoneRepo.save(
|
||||
zoneRepo.create({
|
||||
yardId: yard2.id,
|
||||
code: 'ZONE_002',
|
||||
name: 'Bulk Zone A',
|
||||
type: 'BULK_ZONE',
|
||||
status: 'ACTIVE',
|
||||
isActive: true,
|
||||
capacityWeight: 12500,
|
||||
capacityContainers: 50,
|
||||
maxWeight: 12500,
|
||||
maxVolume: 2500,
|
||||
}),
|
||||
);
|
||||
this.logger.log(`Created zones: ${zone1.code}, ${zone2.code}`);
|
||||
|
||||
// Create inventory in all statuses for testing
|
||||
const statuses = ['RECEIVED', 'STORED', 'RESERVED', 'READY_FOR_LOADING', 'LOADED', 'DISPATCHED'] as const;
|
||||
const now = new Date();
|
||||
|
||||
for (let i = 0; i < statuses.length; i++) {
|
||||
const status = statuses[i];
|
||||
const zone = i < 3 ? zone1 : zone2;
|
||||
|
||||
await inventoryRepo.save(
|
||||
inventoryRepo.create({
|
||||
warehouseId: warehouse.id,
|
||||
yardId: zone.yardId,
|
||||
zoneId: zone.id,
|
||||
status: status as any,
|
||||
quantity: 100 + i * 10,
|
||||
weight: 500 + i * 50,
|
||||
volume: 100 + i * 10,
|
||||
arrivedAt: new Date(now.getTime() - i * 3600000),
|
||||
storedAt: status !== 'RECEIVED' ? new Date(now.getTime() - (i - 1) * 3600000) : null,
|
||||
reservedAt: ['RESERVED', 'READY_FOR_LOADING', 'LOADED', 'DISPATCHED'].includes(status) ? new Date() : null,
|
||||
readyForLoadingAt: ['READY_FOR_LOADING', 'LOADED', 'DISPATCHED'].includes(status) ? new Date() : null,
|
||||
loadedAt: ['LOADED', 'DISPATCHED'].includes(status) ? new Date() : null,
|
||||
dispatchedAt: status === 'DISPATCHED' ? new Date() : null,
|
||||
}),
|
||||
);
|
||||
}
|
||||
this.logger.log('Created 6 test inventory items in all statuses');
|
||||
|
||||
this.logger.log('✅ Batch 1-4 test data seeded successfully');
|
||||
} catch (error) {
|
||||
this.logger.error(`Batch 1-4 seeder failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
186
apps/edr-freight-api/src/seed/indode-facility.seeder.ts
Normal file
186
apps/edr-freight-api/src/seed/indode-facility.seeder.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user