3442 Commits

Author SHA1 Message Date
Marshal
4b8fea2d76 chore: update package overrides in pnpm-workspace.yaml for dependencies 2026-08-12 07:17:13 +00:00
Marshal
6434bb266c Merge branch 'dev' 2026-08-12 06:44:30 +00:00
marshalyordanos
5da36eb128 feat: add wagon usage computation and maintenance logging features
- 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.
2026-08-12 09:36:50 +03:00
Nathnael Wondisha
08eebd21a2 Merge pull request #1242 from Tria-plc/freight/nati-2
feat(freight-api): seal EDR side of contracts with the one global stamp
2026-08-12 06:31:12 +03:00
ghost2023
a603807e8e feat(freight-api): seal EDR side of contracts with the one global stamp 2026-08-12 06:26:46 +03:00
marshalyordanos
35e5404b41 Refactor code structure for improved readability and maintainability 2026-08-11 19:36:00 +03:00
Nathnael Wondisha
13dca1a287 Merge pull request #1241 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-11 17:47:26 +03:00
ghost2023
e52d666647 feat(freight-api): persist eTrade manager phone in identity 2026-08-11 17:41:06 +03:00
Nathnael
637a766118 WIP(represtation step) 2026-08-11 13:13:11 +00:00
Nathnael
d6e349f329 feat(companies): onboard co-operative unions and farms
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.
2026-08-11 12:54:51 +00:00
Nathnael
72164b0b8e fix(freight-portal): stop owner details vanishing between wizard steps
SourcedField rendered read-only whenever a value existed, so the input a
customer had just typed into turned into a badge as soon as the step saved and
they navigated back — and dropped out of requiredKeys at the same time. It now
locks on ownership instead: a Fayda verification owns what its claims filled,
everything else stays an editable, prefilled input.

The representation step follows the same rule and asks in the right order:

- The power-of-attorney question collapses to its answer once given, with a
  button back to it (none for a freight forwarder, whose answer is forced).
- A foreign company picks how to prove the person outright — Fayda or a
  passport — rather than being shown both at once.
- The representative's own fields appear only once the person is established,
  and only for what the verification did not supply; what it did supply is
  already on the panel above and is no longer repeated beneath it.
- Dropped the freight-forwarder lecture and the DARS blurb; the badge and the
  upload field's own help text already say both.

VAT numbers accept any non-blank value. A foreign tax authority's carries
letters and dashes and a co-operative's follows neither pattern, so the 10-11
digit rule only ever rejected numbers we had no business judging.
2026-08-11 12:54:38 +00:00
Hagernesh
1be72799f4 fix(train-scheduling): exempt direct-to-train export bookings from GRN gate
confirmScheduleLoading's assertExportBookingsReceived checked every
wagon-assigned export booking for a warehouse GRN, with no exception for
DIRECT_TO_TRAIN (manual truck-straight-to-wagon) bookings — the one
call site that lacked the carve-out already applied everywhere else GRN
is checked (export-received-gate, booking-journey, carriage acceptance).
Warehouse-routed export cargo still requires GRN; direct handovers rely
on the carriage acceptance sheet instead.
2026-08-11 12:14:13 +00:00
Stephanos A.
ae9bf8bd31 Merge pull request #1239 from Tria-plc/alpha
Overall revenue updates
2026-08-11 15:04:35 +03:00
Stephanos A
bd8187578e Overall revenue updates 2026-08-11 15:02:16 +03:00
Nathnael
02d9debe1d refactor(freight-backoffice): review one identity and the eTrade owner match
- Replace the general-manager rows with owner rows across the customer
  detail, contract cards, types and service mappings.
- The identity card names its subject ("Verifies for this company") and shows
  whether the asserted owner matches the manager on the eTrade licence:
  amber when it does not, green when it does, dimmed when eTrade named
  nobody. Advisory only, since the comparison is a fuzzy transliteration
  match.
- A missing delegation letter now keys on poaDeclared === "yes".
- Keep the three general-manager labels in the change-request label map so
  historical requests still render readable field names.
2026-08-11 11:54:05 +00:00
Nathnael
293f255daa refactor(freight-portal): rebuild the onboarding wizard around owner and representation
Steps are now company -> owner -> representation -> contact -> documents;
PersonnelStep and PoaStep are gone.

- OwnerStep shows whoever the eTrade licence names, read-only with a
  provenance badge (SourcedField), and renders an input for every gap eTrade
  and Fayda left. It warns when the stored owner does not match eTrade.
