feat: add hazardous goods declaration feature

- 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.
This commit is contained in:
Marshal
2026-07-25 21:10:09 +00:00
parent fde5e6de4b
commit 9a1c8e5603
41 changed files with 1663 additions and 99 deletions

View File

@@ -46,6 +46,8 @@ export const FREIGHT_PERMS = {
approveLineStaff: "edr_freight_app:contracts:approve_line_staff",
approveDirector: "edr_freight_app:contracts:approve_director",
approveCeo: "edr_freight_app:contracts:approve_ceo",
hazardousApprovalOne: "edr_freight_app:contracts:hazardous_approval_one",
hazardousApprovalTwo: "edr_freight_app:contracts:hazardous_approval_two",
generateContract: "edr_freight_app:contracts:generate_contract",
signStaff: {
bulk: "edr_freight_app:contracts:sign_staff:bulk",
@@ -442,6 +444,22 @@ const CONTRACT_APPROVE_ROLE_PERMISSION: Record<string, string> = {
CEO: FREIGHT_PERMS.contracts.approveCeo,
};
/**
* The two hazardous-goods steps prepended to a hazardous contract's chain.
* They are not position types — they authorize purely on their own permission,
* exactly as the API's HAZARDOUS_APPROVAL_ROLE_PERMISSION does.
*/
export const HAZARDOUS_APPROVAL_ROLE_PERMISSION: Record<string, string> = {
HAZARDOUS_APPROVAL_ONE: FREIGHT_PERMS.contracts.hazardousApprovalOne,
HAZARDOUS_APPROVAL_TWO: FREIGHT_PERMS.contracts.hazardousApprovalTwo,
};
/** Display label for an approval step's role (hazardous steps get real names). */
export const CONTRACT_APPROVAL_ROLE_LABELS: Record<string, string> = {
HAZARDOUS_APPROVAL_ONE: "Hazardous review — first approver",
HAZARDOUS_APPROVAL_TWO: "Hazardous review — second approver",
};
/**
* Can this user action a contract approval step requiring `requiredRole`?
*
@@ -464,6 +482,10 @@ export function canApproveContractStep(
if (!user || !requiredRole) return false;
if (isFreightApprovalAdmin(user)) return true;
// Hazardous steps are permission-only — no position type stands in for them.
const hazardousPermission = HAZARDOUS_APPROVAL_ROLE_PERMISSION[requiredRole];
if (hazardousPermission) return hasPermission(user, hazardousPermission);
const positionTypes = getPositionTypeKeys(user);
if (positionTypes.includes(requiredRole)) return true;