Extract the truck column list to TRUCK_COLUMNS and drive both the table
head and a per-booking label row from it, so an expanded booking's rows
are labelled without scrolling back to the head.
Enable per-truck editing of warehouse gate arrival/departure times
(arrivedAt/departedAt) via modal on Import Trucks page. Accessible via
row action menu for EDR-haulage trucks. Includes backend endpoint
POST /last-mile/:id/warehouse-gate-times and frontend modal with
DateTimePicker inputs.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Show per-truck warehouse gate arrival (arrivedAt) and departure
(departedAt) timestamps on the Import Trucks page, enabling staff to see
when each truck entered and exited the warehouse. Times displayed in local
format; EDR and customer trucks both supported.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Introduced ContractCourtBadge to display the responsible party for contract actions.
- Updated ContractStatusBadge to include new court badge.
- Enhanced ClearanceDocumentsPage with additional filters for trade direction, freight type, and ownership.
- Modified ContractRequestDetailPage and ContractRequestsPage to utilize ContractCourtBadge.
Booking detail now has a Trucks tab displaying every EDR or customer truck
assigned to a booking's last mile. Each row shows warehouse-gate times
(arrival/departure) and destination-detention times (arrival/return), with
detention costs and inspection status. Detention rows only for EDR trucks;
customer self-haul shows —. Reuses existing TruckDetentionModal and
FeePreviewModal for edit/view actions.
Backend: arrivalTrucksForBooking() adds lastMileId per truck (direct chain to
detention preview), containerItems() adds inspection_status column to responses.
No new SQL, no migrations, no new endpoints.
Frontend: BookingTrucksPanel.tsx self-fetches all data via existing warehouse +
last-mile services, renders adaptive table with cargo-cost strip above.
Wired into BookingRequestDetailPage.tsx tab bar.
- FaydaVerifyPanel + /callback popup flow for owner and poa
- general manager is a plain typed role again, offers "same as
verified owner" copy instead of being fayda-verified itself
- company step gates on owner verification (ethiopian) or typed
passport number (foreign); poa step gates on poa verification
- settings tabs (company profile, general manager, poa) updated to
match
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
getAdminRoleInfo picked a user's unit_admin role by role key alone —
a unit-admin grant carries only a unitId, no organizationId, so a user
who is unit-admin in one org and (say) org-admin in another had the
wrong unit attached to their row wherever both orgs share the viewer's
admin list. That wrong unitId then flowed into the remove action,
which deletes by exact {userId, roleId, unitId} match — a legitimate
0-match, surfaced as "user_role_not_found", removal silently failing.
Fetches the selected org's unit ids (same pattern as the position-type
form's org→units scoping) and requires the unit-admin grant's unitId
to be one of them before treating it as this org's grant.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@tria-plc/iamapi-common throws BadRequestException with a raw,
untranslated code as the message (e.g. "user_role_not_found",
"unit_employee_limit_reached:5") — useErrorHandler's extractMessage
returned that string verbatim, so removing an org/unit admin whose
role row didn't match, or inviting past a unit's employee cap, toasted
the raw backend code instead of an explanation. Adds a small code→i18n
map checked before the raw-message fallback, shared by both the async
and sync error handlers so every caller (org-admin removal, employee
invites, etc.) picks it up for free.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was no UI to assign permissions to the Organization Admin role,
even though the backend's Role→Permission endpoints
(@tria-plc/iamapi-common's role-permissions routes) were already live
and unused. Adds a dedicated page — application picker + the existing
permission checklist — that assigns/reads permissions for the fixed
Organization Admin role, linked from the Organization Admins page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The "Copy Permissions From" dropdown in the position-type form only
filtered candidates by the selected organization's full unit set,
ignoring the form's own "Select Unit" field entirely — so switching
units never re-scoped the list, unlike the equivalent unit filter on
the position-management table.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 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.
GRN-<DIR>-<DATE>-<REF8> carried no owner, so a note couldn't be
identified by who owns the cargo. Add an owner segment sourced from the
booking's company at every generation point (import, export, facility,
manual receive), keep REF8 for uniqueness, and label the GRN document
row Owner's Name.