mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 19:58:11 +00:00
- Introduced HazardDeclarationPanel component to display dangerous goods declaration details. - Updated URL constants to include CLEARANCE_PROCEED endpoint for re-requesting operations. - Enhanced permissions to include hazardous approval roles for contract approvals. - Integrated HazardDeclarationPanel into ContractRequestDetailPage and ContractClearanceDetailPage. - Added proceedToOperation method in bookings service for handling operation re-requests. - Updated contract forms and schemas to include hazard class and UN number fields. - Implemented validation for hazardous contracts in the contract creation flow. - Added expiry notice functionality for contracts nearing validity end. - Created tests for expiry notice calculations and labels. - Updated UI components to reflect hazardous cargo information and validation errors.
81 lines
2.5 KiB
TypeScript
81 lines
2.5 KiB
TypeScript
import { ConflictException } from '@nestjs/common';
|
|
import type { DataSource } from 'typeorm';
|
|
|
|
import { RoutesService } from './routes.service';
|
|
import type { RoutesRepository } from './routes.repository';
|
|
|
|
type StopSeq = Array<{ yardId: string; sequenceNo: number }>;
|
|
|
|
/** DataSource stub whose Route repository returns the given existing routes. */
|
|
const serviceWith = (
|
|
existing: Array<{ id: string; milestones: StopSeq }>,
|
|
): RoutesService => {
|
|
const dataSource = {
|
|
getRepository: () => ({ find: async () => existing }),
|
|
} as unknown as DataSource;
|
|
return new RoutesService(dataSource, {} as RoutesRepository);
|
|
};
|
|
|
|
const assertNotDuplicate = (
|
|
service: RoutesService,
|
|
yardIds: string[],
|
|
excludeRouteId?: string,
|
|
): Promise<void> =>
|
|
(
|
|
service as unknown as {
|
|
assertNotDuplicate: (
|
|
m: Array<{ yardId: string }>,
|
|
id?: string,
|
|
) => Promise<void>;
|
|
}
|
|
).assertNotDuplicate(
|
|
yardIds.map((yardId) => ({ yardId })),
|
|
excludeRouteId,
|
|
);
|
|
|
|
describe('RoutesService duplicate guard', () => {
|
|
const addisAdamaDire: StopSeq = [
|
|
{ yardId: 'addis', sequenceNo: 1 },
|
|
{ yardId: 'adama', sequenceNo: 2 },
|
|
{ yardId: 'dire', sequenceNo: 3 },
|
|
];
|
|
|
|
it('rejects an identical stop sequence', async () => {
|
|
const service = serviceWith([{ id: 'r1', milestones: addisAdamaDire }]);
|
|
|
|
await expect(
|
|
assertNotDuplicate(service, ['addis', 'adama', 'dire']),
|
|
).rejects.toBeInstanceOf(ConflictException);
|
|
});
|
|
|
|
it('allows the same endpoints with a different corridor', async () => {
|
|
// Same origin + destination, but skipping Adama is a genuinely other route.
|
|
const service = serviceWith([{ id: 'r1', milestones: addisAdamaDire }]);
|
|
|
|
await expect(
|
|
assertNotDuplicate(service, ['addis', 'dire']),
|
|
).resolves.toBeUndefined();
|
|
});
|
|
|
|
it('does not flag the route being edited against itself', async () => {
|
|
const service = serviceWith([{ id: 'r1', milestones: addisAdamaDire }]);
|
|
|
|
await expect(
|
|
assertNotDuplicate(service, ['addis', 'adama', 'dire'], 'r1'),
|
|
).resolves.toBeUndefined();
|
|
});
|
|
|
|
it('compares stops by sequence, not storage order', async () => {
|
|
const shuffled: StopSeq = [
|
|
{ yardId: 'dire', sequenceNo: 3 },
|
|
{ yardId: 'addis', sequenceNo: 1 },
|
|
{ yardId: 'adama', sequenceNo: 2 },
|
|
];
|
|
const service = serviceWith([{ id: 'r1', milestones: shuffled }]);
|
|
|
|
await expect(
|
|
assertNotDuplicate(service, ['addis', 'adama', 'dire']),
|
|
).rejects.toBeInstanceOf(ConflictException);
|
|
});
|
|
});
|