mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 22:25:42 +00:00
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>
This commit is contained in:
51
apps/edr-freight-api/src/seed/batch8-test-data.seeder.ts
Normal file
51
apps/edr-freight-api/src/seed/batch8-test-data.seeder.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
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)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user