- RepresentationStep asks outright whether anyone holds power of attorney,
  then branches: "no" verifies the owner, "yes" collects the representative
  and the DARS delegation letter. Freight forwarders cannot answer "no".
- Passport input appears only for a foreign company whose subject has not
  verified with Fayda.
- Drop every same-as-owner copy-across and the auth-user fallbacks for the
  owner's email and phone. Re-picking a business licence now clears the
  eTrade owner prefill, since licences under one TIN can name different
  managers.
- Settings: TabGeneralManager replaced by TabOwner; TabPowerOfAttorney
  reworked around poaDeclared.
2026-08-11 11:53:56 +00:00
Nathnael
8cf041f494 test(companies): rewrite identity specs around the single subject
fayda-identity covers the two subjects, the passport alternative and the
eTrade owner comparison in place of ~40 general-manager assertions.
poa-delegation drops the poaSameAsOwner waiver case and asserts the opposite:
a forwarder is refused without a delegation letter however it represents
itself.
2026-08-11 11:53:42 +00:00
Nathnael
f611c33722 feat(companies): migrate existing companies off the general manager
Data rescue, not just schema tidying — the order matters:

1. Backfill companies.email from generalManagerEmail before the key is
   stripped, or companies whose only address lived there stop receiving mail.
2. Backfill ownerName/Email/Phone (now required) from owner, GM, contact
   person, then the columns; seed etradeManagerName so existing rows read as
   matching rather than as a false mismatch.
3. Convert poaSameAsOwner: non-forwarders become poaDeclared='no' with their
   poa* details cleared; forwarders become 'yes' and keep them, so they now
   owe a DARS letter they were previously waived.
4. Derive poaDeclared for everyone else.
5. Move drafts off the deleted 'personnel' wizard step.
6. Drop the general_manager_* columns and strip gm*/poaSameAsOwner.

down() restores the column shape only; the stripped values are gone by design.
2026-08-11 11:53:36 +00:00
Nathnael
a1bcdfb692 refactor(companies): one verified identity per company, no general manager
Replaces the owner/general-manager/PoA trio with a single identity whose
subject is the PoA when the company declares one and the owner otherwise.

- Drop the general manager everywhere: entity columns, DTOs, required-field
  list, self-service attributes, gm* identity handling.
- New explicit poaDeclared answer ("yes"/"no") replaces poaSameAsOwner. A
  DARS delegation letter is required iff it is "yes"; a freight forwarder is
  forced to "yes" server-side and gets no waiver.
- Owner name/email/phone become typeable and required, prefilled from the
  eTrade lookup, never falling back to the authenticated account.
- Store eTrade's manager separately (etradeManagerName/Phone) and expose
  ownerMatchesEtrade so backoffice compares the asserted owner against the
  licence instead of against itself.
- Foreign companies satisfy the identity with Fayda or a passport number, on
  whichever subject is verifying (poaPassportNumber added).
- Write companies.email/phone from the owner unconditionally, so a company
  without a Fayda-verified owner still has a notification address.
