import { Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { WarehouseInventory } from './entities/warehouse-inventory.entity'; /** * READ-ONLY bridge that exposes warehouse inventory to the Train Scheduling * domain. It only reads warehouse data — it never assigns wagons, creates or * mutates schedules, and is intentionally NOT imported by the scheduling module. */ @Injectable() export class WarehouseSchedulingAdapterService { constructor(private readonly dataSource: DataSource) {} private get repo() { return this.dataSource.getRepository(WarehouseInventory); } getReadyForLoadingInventory(): Promise { return this.repo.find({ where: { status: 'READY_FOR_LOADING' }, relations: { warehouse: true, yard: true, zone: true }, order: { readyForLoadingAt: 'ASC' }, }); } getReservedInventory(): Promise { return this.repo.find({ where: { status: 'RESERVED' }, relations: { warehouse: true, yard: true, zone: true }, order: { reservedAt: 'ASC' }, }); } getInventoryByBooking(bookingId: string): Promise { return this.repo.find({ where: { bookingId }, relations: { warehouse: true, yard: true, zone: true }, order: { createdAt: 'DESC' }, }); } /** * Inventory whose origin booking runs on the given route. Best-effort, read-only: * matches the route's origin/destination yards against the booking's yards. */ async getInventoryByRoute(routeId: string): Promise { return this.repo .createQueryBuilder('inv') .leftJoinAndSelect('inv.warehouse', 'warehouse') .leftJoinAndSelect('inv.yard', 'yard') .leftJoinAndSelect('inv.zone', 'zone') .innerJoin('freight.bookings', 'booking', 'booking.id = inv.booking_id') .innerJoin( 'freight.routes', 'route', 'route.id = :routeId AND (route.origin_yard_id = booking.origin_yard_id OR route.destination_yard_id = booking.destination_yard_id)', { routeId }, ) .orderBy('inv.created_at', 'DESC') .getMany(); } }