Empty container returns now generate a downloadable Equipment Interchange Receipt: container number & size, exact return timestamp, depot/location, condition, and the carrier/booking reference. Customers can download it from their booking's Documents tab (own-booking returns only); staff can pull any via the same endpoint.
Backoffice: new tab on the booking detail page (?tab=additional-charges,
already linked from the row menu) with an Add Charge modal — Save draft or
Send to customer.
Portal: charges panel on the booking detail page, Pay now per charge via
the existing OTP/CBE-bill payment flow.
Also fixes: GET /bookings/:id/additional-charges was returning DRAFT
charges to the customer (hidden client-side only) — now filtered
server-side per caller.
- Added support for viewing and managing consolidated bookings in BookingRequestDetailPage.
- Enhanced BookingRequestsPage to display paired bookings in a single row.
- Introduced pairedDecision method in bookings service to handle decisions for both halves of a consolidated pair.
- Updated contracts service to include methods for manual consolidation of odd-20ft bookings.
- Created new components for selecting and editing consolidation partners.
- Added tests for paired decision logic and manual consolidation scenarios.
- Updated UI to reflect changes in booking handling and provide user feedback for odd container counts.
A resumed onboarding asked for the per-role business licence again and refused
to submit until it was uploaded a second time, however many were already on
file. `getInfo` never populates `companyProfiles[].licenseFiles`, and the
wizard validates against exactly that — so every profile looked empty, while
`markOnboardingComplete` would have accepted the application as it stood.
Validation now reads `licenseProfiles[].uploaded` from the onboarding
requirements: the server's own verdict, already fetched by the step, and the
same source the API enforces on submit.
Reachable today by anyone who resumes onboarding after a licence upload, and by
every company that switches back to eTrade registration — which is where the
e2e suite hit it.
The Company, Owner, Contact and Power of Attorney tabs had drifted from the
onboarding wizard while the manual-registration routes were added, and each
divergence locked somebody out of their own account:
- VAT was validated as 10-or-11 digits here and by onboarding's rule there. A
foreign company's VAT is its own tax authority's and a co-operative's follows
neither, so the stricter copy failed every save on the tab, not just the VAT
field. The schema now reuses onboarding's, with a test pinning both rules.
- Fayda's phone claims are normalized on read, as the wizard does — the
registry holds local numbers that neither the form nor the API's
@IsValidPhone() accepts.
- The eTrade manager is shown read-only, because that record is exactly what
the backoffice checks the company against; leaving it editable let a customer
overwrite the value under review.
- A co-operative's per-role licence cards are hidden on the Documents tab. The
API lifts the requirement, so the slots could never be filled or cleared.
Both manual-registration routes exist for one reason — eTrade holds no record
to fetch — so leaving one is the same act whichever it is. A co-operative that
has since taken out a trade licence had no way out at all: the flag is chosen
in the wizard, and an onboarded company can no longer reach it.
revert-to-etrade now accepts either flag and strips both, and a co-operative's
ACTIVE roles go back to Pending with it: those approvals were granted without a
per-role business licence, because a co-op owes none, and the moment it stops
being one that licence is due. Rejected, suspended and blacklisted roles are
left alone — promoting a blocked role to "awaiting approval" would launder a
staff decision away. An investor's roles are untouched; their licences were
always due and already reviewed.
Switching INTO a route stays with the wizard's nationality/role step, which
owns the mutually-exclusive rules; a second entry point would restate all three.
The Region select called setValue without shouldDirty. `region` is an
eTrade-bundle key, and stepPayload sends those only when the customer changed
them this session — so for the two routes that type their address by hand (a
co-operative, a foreign investor) the region was dropped on every save while
zone, woreda and kebele went through, because those are registered inputs and
are dirty by construction.
Found by the new onboarding e2e suite: both manual-route companies finished
onboarding with zone/woreda/kebele on file and region empty.
A company that ticked the investment-licence box by mistake, or that has since
been registered with the trade registry, had no way back — the flag is chosen
once, on a step onboarding never returns to.
The Company tab now carries a Registration source card for those companies.
It is a re-application rather than a settings edit, so the confirmation says
so outright: the typed registration is cleared, the company returns to pending
and the wizard reopens on the company step, while documents, owner and contact
details stay. Hidden for everyone else, and disabled while a profile change
request is under review — switching then would strand it.
A foreign company can now say it operates on an investment licence, on the
same step as its nationality and roles. The box only appears for a foreign
company, and moving the nationality answer back to Ethiopian drops it — the
API refuses both pairings.
The company step's eTrade gate now reads `manualRegistration`
(co-operative OR investment licence): the TIN lookup still runs, but finding
nothing is an expected outcome rather than a blocker, and the registration
section is typed instead. What stays keyed to `cooperative` alone is the
per-role business licence — an investor holds one, a co-operative does not —
so the licence cards and their validation are unchanged for investors.
Also carries the client plumbing for the revert endpoint the settings card
uses next.
- Added ShippingLineBookingCompletionController and associated service to handle the completion of shipping line bookings.
- Introduced a new module for booking completion to maintain module separation and avoid cyclic dependencies.
- Updated the train scheduling global rules to set default desk hours to 24 hours.
- Modified existing services and entities to accommodate the new booking completion logic.
- Enhanced the front-end components to support the new booking completion flow, including updates to the booking detail and bookings pages.
- Implemented validation and error handling for booking completion, ensuring that only approved bookings can be completed.
- Added migration to set default desk hours in the database.
- Add ShippingLineBookingsPage for listing and managing shipping line bookings.
- Create ShippingLineDocumentsModal for document uploads related to bookings.
- Introduce ShippingLineInitiateModal for initiating new shipping line bookings.
- Implement booking document state management with booking-doc-state utility.
- Add shipping line bookings service for API interactions.
- Update index to export new components and services.
- Enhance types for freight to include shipping line credits.
Import Load List / Marshalling Document only rendered Seq, Wagon,
Booking, Company, Load, Container numbers, Weight T — missing fields
present on the physical marshaling sheet (wagon type, tare, equated
length, departure/arrival station, seal no) and a blank note column
for yard staff. Export marshalling doc already had most of these;
import doc now matches. Existing columns kept in place, unchanged.
- 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.