Files
edr-platform/apps/edr-freight-api/src/seed/batch8-test-data.seeder.ts
Hagernesh 8b28a7c430 feat(warehouse): Batch 8 — Import Auto Unload Arrived Bookings (→ UNLOADED)
- New UNLOADED inventory status (train-arrival landing state) + transitions + unloaded_at column
  (idempotent migration 1791000000003) + INVENTORY_UNLOADED activity type
- POST /warehouse-inventory/import/auto-unload-arrived-bookings { scheduleId }: validates ARRIVED
  IMPORT train, unloads all eligible assigned bookings (IN_TRANSIT/ARRIVED_AT_*) into UNLOADED,
  records unloadedAt + activity. Does NOT store and does NOT inspect. Reuses allocation + inventory
  plumbing. Returns { unloadedCount, skippedCount, failedCount, results }.
- Arrive Queue "Auto Unload Arrived Bookings" button now calls the new endpoint (was per-booking loop)
- Import → Unloaded Queue tab: lists UNLOADED items via InventoryWorkbench (existing actions preserved:
  Inspect/Store/Move/History) + a Last Mile action shown ONLY when booking requested door delivery
- Batch8TestDataSeeder: sets seed import train bookings to IN_TRANSIT (unload-eligible)
- Verified: auto-unload → 1 UNLOADED (unloadedAt set, not stored, not inspected); ineligible skipped;
  idempotent re-run skips already-unloaded

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 12:57:29 +00:00

52 lines
2.1 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { Booking } from '../modules/bookings/entities/booking.entity';
import { TrainSchedule } from '../modules/train-schedules/entities/train-schedule.entity';
import { TrainScheduleBooking } from '../modules/train-schedules/entities/train-schedule-booking.entity';
/**
* Makes the Batch 7 seed import train demonstrable for Batch 8: a booking riding an ARRIVED
* train is IN_TRANSIT until unloaded, so flip the seed import train's assigned bookings to
* IN_TRANSIT (an unload-eligible status). Idempotent — re-applying IN_TRANSIT is a no-op.
*/
@Injectable()
export class Batch8TestDataSeeder {
private readonly logger = new Logger(Batch8TestDataSeeder.name);
constructor(private readonly dataSource: DataSource) {}
async run(): Promise<void> {
try {
const scheduleRepo = this.dataSource.getRepository(TrainSchedule);
const scheduleBookingRepo = this.dataSource.getRepository(TrainScheduleBooking);
const bookingRepo = this.dataSource.getRepository(Booking);
const train = await scheduleRepo.findOne({ where: { trainNumber: 'SEED-IMP-TRAIN-01' } });
if (!train) {
this.logger.log('SEED-IMP-TRAIN-01 not found; skipping Batch 8 seed');
return;
}
const links = await scheduleBookingRepo.find({ where: { trainScheduleId: train.id } });
let updated = 0;
for (const link of links) {
const booking = await bookingRepo.findOne({ where: { id: link.bookingId } });
if (!booking || booking.status === 'IN_TRANSIT') continue;
await bookingRepo.update(booking.id, { status: 'IN_TRANSIT' });
updated += 1;
}
if (updated > 0) {
this.logger.log(`✅ Batch 8: set ${updated} import train booking(s) to IN_TRANSIT (unload-eligible)`);
} else {
this.logger.log('Batch 8: import train bookings already IN_TRANSIT, skipping');
}
} catch (error) {
this.logger.error(
`Batch8TestDataSeeder failed: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
}