2026-08-11 11:53:26 +00:00
Hagernesh Tadesse
8cbd67ae59 Merge pull request #1236 from Tria-plc/eims-integration
feat(permissions): grant the director full warehouse authority
2026-08-11 11:55:42 +03:00
Hagernesh
dac2186c02 feat(permissions): grant the director full warehouse authority
The director position held no warehouse permissions at all. It now
carries the same warehouse set as the chief tier: dashboard, warehouse
/yard/zone CRUD, allocation and fee rule CRUD, the inventory operation
set, inspection reports, interchange documents and fee invoices.
Unlike the dispatcher, the director owns the allocation and fee rules
themselves. The positions seeder backfills existing environments on
boot.
2026-08-11 08:49:41 +00:00
marshal
3bfff81a37 Merge pull request #1234 from Tria-plc/freight_feature/usermanagement
feat(permissions): add granular permissions for train management actions
2026-08-11 11:49:29 +03:00
marshalyordanos
07a120af5e feat(permissions): add granular permissions for train management actions
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
2026-08-11 11:48:16 +03:00
Nathnael
e59e0324e0 Merge branch 'dev' into freight/nati-2 2026-08-11 08:36:21 +00:00
Nathnael
619b183a11 fix: redirect to booking issue fixed 2026-08-11 08:34:15 +00:00
Abubeker Yasin
417acff2f2 Merge pull request #1233 from Tria-plc/alpha
fix: ( payments ) stop reconcile-before-cancel deferring bookings for…
2026-08-11 11:20:52 +03:00
Abubeker Yasin
dc2078dd28 fix: ( payments ) stop reconcile-before-cancel deferring bookings forever 2026-08-11 11:19:39 +03:00
marshalyordanos
ea6eccbf09 feat(upload): increase document upload size limits to 50MB across the application 2026-08-11 09:26:23 +03:00
marshal
577390ca6b Merge pull request #1230 from Tria-plc/freight_feature/usermanagement
feat(wagons): enforce wagon availability limits in transfer requests
2026-08-10 23:32:46 +03:00
marshalyordanos
997998dcb2 feat(wagons): enforce wagon availability limits in transfer requests 2026-08-10 23:30:18 +03:00
marshal
f51214d117 Merge pull request #1228 from Tria-plc/freight_feature/usermanagement
feat(freight): surface scheduling clock and gate pay during drain
2026-08-10 22:14:44 +03:00
marshalyordanos
c743750ef6 feat(freight): surface scheduling clock and gate pay during drain 2026-08-10 22:14:04 +03:00
marshal
01e4b88788 Merge pull request #1227 from Tria-plc/freight_feature/usermanagement
feat(freight): surface scheduling clock and gate pay during drain
2026-08-10 21:50:06 +03:00
Nathnael Wondisha
3426d9dd50 Merge pull request #1226 from Tria-plc/freight/nati-2
fix: the position based gl gate on sidbear
2026-08-10 21:48:14 +03:00
marshalyordanos
40672e9c41 feat(freight): surface scheduling clock and gate pay during drain 2026-08-10 21:47:28 +03:00
Nathnael
92371f17da fix: the position based gl gate on sidbear 2026-08-10 18:45:54 +00:00
marshal
d3096939e7 Merge pull request #1223 from Tria-plc/freight_feature/usermanagement
fix(freight-backoffice): render wagon transfer reason as sanitized HT…
2026-08-10 17:54:28 +03:00
Nathnael
615f7e6798 feat: add choice to etrade fetcher 2026-08-10 14:49:17 +00:00
Marshal
e29e3ff837 fix(freight-backoffice): render wagon transfer reason as sanitized HTML in a modal 2026-08-10 14:02:13 +00:00
Nathnael
c24c93bcf3 feat: add 11 digit vat 2026-08-10 13:56:25 +00:00
Abubeker Yasin
ce57be252c Merge pull request #1220 from Tria-plc/alpha
Alpha
2026-08-10 15:45:44 +03:00
Hagernesh
b701ae3f47 Revert "docs: trim eims.types.ts file header comment"
This reverts commit f4b8dab58d921791b4b3f69e3c9952b6802835cc.
2026-08-10 12:14:18 +00:00
Hagernesh
1b4a317d92 docs: trim eims.types.ts file header comment
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 12:14:18 +00:00
Hagernesh
bf8eadbc85 fix: portal cannot load last-mile confirmation request
LAST_MILE_REQUESTS URL constants were missing the /api prefix every other
endpoint in URLS.ts carries — all five calls (get, submit, contract
view/document/sign) 404'd against the deployed API, so the departure
notification's confirm link never loaded for the customer.

Also widen GET /last-mile-requests/:id from @BookingStaff to @MixedAudience
with the same ownership check submit()/sign() already use — the confirm
page calls this as its first request, before the customer has done
anything else, so it can't be staff-only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 12:14:18 +00:00
Abubeker Yasin
8ce6483e26 Merge branch 'dev' into alpha 2026-08-10 14:38:44 +03:00
Abubeker Yasin
18c47ca4a3 recover: ( payment ) recover cancelation fix deleted by malware 2026-08-10 14:25:14 +03:00
Nathnael Wondisha
b91a7e8a8f Merge pull request #1216 from Tria-plc/freight/nati-2
fix
2026-08-10 12:36:29 +03:00
ghost2023
c75ed8f149 fix 2026-08-10 12:35:43 +03:00
Nathnael Wondisha
29d472351f Merge pull request #1213 from Tria-plc/freight/nati-2
Freight/nati 2
2026-08-10 12:33:07 +03:00
ghost2023
d07d35e438 feat: allow owner to represent company as power of attorney 2026-08-10 12:31:13 +03:00