New freight.additional_charge table, independent of BookingClearanceCharge
(unbounded per booking, free-text reason). Draft -> send issues an invoice
and notifies the customer in-app/SMS/email; settles via the standard
.invoice.paid event. Adds the Additional charges row-menu entry
next to Cancel booking, permission-gated.
Not included: the Additional Payments tab UI, add-charge modal, portal pay
flow.
- Add migration for consolidation approvals table and status enum
- Create ConsolidationApprovalService to handle approval logic
- Implement repository for managing consolidation approvals
- Add entity for consolidation approval with necessary fields
- Develop frontend components for displaying and managing consolidation approvals
- Create tests for consolidation approval service to ensure correct behavior
Adds cancel, sales/withholding receipt filing + listing + PDF download, and
credit/debit memo issuance to EimsFilingCard, each gated on its own
permission.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New logo-settings module (mirrors stamp-settings): single uploaded logo,
stored via FilesService/MinIO, injected as a data URL into invoice/receipt,
contract, warehouse, train-scheduling, and payment-receipt PDFs. Adds a
matching backoffice settings page and settings:logo:view/manage permissions.
>
- Implement ShippingLineCompaniesService for registering and managing shipping line companies.
- Create ResendActivationAction component for resending activation links to shipping lines.
- Develop ShippingLineCompaniesPage for listing and registering shipping lines with validation.
- Introduce shippingLineCompanies.service for API interactions related to shipping lines.
- Define types for shipping line companies, including registration and pagination.
- Add placeholder pages for shipping line portal, including home, bookings, help, invoices, and settings.
- Implemented utility to calculate wagon usage metrics for train schedules.
- Created for sending wagons to maintenance with optional notes.
- Added unit tests for train builder maintenance functionalities, including formatting train run labels and building maintenance notes.
- Developed component for merging train schedules with detailed previews and reasons for merging.
- Introduced component for selecting wagons with search functionality and selection limits.
- Created for displaying and filtering audit logs, including detailed views of individual log entries.
- Added for handling API interactions related to audit logs, including fetching logs and entity types.
They hold a TIN but no business licence, so there is no eTrade record to look
their registration up in. A checkbox on the first wizard step marks them, and
everything that assumed a trade licence bends around it:
- The company step replaces the eTrade lookup with typed registration details
— name, region, zone, woreda, kebele, house number — required exactly because
they are now on screen. applyEtradeSourcedFields skips the lookup rather than
failing it, so what the customer sends is what is stored.
- No freight-forwarder role. Forwarding is licensed work, so the option is not
offered, and the API refuses it at start-onboarding and at every later
role-add rather than letting approval fail on a document they cannot produce.
- No per-role business-licence upload, client-side or in the completion gate.
- Their own document set (company_onboarding_documents_cooperative) merges on
top of the nationality one, admin-managed like every other set. Nationality
wins a fileKey collision so no slot renders twice, and the DARS paper is not
injected into it — the set it merges onto already carries one.
- The owner is typed in full; with no eTrade manager on file the licence
comparison reports "nothing to compare against", which backoffice now
explains rather than leaving as a bare dash.
Stored as an attributes flag, not a column: everything it changes is
behavioural, and nothing queries or joins on it.
feat(train-builder): update permissions checks for train actions in UI
feat(contracts): enhance contract view and shipment request pages with new features
test(shipment-preview): add tests for customs clearing logic in booking preview
style(contract-sign-bar): create CSS for fixed sign bar layout
Now that every fleet-resource page and settings page has its own
dedicated permission key (previous commit), the broad fallbacks are
redundant and over-grant: anyone holding only fleet:view/fleet:manage
or admin could reach every page in that whole section, not just one.
Removed fleet.view fallback from: Routes, Locomotives, Train Builder,
Wagons, Containers, Cargoes, Compliance & Alerts, Procurement, and the
Overview dashboard's Fleet KPI tab.
Removed fleet.manage fallback from: canFleetAction() (per-resource
fleet CRUD, lib/permissions.ts) and TrainBuilderDetailPage's wagon-
assignment check. Hard-delete already had no such fallback.
Removed admin fallback from: File settings, Dropdown settings,
Contract templates, Portal content, Trade access, Exchange rate.
Left untouched: Incidents (sole gate is fleet.view — no dedicated
edr_freight_app:incidents:* key exists on the backend yet, so there's
nothing to fall back FROM; removing it would make the page
super-admin-only).
Access-narrowing change: anyone currently relying on the coarse grant
without also holding the specific resource/settings key will lose
access to these pages until roles are updated to grant the specific
keys directly. Audit role assignments before this deploys.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two gaps that only bite in production: nobody could see an invoice's filing
state, and a blocked chain was visible only in the logs.
A failed filing now notifies the staff who can act on it. An ambiguous result
is HIGH priority because it blocks every further invoice for the system number
until someone resolves it, and nothing else would surface that -- the sweep
just goes quiet. A deterministic rejection affects one invoice, so it is
normal priority. The alert never throws: it must not mask the filing outcome.
The backoffice invoice detail page gains an EIMS card showing status, IRN,
counter, submitted and acknowledged timestamps, and the gateway's own error
message, with actions gated on invoices:eims_register. FAILED offers "File
again" -- the reservation model already allows re-registering a rejected
invoice, so retry needed no new endpoint. UNKNOWN offers no re-file button at
all, since resubmitting risks a duplicate registration, and instead explains
that a supervisor must record the IRN or discard the attempt.
Also aligns the migration class name with its renamed file. The DDL is
idempotent, so re-applying under the new name is a no-op against the columns;
it leaves one superseded row in freight.migrations.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mirrors the new keys in lib/permissions.ts, wraps the warehouse,
overview, reports, support and booking-request routes in
RequirePermission, and gates the dispatch, mark-paid, invoice pay/cancel,
export and support-send actions behind their own keys. Removes duplicate
route blocks.
- Implemented a method in to permanently delete wagons without history.
- Added corresponding permissions for hard delete actions in .
- Updated the UI components to include purge actions, ensuring they are only available to users with the appropriate permissions.
- Created modals for confirming permanent deletions in and .
- Enhanced API services to handle purge requests for locomotives, wagons, and routes.
- Added tests for the purge functionality in both and services to ensure proper behavior and error handling.
- Added functionality to cancel contracts, allowing users to provide a reason for cancellation.
- Updated contract statuses to include SUSPENDED and changed CLOSED to COMPLETED.
- Enhanced the UI to reflect the new cancellation option and updated messaging for contract statuses.
- Refactored contract booking actions to accommodate changes in booking logic for ONE_TIME and GENERAL contracts.
- Removed clearance document management from the contract detail page, as it is now handled per booking.
- Introduced a SQL script to reset bookings and train schedules for development purposes.
- Add TransferFulfillModal for fulfilling wagon transfer requests.
- Create TransferRequestFormModal for filing new wagon transfer requests.
- Introduce TransferCloseShortModal for closing requests that cannot be fully fulfilled.
- Develop WagonTransfersPage to manage and display wagon transfer requests.
- Implement utility functions for handling wagon transfer request data and UI components.
- Enhance UI with Mantine components for better user experience.
- 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.
- Introduced StampUpload component for uploading company stamp images.
- Integrated stamp upload in contract signing modal, supporting PNG and JPG formats.
- Implemented validation for file type and size (max 5 MB).
- Added visual feedback for drag-and-drop functionality.
- Updated contract-related pages to handle duplicate contract alerts and pricing notices.
- Enhanced contract expiry management with a nightly sweep service.
- Added unit tests for new features and updated existing tests for contract handling.
- Implement full train import journey with six container bookings filling a 54-wagon train.
- Create tests for split offer and rebooking scenarios, handling payment expiry and waiting list promotions.
- Add tests for handling waiting bookings expiration when the train is full.
- Implement tests for reopening booking windows after expired reservations.
- Seed database with necessary corridor data for import flows, including yards, container types, locomotives, and rates.