import { BaseRepository } from '@edr/api-common'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { BookingRequest } from './entities/booking-request.entity'; @Injectable() export class BookingRequestRepository extends BaseRepository { constructor( @InjectRepository(BookingRequest) repository: Repository, ) { super(repository); } /** All requests on a contract, newest first. */ async findForContract(contractId: string): Promise { return this.repository.find({ where: { contractId }, order: { createdAt: 'DESC' }, }); } /** * GL queue: every request across all contracts, newest first. The queue page * filters by status client-side (pending work vs accepted/rejected history), * and surfaces the customer — so the contract's company rides along. */ async findQueue(): Promise { return this.repository.find({ order: { createdAt: 'DESC' }, relations: { contract: { company: true } }, }); } async findById(id: string): Promise { return this.repository.findOne({ where: { id }, // Load the contract with the bits the detail page surfaces: customer // (company), service type (mile/customs flags), routes (with yard labels) // and cargo scope. relations: { contract: { company: true, serviceType: true, routes: { originYard: true, destinationYard: true }, cargoScope: true, }, }, }); } /** * Highest NNNNNN sequence already issued for `SR-…` references (all-time — * these are not year-scoped). Includes soft-deleted rows so a cancel/delete * can't make the next number reuse an earlier one. A plain row count drifts * below the issued sequence after any delete and hands out duplicates. */ async maxReferenceSequence(): Promise { const row = await this.repository .createQueryBuilder('request') .withDeleted() .select( "COALESCE(MAX(CAST(SUBSTRING(request.reference FROM '[0-9]+$') AS int)), 0)", 'max', ) .where('request.reference LIKE :prefix', { prefix: 'SR-%' }) .getRawOne<{ max: string | number | null }>(); return Number(row?.max ?? 0); } }