import { BadRequestException } from '@nestjs/common'; import type { DataSource } from 'typeorm'; import { ClearanceMilestoneService } from './clearance-milestone.service'; import type { ClearanceMilestone } from './entities/clearance-milestone.entity'; type Status = 'PENDING' | 'COMPLETED' | 'SKIPPED'; /** * Risk assignment is gated on the T1 being closed (catalog order * T1_CLOSED → RISK_ASSIGNED): customs cannot rate cargo still under transit. */ function makeService(t1Status: Status | 'MISSING') { const rows = new Map(); if (t1Status !== 'MISSING') { rows.set('T1_CLOSED', { milestoneCode: 'T1_CLOSED', status: t1Status } as ClearanceMilestone); } const risk = { milestoneCode: 'RISK_ASSIGNED', status: 'PENDING' } as ClearanceMilestone; rows.set('RISK_ASSIGNED', risk); const repo = { findOne: jest.fn(({ where }: { where: { milestoneCode: string } }) => Promise.resolve(rows.get(where.milestoneCode) ?? null), ), save: jest.fn((m: ClearanceMilestone) => Promise.resolve(m)), }; const dataSource = { getRepository: () => repo } as unknown as DataSource; return { service: new ClearanceMilestoneService(dataSource), repo, risk }; } describe('ClearanceMilestoneService.assignRisk', () => { it('rejects the assignment while the T1 is still open', async () => { const { service, repo } = makeService('PENDING'); await expect(service.assignRisk('b-1', 'GREEN')).rejects.toBeInstanceOf( BadRequestException, ); expect(repo.save).not.toHaveBeenCalled(); }); it('rejects the assignment when the booking has no T1_CLOSED milestone', async () => { const { service, repo } = makeService('MISSING'); await expect(service.assignRisk('b-1', 'GREEN')).rejects.toBeInstanceOf( BadRequestException, ); expect(repo.save).not.toHaveBeenCalled(); }); it('assigns the risk level once the T1 is closed', async () => { const { service, risk } = makeService('COMPLETED'); const saved = await service.assignRisk('b-1', 'RED', 'user-1'); expect(saved.status).toBe('COMPLETED'); expect(saved.metadata?.riskLevel).toBe('RED'); expect(risk.triggeredByUserId).toBe('user-1'); }); it('assigns the risk level when the T1 step was skipped', async () => { const { service } = makeService('SKIPPED'); const saved = await service.assignRisk('b-1', 'YELLOW'); expect(saved.status).toBe('COMPLETED'); expect(saved.metadata?.riskLevel).toBe('YELLOW'); }); });