import { BadRequestException } from '@nestjs/common'; import { WarehouseInventoryService } from './warehouse-inventory.service'; /** * Export cargo is received into the warehouse to wait for its train, and only a * paid booking may be received — otherwise storage and a GRN would start against * cargo the customer has not settled. Import is never blocked: it arrives OFF a * train and its receive is the unload. * * The guard touches only the DataSource, so the instance is built off the * prototype rather than stubbing all 20-odd collaborators. */ type Guard = ( bookingId: string | null | undefined, direction: string | null, ) => Promise; function makeGuard(paymentStatus: string | null) { const query = jest.fn().mockResolvedValue([{ paymentStatus }]); const service = Object.create(WarehouseInventoryService.prototype) as Record; service.dataSource = { query }; const guard = ( service as unknown as { assertExportBookingPaid: Guard } ).assertExportBookingPaid.bind(service); return { guard, query }; } describe('receive() — export paid gate', () => { it('rejects an unpaid export booking', async () => { const { guard } = makeGuard('PENDING'); await expect(guard('b-1', 'EXPORT')).rejects.toBeInstanceOf(BadRequestException); }); it('allows a paid export booking', async () => { const { guard } = makeGuard('PAID'); await expect(guard('b-1', 'EXPORT')).resolves.toBeUndefined(); }); it('never blocks import, paid or not', async () => { const { guard, query } = makeGuard('PENDING'); await expect(guard('b-1', 'IMPORT')).resolves.toBeUndefined(); expect(query).not.toHaveBeenCalled(); }); it('ignores a receive with no booking attached', async () => { const { guard, query } = makeGuard('PENDING'); await expect(guard(null, 'EXPORT')).resolves.toBeUndefined(); expect(query).not.toHaveBeenCalled(); }); });