mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Yard create/update now rejects capacities that overflow the parent warehouse, and zone create/update rejects capacities that overflow the parent yard, via BadRequestException. Dispatcher permission preset expanded to full CRUD on warehouse and fleet management; allocation and fee rules remain view-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
859 lines
47 KiB
TypeScript
859 lines
47 KiB
TypeScript
const EDR_FREIGHT_APP_KEY = 'edr_freight_app';
|
||
|
||
export type FreightPermissionSeed = {
|
||
id: string;
|
||
key: string;
|
||
name: { am: string; en: string };
|
||
applicationKey: string;
|
||
};
|
||
|
||
export const RULE_ENGINE_RESOURCE_SLUGS = [
|
||
'cargo-types',
|
||
'container-types',
|
||
'wagon-types',
|
||
'service-types',
|
||
'yards',
|
||
'shipping-lines',
|
||
'weight-limit-rules',
|
||
'priority-configs',
|
||
'rates',
|
||
'approval-rules',
|
||
'yard-distances',
|
||
] as const;
|
||
|
||
export type RuleEngineResourceSlug = (typeof RULE_ENGINE_RESOURCE_SLUGS)[number];
|
||
|
||
const slugToResourceKey = (slug: RuleEngineResourceSlug): string =>
|
||
slug.replace(/-/g, '_');
|
||
|
||
const perm = (
|
||
id: string,
|
||
key: string,
|
||
en: string,
|
||
): FreightPermissionSeed => ({
|
||
id,
|
||
key,
|
||
name: { am: en, en },
|
||
applicationKey: EDR_FREIGHT_APP_KEY,
|
||
});
|
||
|
||
export const BOOKING_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('a1000001-0001-4000-8000-000000000001', 'edr_freight_app:bookings:view', 'View bookings'),
|
||
perm('a1000001-0001-4000-8000-000000000002', 'edr_freight_app:bookings:staff_accept', 'Accept booking intake'),
|
||
perm('a1000001-0001-4000-8000-000000000003', 'edr_freight_app:bookings:request_changes', 'Request booking changes'),
|
||
perm('a1000001-0001-4000-8000-000000000004', 'edr_freight_app:bookings:reject', 'Reject booking submission'),
|
||
perm('a1000001-0001-4000-8000-000000000005', 'edr_freight_app:bookings:approve_line_staff', 'Approve as line staff'),
|
||
perm('a1000001-0001-4000-8000-000000000006', 'edr_freight_app:bookings:approve_director', 'Approve as director'),
|
||
perm('a1000001-0001-4000-8000-000000000007', 'edr_freight_app:bookings:approve_ceo', 'Approve as CEO'),
|
||
perm('a1000001-0001-4000-8000-000000000008', 'edr_freight_app:bookings:reject_approval', 'Reject at approval step'),
|
||
perm('a1000001-0001-4000-8000-000000000009', 'edr_freight_app:bookings:generate_contract', 'Generate contract'),
|
||
perm('a1000001-0001-4000-8000-00000000000a', 'edr_freight_app:bookings:sign_staff', 'Staff contract signature'),
|
||
perm('a1000001-0001-4000-8000-00000000000b', 'edr_freight_app:bookings:payment_pnr', 'Generate PNR'),
|
||
perm('a1000001-0001-4000-8000-00000000000c', 'edr_freight_app:bookings:payment_verify', 'Verify payment'),
|
||
perm('a1000001-0001-4000-8000-00000000000d', 'edr_freight_app:bookings:operations', 'Booking operations'),
|
||
perm('a1000001-0001-4000-8000-00000000000e', 'edr_freight_app:bookings:cancel', 'Cancel booking'),
|
||
perm('a1000001-0001-4000-8000-000000000023', 'edr_freight_app:bookings:clearance_view', 'View customs-clearance queue'),
|
||
perm('a1000001-0001-4000-8000-000000000020', 'edr_freight_app:bookings:review_documents', 'Review clearance documents'),
|
||
perm('a1000001-0001-4000-8000-000000000021', 'edr_freight_app:bookings:upload_clearance_output', 'Upload customs output documents'),
|
||
perm('a1000001-0001-4000-8000-000000000022', 'edr_freight_app:bookings:finalize_clearance', 'Finalize document clearance'),
|
||
perm('a1000001-0001-4000-8000-00000000000f', 'edr_freight_app:train_scheduling:view', 'View train scheduling'),
|
||
perm('a1000001-0001-4000-8000-000000000010', 'edr_freight_app:train_scheduling:manage', 'Manage train scheduling'),
|
||
perm('a1000001-0001-4000-8000-000000000011', 'edr_freight_app:fleet:view', 'View fleet'),
|
||
perm('a1000001-0001-4000-8000-000000000012', 'edr_freight_app:fleet:manage', 'Manage fleet'),
|
||
perm('a1000001-0001-4000-8000-000000000013', 'edr_freight_app:admin', 'Freight administration'),
|
||
perm('a1000001-0001-4000-8000-000000000024', 'edr_freight_app:bookings:create', 'Create booking'),
|
||
];
|
||
|
||
/**
|
||
* Contract-phase permissions (contract–booking separation). Mirror the booking
|
||
* approval/sign/clearance permissions but scoped to the new contracts module.
|
||
*/
|
||
export const CONTRACT_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('a3000001-0001-4000-8000-000000000001', 'edr_freight_app:contracts:view', 'View contracts'),
|
||
perm('a3000001-0001-4000-8000-000000000002', 'edr_freight_app:contracts:staff_accept', 'Accept contract intake'),
|
||
perm('a3000001-0001-4000-8000-000000000003', 'edr_freight_app:contracts:request_changes', 'Request contract changes'),
|
||
perm('a3000001-0001-4000-8000-000000000004', 'edr_freight_app:contracts:reject', 'Reject contract'),
|
||
perm('a3000001-0001-4000-8000-000000000005', 'edr_freight_app:contracts:approve_line_staff', 'Approve contract as line staff'),
|
||
perm('a3000001-0001-4000-8000-000000000006', 'edr_freight_app:contracts:approve_director', 'Approve contract as director'),
|
||
perm('a3000001-0001-4000-8000-000000000007', 'edr_freight_app:contracts:approve_ceo', 'Approve contract as CEO'),
|
||
perm('a3000001-0001-4000-8000-000000000008', 'edr_freight_app:contracts:generate_contract', 'Generate contract document'),
|
||
perm('a3000001-0001-4000-8000-000000000009', 'edr_freight_app:contracts:sign_staff', 'Staff contract signature'),
|
||
perm('a3000001-0001-4000-8000-00000000000a', 'edr_freight_app:contracts:clearance_review', 'Review pre-booking clearance docs'),
|
||
perm('a3000001-0001-4000-8000-00000000000b', 'edr_freight_app:contracts:finalize_clearance', 'Finalize pre-booking clearance'),
|
||
perm('a3000001-0001-4000-8000-00000000000c', 'edr_freight_app:contracts:create_booking', 'GL ET create booking under contract'),
|
||
perm('a3000001-0001-4000-8000-00000000000d', 'edr_freight_app:contracts:ops_clearance_review', 'Operations review of self-clearance docs (Path A)'),
|
||
perm('a3000001-0001-4000-8000-00000000000e', 'edr_freight_app:contracts:clearance_et_actions', 'GL Ethiopia phased clearance actions'),
|
||
perm('a3000001-0001-4000-8000-00000000000f', 'edr_freight_app:contracts:clearance_dj_actions', 'GL Djibouti phased clearance actions'),
|
||
perm('a3000001-0001-4000-8000-000000000010', 'edr_freight_app:contracts:clearance_duty_advise', 'Advise contract duty/tax'),
|
||
];
|
||
|
||
const RULE_ENGINE_PERMISSION_IDS: Record<RuleEngineResourceSlug, { view: string; manage: string }> = {
|
||
'cargo-types': { view: 'b2000001-0001-4000-8000-000000000001', manage: 'b2000001-0001-4000-8000-000000000002' },
|
||
'container-types': { view: 'b2000001-0001-4000-8000-000000000003', manage: 'b2000001-0001-4000-8000-000000000004' },
|
||
'wagon-types': { view: 'b2000001-0001-4000-8000-000000000015', manage: 'b2000001-0001-4000-8000-000000000016' },
|
||
'service-types': { view: 'b2000001-0001-4000-8000-000000000005', manage: 'b2000001-0001-4000-8000-000000000006' },
|
||
yards: { view: 'b2000001-0001-4000-8000-000000000007', manage: 'b2000001-0001-4000-8000-000000000008' },
|
||
'shipping-lines': { view: 'b2000001-0001-4000-8000-000000000009', manage: 'b2000001-0001-4000-8000-00000000000a' },
|
||
'weight-limit-rules': { view: 'b2000001-0001-4000-8000-00000000000b', manage: 'b2000001-0001-4000-8000-00000000000c' },
|
||
'priority-configs': { view: 'b2000001-0001-4000-8000-00000000000f', manage: 'b2000001-0001-4000-8000-000000000010' },
|
||
rates: { view: 'b2000001-0001-4000-8000-000000000011', manage: 'b2000001-0001-4000-8000-000000000012' },
|
||
'approval-rules': { view: 'b2000001-0001-4000-8000-000000000013', manage: 'b2000001-0001-4000-8000-000000000014' },
|
||
'yard-distances': { view: 'b2000001-0001-4000-8000-000000000018', manage: 'b2000001-0001-4000-8000-000000000019' },
|
||
};
|
||
|
||
/**
|
||
* Slugs whose changes go through a separate approver. `manage` lets a staff
|
||
* member propose a change; only `approve` lets someone put it into effect.
|
||
* Only listed slugs get the permission — the rest are manage-only.
|
||
*/
|
||
const RULE_ENGINE_APPROVE_PERMISSION_IDS: Partial<Record<RuleEngineResourceSlug, string>> = {
|
||
rates: 'b2000001-0001-4000-8000-000000000017',
|
||
};
|
||
|
||
export type RuleEngineApprovableSlug = 'rates';
|
||
|
||
export const RULE_ENGINE_PERMISSIONS: FreightPermissionSeed[] = RULE_ENGINE_RESOURCE_SLUGS.flatMap(
|
||
(slug) => {
|
||
const resource = slugToResourceKey(slug);
|
||
const ids = RULE_ENGINE_PERMISSION_IDS[slug];
|
||
const approveId = RULE_ENGINE_APPROVE_PERMISSION_IDS[slug];
|
||
return [
|
||
perm(ids.view, `edr_freight_app:rule_engine:${resource}:view`, `View ${slug}`),
|
||
perm(ids.manage, `edr_freight_app:rule_engine:${resource}:manage`, `Manage ${slug}`),
|
||
...(approveId
|
||
? [perm(approveId, `edr_freight_app:rule_engine:${resource}:approve`, `Approve ${slug} changes`)]
|
||
: []),
|
||
];
|
||
},
|
||
);
|
||
|
||
/**
|
||
* Container-allocation permission for the previously-unguarded
|
||
* booking allocate-containers endpoint.
|
||
*/
|
||
export const GAP_CONTROLLER_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('c1000001-0001-4000-8000-000000000001', 'edr_freight_app:allocation:manage', 'Allocate containers to vehicles'),
|
||
];
|
||
|
||
/**
|
||
* Advanced backoffice resources — full CRUD + workflow-action keys.
|
||
* See docs/rbac/freight-backoffice-permissions.md. Additive only: the existing
|
||
* bookings/contracts/rule-engine/allocation keys above are unchanged.
|
||
*/
|
||
|
||
// C. Customers
|
||
export const CUSTOMER_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('d1a00001-0001-4000-8000-000000000001', 'edr_freight_app:customers:view', 'View customers'),
|
||
perm('d1a00001-0001-4000-8000-000000000002', 'edr_freight_app:customers:create', 'Create customer'),
|
||
perm('d1a00001-0001-4000-8000-000000000003', 'edr_freight_app:customers:update', 'Update customer'),
|
||
perm('d1a00001-0001-4000-8000-000000000004', 'edr_freight_app:customers:deactivate', 'Deactivate customer'),
|
||
perm('d1a00001-0001-4000-8000-000000000005', 'edr_freight_app:customers:verify', 'Verify customer (KYC/Fayda)'),
|
||
perm('d1a00001-0001-4000-8000-000000000006', 'edr_freight_app:customers:reset-password', 'Trigger customer password reset'),
|
||
];
|
||
|
||
// D. Finance — payments + invoices
|
||
export const FINANCE_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('d2a00001-0001-4000-8000-000000000001', 'edr_freight_app:payments:view', 'View payments'),
|
||
perm('d2a00001-0001-4000-8000-000000000002', 'edr_freight_app:payments:verify', 'Verify/settle payment'),
|
||
perm('d2a00001-0001-4000-8000-000000000003', 'edr_freight_app:payments:refund', 'Refund payment'),
|
||
perm('d2b00001-0001-4000-8000-000000000001', 'edr_freight_app:invoices:view', 'View invoices'),
|
||
perm('d2b00001-0001-4000-8000-000000000002', 'edr_freight_app:invoices:create', 'Generate invoice'),
|
||
perm('d2b00001-0001-4000-8000-000000000003', 'edr_freight_app:invoices:cancel', 'Cancel invoice'),
|
||
perm('d2b00001-0001-4000-8000-000000000004', 'edr_freight_app:invoices:export', 'Download invoice document'),
|
||
];
|
||
|
||
// E. First / last mile operations
|
||
export const MILE_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('d3a00001-0001-4000-8000-000000000001', 'edr_freight_app:first_mile:view', 'View first-mile'),
|
||
perm('d3a00001-0001-4000-8000-000000000002', 'edr_freight_app:first_mile:accept', 'Accept first-mile request'),
|
||
perm('d3a00001-0001-4000-8000-000000000003', 'edr_freight_app:first_mile:create', 'Create first-mile'),
|
||
perm('d3a00001-0001-4000-8000-000000000004', 'edr_freight_app:first_mile:update', 'Update first-mile'),
|
||
perm('d3a00001-0001-4000-8000-000000000005', 'edr_freight_app:first_mile:delete', 'Delete first-mile'),
|
||
perm('d3a00001-0001-4000-8000-000000000006', 'edr_freight_app:first_mile:assign_vehicles', 'Assign first-mile vehicles'),
|
||
perm('d3a00001-0001-4000-8000-000000000007', 'edr_freight_app:first_mile:set_distances', 'Set first-mile distances'),
|
||
perm('d3a00001-0001-4000-8000-000000000008', 'edr_freight_app:first_mile:generate_invoice', 'Generate first-mile invoice'),
|
||
perm('d3b00001-0001-4000-8000-000000000001', 'edr_freight_app:last_mile:view', 'View last-mile'),
|
||
perm('d3b00001-0001-4000-8000-000000000002', 'edr_freight_app:last_mile:accept', 'Accept last-mile request'),
|
||
perm('d3b00001-0001-4000-8000-000000000003', 'edr_freight_app:last_mile:create', 'Create last-mile'),
|
||
perm('d3b00001-0001-4000-8000-000000000004', 'edr_freight_app:last_mile:update', 'Update last-mile'),
|
||
perm('d3b00001-0001-4000-8000-000000000005', 'edr_freight_app:last_mile:delete', 'Delete last-mile'),
|
||
perm('d3b00001-0001-4000-8000-000000000006', 'edr_freight_app:last_mile:assign_vehicles', 'Assign last-mile vehicles'),
|
||
perm('d3b00001-0001-4000-8000-000000000007', 'edr_freight_app:last_mile:set_distances', 'Set last-mile distances'),
|
||
perm('d3b00001-0001-4000-8000-000000000008', 'edr_freight_app:last_mile:generate_invoice', 'Generate last-mile invoice'),
|
||
];
|
||
|
||
// F. Fleet — rail assets (splits the flat fleet:view/manage)
|
||
export const FLEET_RAIL_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('e1a00001-0001-4000-8000-000000000001', 'edr_freight_app:locomotives:view', 'View locomotives'),
|
||
perm('e1a00001-0001-4000-8000-000000000002', 'edr_freight_app:locomotives:create', 'Create locomotive'),
|
||
perm('e1a00001-0001-4000-8000-000000000003', 'edr_freight_app:locomotives:update', 'Update locomotive'),
|
||
perm('e1a00001-0001-4000-8000-000000000004', 'edr_freight_app:locomotives:delete', 'Delete locomotive'),
|
||
perm('e1b00001-0001-4000-8000-000000000001', 'edr_freight_app:wagons:view', 'View wagons'),
|
||
perm('e1b00001-0001-4000-8000-000000000002', 'edr_freight_app:wagons:create', 'Create wagon'),
|
||
perm('e1b00001-0001-4000-8000-000000000003', 'edr_freight_app:wagons:update', 'Update wagon'),
|
||
perm('e1b00001-0001-4000-8000-000000000004', 'edr_freight_app:wagons:delete', 'Delete wagon'),
|
||
perm('e1b00001-0001-4000-8000-000000000005', 'edr_freight_app:wagons:transfer_request', 'Request wagon transfer'),
|
||
perm('e1b00001-0001-4000-8000-000000000006', 'edr_freight_app:wagons:transfer_fulfill', 'Fulfil wagon transfer (OCC)'),
|
||
perm('e1b00001-0001-4000-8000-000000000007', 'edr_freight_app:wagons:transfer_history_all', "View all staff's transfer history"),
|
||
perm('e1c00001-0001-4000-8000-000000000001', 'edr_freight_app:trains:view', 'View trains'),
|
||
perm('e1c00001-0001-4000-8000-000000000002', 'edr_freight_app:trains:create', 'Create train'),
|
||
perm('e1c00001-0001-4000-8000-000000000003', 'edr_freight_app:trains:update', 'Update train'),
|
||
perm('e1c00001-0001-4000-8000-000000000004', 'edr_freight_app:trains:delete', 'Delete train'),
|
||
perm('e1c00001-0001-4000-8000-000000000005', 'edr_freight_app:trains:assign_wagons', 'Assign wagons to train'),
|
||
perm('e1d00001-0001-4000-8000-000000000001', 'edr_freight_app:routes:view', 'View routes'),
|
||
perm('e1d00001-0001-4000-8000-000000000002', 'edr_freight_app:routes:create', 'Create route'),
|
||
perm('e1d00001-0001-4000-8000-000000000003', 'edr_freight_app:routes:update', 'Update route'),
|
||
perm('e1d00001-0001-4000-8000-000000000004', 'edr_freight_app:routes:delete', 'Delete route'),
|
||
perm('e1e00001-0001-4000-8000-000000000001', 'edr_freight_app:containers:view', 'View containers'),
|
||
perm('e1e00001-0001-4000-8000-000000000002', 'edr_freight_app:containers:create', 'Create container'),
|
||
perm('e1e00001-0001-4000-8000-000000000003', 'edr_freight_app:containers:update', 'Update container'),
|
||
perm('e1e00001-0001-4000-8000-000000000004', 'edr_freight_app:containers:delete', 'Delete container'),
|
||
perm('e1f00001-0001-4000-8000-000000000001', 'edr_freight_app:cargoes:view', 'View cargoes'),
|
||
perm('e1f00001-0001-4000-8000-000000000002', 'edr_freight_app:cargoes:create', 'Create cargo'),
|
||
perm('e1f00001-0001-4000-8000-000000000003', 'edr_freight_app:cargoes:update', 'Update cargo'),
|
||
perm('e1f00001-0001-4000-8000-000000000004', 'edr_freight_app:cargoes:delete', 'Delete cargo'),
|
||
];
|
||
|
||
// G. Fleet — road & telemetry
|
||
export const FLEET_ROAD_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('e2a00001-0001-4000-8000-000000000001', 'edr_freight_app:vehicles:view', 'View vehicles'),
|
||
perm('e2a00001-0001-4000-8000-000000000002', 'edr_freight_app:vehicles:create', 'Create vehicle'),
|
||
perm('e2a00001-0001-4000-8000-000000000003', 'edr_freight_app:vehicles:update', 'Update vehicle'),
|
||
perm('e2a00001-0001-4000-8000-000000000004', 'edr_freight_app:vehicles:delete', 'Delete vehicle'),
|
||
perm('e2b00001-0001-4000-8000-000000000001', 'edr_freight_app:drivers:view', 'View drivers'),
|
||
perm('e2b00001-0001-4000-8000-000000000002', 'edr_freight_app:drivers:create', 'Create driver'),
|
||
perm('e2b00001-0001-4000-8000-000000000003', 'edr_freight_app:drivers:update', 'Update driver'),
|
||
perm('e2b00001-0001-4000-8000-000000000004', 'edr_freight_app:drivers:delete', 'Delete driver'),
|
||
perm('e2c00001-0001-4000-8000-000000000001', 'edr_freight_app:tracking:view', 'Track vehicles'),
|
||
perm('e2c00001-0001-4000-8000-000000000002', 'edr_freight_app:tracking:manage', 'Manage GPS trackers'),
|
||
perm('e2d00001-0001-4000-8000-000000000001', 'edr_freight_app:fuel:view', 'View fuel purchases'),
|
||
perm('e2d00001-0001-4000-8000-000000000002', 'edr_freight_app:fuel:create', 'Create fuel purchase'),
|
||
perm('e2d00001-0001-4000-8000-000000000003', 'edr_freight_app:fuel:update', 'Update fuel purchase'),
|
||
perm('e2d00001-0001-4000-8000-000000000004', 'edr_freight_app:fuel:delete', 'Delete fuel purchase'),
|
||
perm('e2d00001-0001-4000-8000-000000000005', 'edr_freight_app:fuel:approve', 'Approve fuel purchase'),
|
||
perm('e2e00001-0001-4000-8000-000000000001', 'edr_freight_app:maintenance:view', 'View maintenance'),
|
||
perm('e2e00001-0001-4000-8000-000000000002', 'edr_freight_app:maintenance:create', 'Create maintenance'),
|
||
perm('e2e00001-0001-4000-8000-000000000003', 'edr_freight_app:maintenance:update', 'Update maintenance'),
|
||
perm('e2e00001-0001-4000-8000-000000000004', 'edr_freight_app:maintenance:delete', 'Delete maintenance'),
|
||
perm('e2e00001-0001-4000-8000-000000000005', 'edr_freight_app:maintenance:complete', 'Complete maintenance'),
|
||
perm('e2f00001-0001-4000-8000-000000000001', 'edr_freight_app:fleet_reports:view', 'View fleet financial reports'),
|
||
perm('e2f00001-0001-4000-8000-000000000002', 'edr_freight_app:fleet_reports:export', 'Export fleet financial reports'),
|
||
perm('e2000001-0001-4000-8000-000000000001', 'edr_freight_app:fleet_dashboard:view', 'View fleet dashboard'),
|
||
];
|
||
|
||
// H. Warehouse management
|
||
export const WAREHOUSE_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('f1000001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_dashboard:view', 'View warehouse dashboard'),
|
||
perm('f1a00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouses:view', 'View warehouses'),
|
||
perm('f1a00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouses:create', 'Create warehouse'),
|
||
perm('f1a00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouses:update', 'Update warehouse'),
|
||
perm('f1a00001-0001-4000-8000-000000000004', 'edr_freight_app:warehouses:delete', 'Delete warehouse'),
|
||
perm('f1b00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_yards:view', 'View warehouse yards'),
|
||
perm('f1b00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouse_yards:create', 'Create warehouse yard'),
|
||
perm('f1b00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouse_yards:update', 'Update warehouse yard'),
|
||
perm('f1b00001-0001-4000-8000-000000000004', 'edr_freight_app:warehouse_yards:delete', 'Delete warehouse yard'),
|
||
perm('f1c00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_zones:view', 'View warehouse zones'),
|
||
perm('f1c00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouse_zones:create', 'Create warehouse zone'),
|
||
perm('f1c00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouse_zones:update', 'Update warehouse zone'),
|
||
perm('f1d00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_allocation_rules:view', 'View allocation rules'),
|
||
perm('f1d00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouse_allocation_rules:create', 'Create allocation rule'),
|
||
perm('f1d00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouse_allocation_rules:update', 'Update allocation rule'),
|
||
perm('f1d00001-0001-4000-8000-000000000004', 'edr_freight_app:warehouse_allocation_rules:delete', 'Delete allocation rule'),
|
||
perm('f1e00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_fee_rules:view', 'View fee rules'),
|
||
perm('f1e00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouse_fee_rules:create', 'Create fee rule'),
|
||
perm('f1e00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouse_fee_rules:update', 'Update fee rule'),
|
||
perm('f1e00001-0001-4000-8000-000000000004', 'edr_freight_app:warehouse_fee_rules:delete', 'Delete fee rule'),
|
||
perm('f1f00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_inspection_reports:view', 'View inspection reports'),
|
||
perm('f1f00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouse_inspection_reports:create', 'Create inspection report'),
|
||
perm('f1f00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouse_inspection_reports:update', 'Update inspection report'),
|
||
];
|
||
|
||
// I. Port & terminal — inventory movement + interchange + fee invoices
|
||
export const PORT_TERMINAL_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('f2a00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_inventory:view', 'View terminal inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouse_inventory:receive', 'Receive inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouse_inventory:move', 'Move/store/reserve inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000004', 'edr_freight_app:warehouse_inventory:load', 'Load inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000005', 'edr_freight_app:warehouse_inventory:unload', 'Unload inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000006', 'edr_freight_app:warehouse_inventory:dispatch', 'Dispatch inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000007', 'edr_freight_app:warehouse_inventory:gate_pass', 'Gate-clearance inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000008', 'edr_freight_app:warehouse_inventory:release', 'Release inventory'),
|
||
perm('f2a00001-0001-4000-8000-000000000009', 'edr_freight_app:warehouse_inventory:deliver', 'Deliver inventory'),
|
||
perm('f2a00001-0001-4000-8000-00000000000a', 'edr_freight_app:warehouse_inventory:inspect', 'Inspect inventory'),
|
||
perm('f2b00001-0001-4000-8000-000000000001', 'edr_freight_app:interchange_documents:view', 'View interchange documents'),
|
||
perm('f2b00001-0001-4000-8000-000000000002', 'edr_freight_app:interchange_documents:generate', 'Generate interchange document'),
|
||
perm('f2b00001-0001-4000-8000-000000000003', 'edr_freight_app:interchange_documents:acknowledge', 'Acknowledge interchange document'),
|
||
perm('f2b00001-0001-4000-8000-000000000004', 'edr_freight_app:interchange_documents:dispute', 'Dispute interchange document'),
|
||
perm('f2b00001-0001-4000-8000-000000000005', 'edr_freight_app:interchange_documents:cancel', 'Cancel interchange document'),
|
||
perm('f2c00001-0001-4000-8000-000000000001', 'edr_freight_app:warehouse_fee_invoices:view', 'View warehouse fee invoices'),
|
||
perm('f2c00001-0001-4000-8000-000000000002', 'edr_freight_app:warehouse_fee_invoices:generate', 'Generate warehouse fee invoice'),
|
||
perm('f2c00001-0001-4000-8000-000000000003', 'edr_freight_app:warehouse_fee_invoices:cancel', 'Cancel warehouse fee invoice'),
|
||
perm('f2c00001-0001-4000-8000-000000000004', 'edr_freight_app:warehouse_fee_invoices:pay', 'Pay warehouse fee invoice'),
|
||
];
|
||
|
||
// E'. Train-scheduling finer actions (augment existing view/manage)
|
||
export const SCHEDULING_EXTRA_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('a2a00001-0001-4000-8000-000000000001', 'edr_freight_app:train_scheduling:create', 'Create train schedule'),
|
||
perm('a2a00001-0001-4000-8000-000000000002', 'edr_freight_app:train_scheduling:update', 'Update train schedule'),
|
||
perm('a2a00001-0001-4000-8000-000000000003', 'edr_freight_app:train_scheduling:cancel', 'Cancel train schedule'),
|
||
perm('a2a00001-0001-4000-8000-000000000004', 'edr_freight_app:train_scheduling:reschedule', 'Reschedule train'),
|
||
perm('a2a00001-0001-4000-8000-000000000005', 'edr_freight_app:train_scheduling:rules_manage', 'Manage global scheduling rules'),
|
||
];
|
||
|
||
// L. Administration & settings (split from the coarse admin umbrella)
|
||
export const CONFIG_SETTINGS_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('b3a00001-0001-4000-8000-000000000001', 'edr_freight_app:config:contract_validity:view', 'View contract validity periods'),
|
||
perm('b3a00001-0001-4000-8000-000000000002', 'edr_freight_app:config:contract_validity:manage', 'Manage contract validity periods'),
|
||
perm('b4a00001-0001-4000-8000-000000000001', 'edr_freight_app:settings:file_upload:view', 'View file-upload settings'),
|
||
perm('b4a00001-0001-4000-8000-000000000002', 'edr_freight_app:settings:file_upload:manage', 'Manage file-upload settings'),
|
||
perm('b4b00001-0001-4000-8000-000000000001', 'edr_freight_app:settings:dropdown:view', 'View dropdown settings'),
|
||
perm('b4b00001-0001-4000-8000-000000000002', 'edr_freight_app:settings:dropdown:manage', 'Manage dropdown settings'),
|
||
];
|
||
|
||
// M. Staff / IAM admin — NEW keys only. The employee_registration / role_assignment
|
||
// / hierarchy_* / position_types:view keys are seeded separately in edr-freight.seed.ts.
|
||
export const STAFF_IAM_PERMISSIONS: FreightPermissionSeed[] = [
|
||
perm('c2a00001-0001-4000-8000-000000000001', 'edr_freight_app:staff:roles:view', 'View roles'),
|
||
perm('c2a00001-0001-4000-8000-000000000002', 'edr_freight_app:staff:roles:create', 'Create role'),
|
||
perm('c2a00001-0001-4000-8000-000000000003', 'edr_freight_app:staff:roles:update', 'Update role'),
|
||
perm('c2a00001-0001-4000-8000-000000000004', 'edr_freight_app:staff:roles:delete', 'Delete role'),
|
||
perm('c2b00001-0001-4000-8000-000000000001', 'edr_freight_app:staff:permissions:view', 'View permission assignments'),
|
||
perm('c2b00001-0001-4000-8000-000000000002', 'edr_freight_app:staff:permissions:assign', 'Assign permissions'),
|
||
perm('c2c00001-0001-4000-8000-000000000001', 'edr_freight_app:position_types:create', 'Create position type'),
|
||
perm('c2c00001-0001-4000-8000-000000000002', 'edr_freight_app:position_types:update', 'Update position type'),
|
||
perm('c2c00001-0001-4000-8000-000000000003', 'edr_freight_app:position_types:delete', 'Delete position type'),
|
||
];
|
||
|
||
export const ADVANCED_BACKOFFICE_PERMISSIONS: FreightPermissionSeed[] = [
|
||
...CUSTOMER_PERMISSIONS,
|
||
...FINANCE_PERMISSIONS,
|
||
...MILE_PERMISSIONS,
|
||
...FLEET_RAIL_PERMISSIONS,
|
||
...FLEET_ROAD_PERMISSIONS,
|
||
...WAREHOUSE_PERMISSIONS,
|
||
...PORT_TERMINAL_PERMISSIONS,
|
||
...SCHEDULING_EXTRA_PERMISSIONS,
|
||
...CONFIG_SETTINGS_PERMISSIONS,
|
||
...STAFF_IAM_PERMISSIONS,
|
||
];
|
||
|
||
export const BOOKING_RULE_ENGINE_PERMISSIONS = [
|
||
...BOOKING_PERMISSIONS,
|
||
...CONTRACT_PERMISSIONS,
|
||
...RULE_ENGINE_PERMISSIONS,
|
||
...GAP_CONTROLLER_PERMISSIONS,
|
||
...ADVANCED_BACKOFFICE_PERMISSIONS,
|
||
];
|
||
|
||
export const BOOKING_RULE_ENGINE_PERMISSION_KEYS = BOOKING_RULE_ENGINE_PERMISSIONS.map(
|
||
(p) => p.key,
|
||
);
|
||
|
||
export const FREIGHT_PERMS = {
|
||
bookings: {
|
||
view: 'edr_freight_app:bookings:view',
|
||
create: 'edr_freight_app:bookings:create',
|
||
clearanceView: 'edr_freight_app:bookings:clearance_view',
|
||
staffAccept: 'edr_freight_app:bookings:staff_accept',
|
||
requestChanges: 'edr_freight_app:bookings:request_changes',
|
||
reject: 'edr_freight_app:bookings:reject',
|
||
approveLineStaff: 'edr_freight_app:bookings:approve_line_staff',
|
||
approveDirector: 'edr_freight_app:bookings:approve_director',
|
||
approveCeo: 'edr_freight_app:bookings:approve_ceo',
|
||
rejectApproval: 'edr_freight_app:bookings:reject_approval',
|
||
generateContract: 'edr_freight_app:bookings:generate_contract',
|
||
signStaff: 'edr_freight_app:bookings:sign_staff',
|
||
operations: 'edr_freight_app:bookings:operations',
|
||
cancel: 'edr_freight_app:bookings:cancel',
|
||
reviewDocuments: 'edr_freight_app:bookings:review_documents',
|
||
uploadClearanceOutput: 'edr_freight_app:bookings:upload_clearance_output',
|
||
finalizeClearance: 'edr_freight_app:bookings:finalize_clearance',
|
||
},
|
||
contracts: {
|
||
view: 'edr_freight_app:contracts:view',
|
||
staffAccept: 'edr_freight_app:contracts:staff_accept',
|
||
requestChanges: 'edr_freight_app:contracts:request_changes',
|
||
reject: 'edr_freight_app:contracts:reject',
|
||
approveLineStaff: 'edr_freight_app:contracts:approve_line_staff',
|
||
approveDirector: 'edr_freight_app:contracts:approve_director',
|
||
approveCeo: 'edr_freight_app:contracts:approve_ceo',
|
||
generateContract: 'edr_freight_app:contracts:generate_contract',
|
||
signStaff: 'edr_freight_app:contracts:sign_staff',
|
||
clearanceReview: 'edr_freight_app:contracts:clearance_review',
|
||
finalizeClearance: 'edr_freight_app:contracts:finalize_clearance',
|
||
createBooking: 'edr_freight_app:contracts:create_booking',
|
||
opsClearanceReview: 'edr_freight_app:contracts:ops_clearance_review',
|
||
clearanceEtActions: 'edr_freight_app:contracts:clearance_et_actions',
|
||
clearanceDjActions: 'edr_freight_app:contracts:clearance_dj_actions',
|
||
clearanceDutyAdvise: 'edr_freight_app:contracts:clearance_duty_advise',
|
||
},
|
||
trainScheduling: {
|
||
view: 'edr_freight_app:train_scheduling:view',
|
||
manage: 'edr_freight_app:train_scheduling:manage',
|
||
create: 'edr_freight_app:train_scheduling:create',
|
||
update: 'edr_freight_app:train_scheduling:update',
|
||
cancel: 'edr_freight_app:train_scheduling:cancel',
|
||
reschedule: 'edr_freight_app:train_scheduling:reschedule',
|
||
rulesManage: 'edr_freight_app:train_scheduling:rules_manage',
|
||
},
|
||
fleet: {
|
||
view: 'edr_freight_app:fleet:view',
|
||
manage: 'edr_freight_app:fleet:manage',
|
||
},
|
||
admin: 'edr_freight_app:admin',
|
||
ruleEngine: {
|
||
view: (slug: RuleEngineResourceSlug) =>
|
||
`edr_freight_app:rule_engine:${slugToResourceKey(slug)}:view`,
|
||
manage: (slug: RuleEngineResourceSlug) =>
|
||
`edr_freight_app:rule_engine:${slugToResourceKey(slug)}:manage`,
|
||
approve: (slug: RuleEngineApprovableSlug) =>
|
||
`edr_freight_app:rule_engine:${slugToResourceKey(slug)}:approve`,
|
||
},
|
||
allocation: {
|
||
manage: 'edr_freight_app:allocation:manage',
|
||
},
|
||
customers: {
|
||
view: 'edr_freight_app:customers:view',
|
||
create: 'edr_freight_app:customers:create',
|
||
update: 'edr_freight_app:customers:update',
|
||
deactivate: 'edr_freight_app:customers:deactivate',
|
||
verify: 'edr_freight_app:customers:verify',
|
||
resetPassword: 'edr_freight_app:customers:reset-password',
|
||
},
|
||
payments: {
|
||
view: 'edr_freight_app:payments:view',
|
||
verify: 'edr_freight_app:payments:verify',
|
||
refund: 'edr_freight_app:payments:refund',
|
||
},
|
||
invoices: {
|
||
view: 'edr_freight_app:invoices:view',
|
||
create: 'edr_freight_app:invoices:create',
|
||
cancel: 'edr_freight_app:invoices:cancel',
|
||
export: 'edr_freight_app:invoices:export',
|
||
},
|
||
firstMile: {
|
||
view: 'edr_freight_app:first_mile:view',
|
||
accept: 'edr_freight_app:first_mile:accept',
|
||
create: 'edr_freight_app:first_mile:create',
|
||
update: 'edr_freight_app:first_mile:update',
|
||
delete: 'edr_freight_app:first_mile:delete',
|
||
assignVehicles: 'edr_freight_app:first_mile:assign_vehicles',
|
||
setDistances: 'edr_freight_app:first_mile:set_distances',
|
||
generateInvoice: 'edr_freight_app:first_mile:generate_invoice',
|
||
},
|
||
lastMile: {
|
||
view: 'edr_freight_app:last_mile:view',
|
||
accept: 'edr_freight_app:last_mile:accept',
|
||
create: 'edr_freight_app:last_mile:create',
|
||
update: 'edr_freight_app:last_mile:update',
|
||
delete: 'edr_freight_app:last_mile:delete',
|
||
assignVehicles: 'edr_freight_app:last_mile:assign_vehicles',
|
||
setDistances: 'edr_freight_app:last_mile:set_distances',
|
||
generateInvoice: 'edr_freight_app:last_mile:generate_invoice',
|
||
},
|
||
locomotives: {
|
||
view: 'edr_freight_app:locomotives:view',
|
||
create: 'edr_freight_app:locomotives:create',
|
||
update: 'edr_freight_app:locomotives:update',
|
||
delete: 'edr_freight_app:locomotives:delete',
|
||
},
|
||
wagons: {
|
||
view: 'edr_freight_app:wagons:view',
|
||
create: 'edr_freight_app:wagons:create',
|
||
update: 'edr_freight_app:wagons:update',
|
||
delete: 'edr_freight_app:wagons:delete',
|
||
// Requester creates a transfer request; OCC fulfils it (picks the wagons and
|
||
// executes the move). Distinct keys so OCC can hold fulfil without request.
|
||
transferRequest: 'edr_freight_app:wagons:transfer_request',
|
||
transferFulfill: 'edr_freight_app:wagons:transfer_fulfill',
|
||
// Admin: read every staffer's transfer history. Without it, a user only sees
|
||
// their own (the /history endpoint uses the caller id, backend-enforced).
|
||
transferHistoryAll: 'edr_freight_app:wagons:transfer_history_all',
|
||
},
|
||
trains: {
|
||
view: 'edr_freight_app:trains:view',
|
||
create: 'edr_freight_app:trains:create',
|
||
update: 'edr_freight_app:trains:update',
|
||
delete: 'edr_freight_app:trains:delete',
|
||
assignWagons: 'edr_freight_app:trains:assign_wagons',
|
||
},
|
||
routes: {
|
||
view: 'edr_freight_app:routes:view',
|
||
create: 'edr_freight_app:routes:create',
|
||
update: 'edr_freight_app:routes:update',
|
||
delete: 'edr_freight_app:routes:delete',
|
||
},
|
||
containers: {
|
||
view: 'edr_freight_app:containers:view',
|
||
create: 'edr_freight_app:containers:create',
|
||
update: 'edr_freight_app:containers:update',
|
||
delete: 'edr_freight_app:containers:delete',
|
||
},
|
||
cargoes: {
|
||
view: 'edr_freight_app:cargoes:view',
|
||
create: 'edr_freight_app:cargoes:create',
|
||
update: 'edr_freight_app:cargoes:update',
|
||
delete: 'edr_freight_app:cargoes:delete',
|
||
},
|
||
vehicles: {
|
||
view: 'edr_freight_app:vehicles:view',
|
||
create: 'edr_freight_app:vehicles:create',
|
||
update: 'edr_freight_app:vehicles:update',
|
||
delete: 'edr_freight_app:vehicles:delete',
|
||
},
|
||
drivers: {
|
||
view: 'edr_freight_app:drivers:view',
|
||
create: 'edr_freight_app:drivers:create',
|
||
update: 'edr_freight_app:drivers:update',
|
||
delete: 'edr_freight_app:drivers:delete',
|
||
},
|
||
tracking: {
|
||
view: 'edr_freight_app:tracking:view',
|
||
manage: 'edr_freight_app:tracking:manage',
|
||
},
|
||
fuel: {
|
||
view: 'edr_freight_app:fuel:view',
|
||
create: 'edr_freight_app:fuel:create',
|
||
update: 'edr_freight_app:fuel:update',
|
||
delete: 'edr_freight_app:fuel:delete',
|
||
approve: 'edr_freight_app:fuel:approve',
|
||
},
|
||
maintenance: {
|
||
view: 'edr_freight_app:maintenance:view',
|
||
create: 'edr_freight_app:maintenance:create',
|
||
update: 'edr_freight_app:maintenance:update',
|
||
delete: 'edr_freight_app:maintenance:delete',
|
||
complete: 'edr_freight_app:maintenance:complete',
|
||
},
|
||
fleetReports: {
|
||
view: 'edr_freight_app:fleet_reports:view',
|
||
export: 'edr_freight_app:fleet_reports:export',
|
||
},
|
||
fleetDashboard: {
|
||
view: 'edr_freight_app:fleet_dashboard:view',
|
||
},
|
||
warehouseDashboard: {
|
||
view: 'edr_freight_app:warehouse_dashboard:view',
|
||
},
|
||
warehouses: {
|
||
view: 'edr_freight_app:warehouses:view',
|
||
create: 'edr_freight_app:warehouses:create',
|
||
update: 'edr_freight_app:warehouses:update',
|
||
delete: 'edr_freight_app:warehouses:delete',
|
||
},
|
||
warehouseYards: {
|
||
view: 'edr_freight_app:warehouse_yards:view',
|
||
create: 'edr_freight_app:warehouse_yards:create',
|
||
update: 'edr_freight_app:warehouse_yards:update',
|
||
delete: 'edr_freight_app:warehouse_yards:delete',
|
||
},
|
||
warehouseZones: {
|
||
view: 'edr_freight_app:warehouse_zones:view',
|
||
create: 'edr_freight_app:warehouse_zones:create',
|
||
update: 'edr_freight_app:warehouse_zones:update',
|
||
},
|
||
warehouseAllocationRules: {
|
||
view: 'edr_freight_app:warehouse_allocation_rules:view',
|
||
create: 'edr_freight_app:warehouse_allocation_rules:create',
|
||
update: 'edr_freight_app:warehouse_allocation_rules:update',
|
||
delete: 'edr_freight_app:warehouse_allocation_rules:delete',
|
||
},
|
||
warehouseFeeRules: {
|
||
view: 'edr_freight_app:warehouse_fee_rules:view',
|
||
create: 'edr_freight_app:warehouse_fee_rules:create',
|
||
update: 'edr_freight_app:warehouse_fee_rules:update',
|
||
delete: 'edr_freight_app:warehouse_fee_rules:delete',
|
||
},
|
||
warehouseInspectionReports: {
|
||
view: 'edr_freight_app:warehouse_inspection_reports:view',
|
||
create: 'edr_freight_app:warehouse_inspection_reports:create',
|
||
update: 'edr_freight_app:warehouse_inspection_reports:update',
|
||
},
|
||
warehouseInventory: {
|
||
view: 'edr_freight_app:warehouse_inventory:view',
|
||
receive: 'edr_freight_app:warehouse_inventory:receive',
|
||
move: 'edr_freight_app:warehouse_inventory:move',
|
||
load: 'edr_freight_app:warehouse_inventory:load',
|
||
unload: 'edr_freight_app:warehouse_inventory:unload',
|
||
dispatch: 'edr_freight_app:warehouse_inventory:dispatch',
|
||
gatePass: 'edr_freight_app:warehouse_inventory:gate_pass',
|
||
release: 'edr_freight_app:warehouse_inventory:release',
|
||
deliver: 'edr_freight_app:warehouse_inventory:deliver',
|
||
inspect: 'edr_freight_app:warehouse_inventory:inspect',
|
||
},
|
||
interchangeDocuments: {
|
||
view: 'edr_freight_app:interchange_documents:view',
|
||
generate: 'edr_freight_app:interchange_documents:generate',
|
||
acknowledge: 'edr_freight_app:interchange_documents:acknowledge',
|
||
dispute: 'edr_freight_app:interchange_documents:dispute',
|
||
cancel: 'edr_freight_app:interchange_documents:cancel',
|
||
},
|
||
warehouseFeeInvoices: {
|
||
view: 'edr_freight_app:warehouse_fee_invoices:view',
|
||
generate: 'edr_freight_app:warehouse_fee_invoices:generate',
|
||
cancel: 'edr_freight_app:warehouse_fee_invoices:cancel',
|
||
pay: 'edr_freight_app:warehouse_fee_invoices:pay',
|
||
},
|
||
config: {
|
||
contractValidity: {
|
||
view: 'edr_freight_app:config:contract_validity:view',
|
||
manage: 'edr_freight_app:config:contract_validity:manage',
|
||
},
|
||
},
|
||
settings: {
|
||
fileUpload: {
|
||
view: 'edr_freight_app:settings:file_upload:view',
|
||
manage: 'edr_freight_app:settings:file_upload:manage',
|
||
},
|
||
dropdown: {
|
||
view: 'edr_freight_app:settings:dropdown:view',
|
||
manage: 'edr_freight_app:settings:dropdown:manage',
|
||
},
|
||
},
|
||
staff: {
|
||
roles: {
|
||
view: 'edr_freight_app:staff:roles:view',
|
||
create: 'edr_freight_app:staff:roles:create',
|
||
update: 'edr_freight_app:staff:roles:update',
|
||
delete: 'edr_freight_app:staff:roles:delete',
|
||
},
|
||
permissions: {
|
||
view: 'edr_freight_app:staff:permissions:view',
|
||
assign: 'edr_freight_app:staff:permissions:assign',
|
||
},
|
||
// Seeded in edr-freight.seed.ts (EDR_FREIGHT_PERMISSIONS) — surfaced here for gating.
|
||
employeeRegistration: {
|
||
view: 'edr_freight_app:employee_registration:view',
|
||
create: 'edr_freight_app:employee_registration:create',
|
||
update: 'edr_freight_app:employee_registration:update',
|
||
activate: 'edr_freight_app:employee_registration:activate',
|
||
deactivate: 'edr_freight_app:employee_registration:deactivate',
|
||
},
|
||
roleAssignment: {
|
||
view: 'edr_freight_app:role_assignment:view',
|
||
assign: 'edr_freight_app:role_assignment:assign',
|
||
replace: 'edr_freight_app:role_assignment:replace',
|
||
},
|
||
hierarchyUnits: {
|
||
view: 'edr_freight_app:hierarchy_units:view',
|
||
create: 'edr_freight_app:hierarchy_units:create',
|
||
update: 'edr_freight_app:hierarchy_units:update',
|
||
delete: 'edr_freight_app:hierarchy_units:delete',
|
||
},
|
||
hierarchyPositions: {
|
||
view: 'edr_freight_app:hierarchy_positions:view',
|
||
create: 'edr_freight_app:hierarchy_positions:create',
|
||
update: 'edr_freight_app:hierarchy_positions:update',
|
||
delete: 'edr_freight_app:hierarchy_positions:delete',
|
||
changeParent: 'edr_freight_app:hierarchy_positions:change_parent',
|
||
},
|
||
hierarchyEmployeeAssignment: {
|
||
view: 'edr_freight_app:hierarchy_employee_assignment:view',
|
||
invite: 'edr_freight_app:hierarchy_employee_assignment:invite',
|
||
assign: 'edr_freight_app:hierarchy_employee_assignment:assign',
|
||
},
|
||
positionTypes: {
|
||
view: 'edr_freight_app:position_types:view',
|
||
create: 'edr_freight_app:position_types:create',
|
||
update: 'edr_freight_app:position_types:update',
|
||
delete: 'edr_freight_app:position_types:delete',
|
||
},
|
||
},
|
||
} as const;
|
||
|
||
const allRuleEngineViewKeys = () =>
|
||
RULE_ENGINE_RESOURCE_SLUGS.map((s) => FREIGHT_PERMS.ruleEngine.view(s));
|
||
|
||
export const ROLE_PERMISSION_PRESETS = {
|
||
// Marketing / line staff: drives a booking from intake through line-staff
|
||
// approval and contract generation/signing — i.e. until the contract is ready
|
||
// and signed. No director/CEO approval, no scheduling, no operations.
|
||
lineStaff: [
|
||
FREIGHT_PERMS.bookings.view,
|
||
FREIGHT_PERMS.bookings.staffAccept,
|
||
FREIGHT_PERMS.bookings.requestChanges,
|
||
FREIGHT_PERMS.bookings.reject,
|
||
FREIGHT_PERMS.bookings.approveLineStaff,
|
||
FREIGHT_PERMS.bookings.rejectApproval,
|
||
FREIGHT_PERMS.bookings.cancel,
|
||
FREIGHT_PERMS.contracts.view,
|
||
FREIGHT_PERMS.contracts.staffAccept,
|
||
FREIGHT_PERMS.contracts.requestChanges,
|
||
FREIGHT_PERMS.contracts.reject,
|
||
FREIGHT_PERMS.contracts.approveLineStaff,
|
||
...allRuleEngineViewKeys(),
|
||
],
|
||
// Operations Officer: train scheduling + wagon allocation + transit/complete
|
||
// + fleet management (wagons, trains, locomotives, routes, containers, cargo).
|
||
operationsOfficer: [
|
||
FREIGHT_PERMS.bookings.view,
|
||
FREIGHT_PERMS.bookings.operations,
|
||
FREIGHT_PERMS.trainScheduling.view,
|
||
FREIGHT_PERMS.trainScheduling.manage,
|
||
FREIGHT_PERMS.fleet.view,
|
||
FREIGHT_PERMS.fleet.manage,
|
||
// Path A (no customs): Operations reviews the customer's self-clearance docs
|
||
// — on the contract for ONE_TIME contracts, and PER BOOKING for GENERAL
|
||
// contracts (booking-level document review → finalize → CLEARANCE_READY).
|
||
FREIGHT_PERMS.contracts.view,
|
||
FREIGHT_PERMS.contracts.opsClearanceReview,
|
||
FREIGHT_PERMS.bookings.clearanceView,
|
||
FREIGHT_PERMS.bookings.reviewDocuments,
|
||
FREIGHT_PERMS.bookings.finalizeClearance,
|
||
...allRuleEngineViewKeys(),
|
||
],
|
||
director: [
|
||
FREIGHT_PERMS.bookings.view,
|
||
FREIGHT_PERMS.bookings.approveDirector,
|
||
FREIGHT_PERMS.bookings.rejectApproval,
|
||
FREIGHT_PERMS.bookings.generateContract,
|
||
FREIGHT_PERMS.contracts.view,
|
||
FREIGHT_PERMS.contracts.approveDirector,
|
||
FREIGHT_PERMS.contracts.generateContract,
|
||
...allRuleEngineViewKeys(),
|
||
],
|
||
ceo: [
|
||
FREIGHT_PERMS.bookings.view,
|
||
FREIGHT_PERMS.bookings.approveCeo,
|
||
FREIGHT_PERMS.bookings.rejectApproval,
|
||
FREIGHT_PERMS.contracts.view,
|
||
FREIGHT_PERMS.contracts.approveCeo,
|
||
...allRuleEngineViewKeys(),
|
||
],
|
||
finance: [FREIGHT_PERMS.bookings.view],
|
||
// Global Logistics: manages ONLY the customs-clearance queue. Scoped out of
|
||
// the general booking-request list (no bookings:view) — instead a dedicated
|
||
// clearance:view permission lists the clearance bookings. Reviews customer
|
||
// clearance documents, uploads customs output documents, and finalizes the
|
||
// clearance gate.
|
||
// GL Ethiopia (edr_gl_ethiopia): reviews pre-booking clearance docs on the
|
||
// contract, uploads ET output docs, finalizes clearance, and EXCLUSIVELY creates
|
||
// the booking under a customs contract (Path B). Also runs post-booking ET
|
||
// milestones + the legacy booking-clearance permissions during migration.
|
||
glEthiopia: [
|
||
FREIGHT_PERMS.contracts.view,
|
||
FREIGHT_PERMS.contracts.clearanceReview,
|
||
FREIGHT_PERMS.contracts.finalizeClearance,
|
||
FREIGHT_PERMS.contracts.createBooking,
|
||
FREIGHT_PERMS.contracts.clearanceEtActions,
|
||
FREIGHT_PERMS.contracts.clearanceDutyAdvise,
|
||
FREIGHT_PERMS.bookings.clearanceView,
|
||
FREIGHT_PERMS.bookings.reviewDocuments,
|
||
FREIGHT_PERMS.bookings.uploadClearanceOutput,
|
||
FREIGHT_PERMS.bookings.finalizeClearance,
|
||
FREIGHT_PERMS.bookings.operations,
|
||
],
|
||
// GL Djibouti (edr_gl_djibouti): DO/RO collection, gatepass, loading milestones,
|
||
// damage reports. Read-only on the contract; no booking creation.
|
||
glDjibouti: [
|
||
FREIGHT_PERMS.contracts.view,
|
||
FREIGHT_PERMS.contracts.clearanceDjActions,
|
||
FREIGHT_PERMS.bookings.clearanceView,
|
||
FREIGHT_PERMS.bookings.uploadClearanceOutput,
|
||
FREIGHT_PERMS.bookings.operations,
|
||
],
|
||
// Marketing handles intake through contract (same as line staff here) and,
|
||
// for non-customs bookings, reviews/finalizes the customer's clearance
|
||
// documents from the booking detail (customs bookings go to Global Logistics).
|
||
marketing: [
|
||
FREIGHT_PERMS.bookings.view,
|
||
FREIGHT_PERMS.bookings.staffAccept,
|
||
FREIGHT_PERMS.bookings.requestChanges,
|
||
FREIGHT_PERMS.bookings.reject,
|
||
FREIGHT_PERMS.bookings.approveLineStaff,
|
||
FREIGHT_PERMS.bookings.rejectApproval,
|
||
FREIGHT_PERMS.bookings.cancel,
|
||
FREIGHT_PERMS.bookings.generateContract,
|
||
FREIGHT_PERMS.bookings.signStaff,
|
||
FREIGHT_PERMS.bookings.reviewDocuments,
|
||
FREIGHT_PERMS.bookings.finalizeClearance,
|
||
FREIGHT_PERMS.contracts.view,
|
||
FREIGHT_PERMS.contracts.staffAccept,
|
||
FREIGHT_PERMS.contracts.requestChanges,
|
||
FREIGHT_PERMS.contracts.reject,
|
||
FREIGHT_PERMS.contracts.approveLineStaff,
|
||
FREIGHT_PERMS.contracts.generateContract,
|
||
FREIGHT_PERMS.contracts.signStaff,
|
||
],
|
||
orgManager: [...BOOKING_RULE_ENGINE_PERMISSION_KEYS],
|
||
} as const;
|
||
|
||
/**
|
||
* Position permission presets (positions-as-roles). Grants flow to users via
|
||
* Position → PositionPermission (NOT Role/RolePermission). Each reuses the
|
||
* matching ROLE_PERMISSION_PRESETS key-array as a building block and adds the
|
||
* gap-controller keys the position needs. Deduped via Set.
|
||
*/
|
||
const dedupe = (keys: string[]): string[] => [...new Set(keys)];
|
||
|
||
export const POSITION_PERMISSION_PRESETS = {
|
||
// Chief: senior operational role — intake/line-staff approval + director
|
||
// approval + scheduling/ops, plus container allocation.
|
||
chief: dedupe([
|
||
...ROLE_PERMISSION_PRESETS.lineStaff,
|
||
...ROLE_PERMISSION_PRESETS.director,
|
||
...ROLE_PERMISSION_PRESETS.operationsOfficer,
|
||
FREIGHT_PERMS.allocation.manage,
|
||
]),
|
||
director: dedupe([...ROLE_PERMISSION_PRESETS.director]),
|
||
ceo: dedupe([...ROLE_PERMISSION_PRESETS.ceo]),
|
||
ethiopianGl: dedupe([...ROLE_PERMISSION_PRESETS.glEthiopia]),
|
||
djiboutiGl: dedupe([...ROLE_PERMISSION_PRESETS.glDjibouti]),
|
||
marketer: dedupe([...ROLE_PERMISSION_PRESETS.marketing]),
|
||
operation: dedupe([
|
||
...ROLE_PERMISSION_PRESETS.operationsOfficer,
|
||
FREIGHT_PERMS.allocation.manage,
|
||
]),
|
||
// Operations Chief: full operational authority — the entire freight
|
||
// permission catalog (all CRUD across bookings, contracts, scheduling,
|
||
// fleet, warehouse, mile, finance, settings, staff).
|
||
operationsChief: dedupe([...BOOKING_RULE_ENGINE_PERMISSION_KEYS]),
|
||
// Dispatcher: full CRUD on warehouse management (incl. import/export/intercity
|
||
// inventory flows) and fleet management, plus truck dispatch on the mile legs
|
||
// and operational context. The ONE carve-out: allocation & fee rules stay
|
||
// VIEW-ONLY — a dispatcher never creates/updates/deletes those rules.
|
||
dispatcher: dedupe([
|
||
// Warehouse management — full CRUD.
|
||
FREIGHT_PERMS.warehouseDashboard.view,
|
||
...Object.values(FREIGHT_PERMS.warehouses),
|
||
...Object.values(FREIGHT_PERMS.warehouseYards),
|
||
...Object.values(FREIGHT_PERMS.warehouseZones),
|
||
...Object.values(FREIGHT_PERMS.warehouseInventory),
|
||
...Object.values(FREIGHT_PERMS.warehouseInspectionReports),
|
||
...Object.values(FREIGHT_PERMS.interchangeDocuments),
|
||
...Object.values(FREIGHT_PERMS.warehouseFeeInvoices),
|
||
// View-only on the rules that govern allocation and fees.
|
||
FREIGHT_PERMS.warehouseAllocationRules.view,
|
||
FREIGHT_PERMS.warehouseFeeRules.view,
|
||
// Fleet management — full CRUD.
|
||
...Object.values(FREIGHT_PERMS.fleet),
|
||
FREIGHT_PERMS.fleetDashboard.view,
|
||
...Object.values(FREIGHT_PERMS.fleetReports),
|
||
...Object.values(FREIGHT_PERMS.vehicles),
|
||
...Object.values(FREIGHT_PERMS.drivers),
|
||
...Object.values(FREIGHT_PERMS.tracking),
|
||
...Object.values(FREIGHT_PERMS.fuel),
|
||
...Object.values(FREIGHT_PERMS.maintenance),
|
||
...Object.values(FREIGHT_PERMS.locomotives),
|
||
...Object.values(FREIGHT_PERMS.wagons),
|
||
...Object.values(FREIGHT_PERMS.trains),
|
||
...Object.values(FREIGHT_PERMS.routes),
|
||
...Object.values(FREIGHT_PERMS.containers),
|
||
...Object.values(FREIGHT_PERMS.cargoes),
|
||
// Truck dispatch on the EDR mile legs + operational context.
|
||
...Object.values(FREIGHT_PERMS.firstMile),
|
||
...Object.values(FREIGHT_PERMS.lastMile),
|
||
FREIGHT_PERMS.trainScheduling.view,
|
||
FREIGHT_PERMS.bookings.operations,
|
||
]),
|
||
} as const;
|
||
|
||
/** Derive the module bucket from the resource segment of a permission key. */
|
||
const moduleOf = (key: string): string => key.split(':')[1] ?? 'other';
|
||
|
||
export const PERMISSIONS_CATALOG = BOOKING_RULE_ENGINE_PERMISSIONS.map((p) => ({
|
||
key: p.key,
|
||
label: p.name.en,
|
||
module: moduleOf(p.key),
|
||
}));
|