Commit Graph

227 Commits

Author SHA1 Message Date
Hagernesh
6983645347 feat(warehouses): gate double-handling fee on a per-booking Yes/No
Double handling billed every import with a matching rule. Add
bookings.double_handling (+ set_at/by), charge only when Yes, expose a
PATCH endpoint (import-only, locked after invoicing, audited) and Yes/No
items in the inventory row menu.
2026-07-25 10:45:34 +00:00
Hagernesh
cf8a2e928d fix(warehouses): detention groups by canonical truck type
Join truck_types via vehicles.truck_type_id (normalized legacy
vehicle_type only as fallback) so type renames can't unmatch detention
rules and FK-less vehicles keep billing.
2026-07-24 11:55:05 +00:00
marshal
d585351501 Merge pull request #943 from Tria-plc/freight_feature/usermanagement
changes
2026-07-23 17:20:24 +03:00
Marshal
127676055b changes 2026-07-23 14:18:24 +00:00
marshal
cf13c8d175 Merge pull request #942 from Tria-plc/freight_feature/usermanagement
revert back the clerance payment
2026-07-23 16:56:56 +03:00
Marshal
15a6bab5d0 revert back the clerance payment 2026-07-23 13:54:09 +00:00
Nathnael
dcc94643d0 feat(companies): enforce customers:* permissions on customer endpoints
The customers:* keys were seeded and present in the backoffice constants but
enforced nowhere except reset-password. Customer CRUD sat behind the coarse
edr_freight_app:admin umbrella, and every company read endpoint was unguarded.

Two routes could not be gated on the route alone, because the authority they
need depends on the request BODY, not the path:

  - PATCH /companies/:id carries `status` (UpdateCompanyDto extends
    PartialType(CreateCompanyDto)), so it both edits fields and blacklists.
  - PATCH /company-profiles/:profileId/status is approve, reject, suspend and
    blacklist on one route.

Both now take a one-of route guard and assert per-status against a shared
STATUS_PERM map: approving/reactivating needs customers:verify, suspending or
blacklisting needs customers:deactivate. PATCH /companies/:id additionally
requires customers:update when any non-status field is present, so a caller
holding only deactivate cannot rename a company. The backoffice mirrors the
same map so no button is offered that the server would reject.

GET /companies/:companyId/documents is left authenticated-only with the split
in the handler: it is dual-audience. The portal reads its own documents during
onboarding, and the contract-request detail page (gated on contracts:view)
reads the applicant's. Gating it on customers:view alone would have 403'd
customers on their own documents and blanked the contract reviewer's panel.

The two by-company customer-view reads take a one-of guard for the same reason
— otherwise a staffer granted only customers:view gets a detail page whose tabs
403 individually.

Frontend: the customers routes were sidebar-filtered but not wrapped in
RequirePermission, so direct URL navigation rendered them for anyone.

Verified: freight-api type-check clean; backoffice type-check unchanged from
HEAD (pre-existing errors only); 25 tests pass across the companies and
freight-permission suites. Not exercised against a running API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 13:48:42 +00:00
marshal
4df17f36ce Merge pull request #935 from Tria-plc/freight_feature/usermanagement
changes
2026-07-23 14:07:03 +03:00
Marshal
13609f8d59 changes 2026-07-23 11:06:10 +00:00
Hagernesh
ec066f3d29 Fix:
Added assertCapacity() checks before saving (matches single receive)
Added applyCapacityDelta() after save to increment counters
Now validates warehouse → yard → zone capacity hierarchy
Single receive already had both checks; bulk receive was gap.
2026-07-22 13:18:36 +00:00
Hagernesh Tadesse
11437cfd35 Merge pull request #905 from Tria-plc/testfixes
Fixes
Download Excel template with instructions
Parse uploaded file, preview trucks
Validate container assignments (1x40ft OR 2x20ft per truck)
Commit bulk upload in one call
2026-07-22 13:54:59 +03:00
Hagernesh
7763d67ea8 feat: bulk upload for customer truck assignments
Add Excel template-based bulk upload for customer truck assignments
(self-haul + EDR). Supports up to 2x20ft or 1x40ft containers per truck.

API: POST /bookings/:id/customer-trucks/bulk accepts array of trucks.
Portal: DownloadTemplate → ParseExcel → PreviewUpload → Commit flow.
Validates truck load rules per booking container configuration.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-22 08:01:16 +00:00
Nathnael
179d6eea9e Merge branch 'dev' into freight/feat/fixes-v1 2026-07-22 07:20:08 +00:00
Nathnael
82cb5508cc chore: rm the active company profile 2026-07-22 06:43:05 +00:00
Marshal
835c9e111c feat(train-scheduling): implement container movement between wagons
- Added functionality to move containers between wagons in the train scheduling system.
- Introduced  API endpoint and service method to handle container movement.
- Updated  component to support drag-and-drop for rearranging containers.
- Enhanced  to allow moving containers to other wagons via a context menu.
- Implemented UI feedback for container movement actions, including loading states and success/error notifications.
- Updated relevant types and constants to accommodate new container movement logic.
- Added tests for the rule engine to ensure proper handling of hazardous bookings.
2026-07-21 23:02:06 +00:00
Hagernesh
86569f7490 Customer portal card displays warehouse location data (warehouse/yard/zone + arrival time) once cargo arrives at warehouse. Shows loading state during fetch, placeholder text if not yet received. Type-check passes. 2026-07-21 11:55:18 +00:00
Marshal
9ca4075c1e Implement intercity document handling and rejection notes for contracts 2026-07-21 10:39:21 +00:00
Marshal
6f8456631c Implement intercity document handling and rejection notes for contracts 2026-07-21 10:20:36 +00:00
Marshal
ceb32e0a80 Implement intercity document handling and rejection notes for contracts 2026-07-21 10:15:18 +00:00
Nathnael
4afffca3d2 fix(companies): honest status errors and per-role suspension visibility
A suspended customer trying to create a contract was told their account
was "awaiting approval" - the guards collapsed every non-active status
into the pending message. Contract and booking creation now go through a
shared assertCompanyActiveFor that names the real company status, and
the per-role guard names the role's actual state (suspended,
blacklisted, rejected - with the reviewer note) so a customer suspended
for one operation knows the others still work.

Portal: the operation dropdown gets a Suspended badge, the block modal a
suspended branch quoting the staff message, and the wizard a
suspended/blacklisted gate instead of falling through to a submit error.

EDRFREIGHT-234
2026-07-21 09:09:34 +00:00
marshal
b9b2075207 Merge pull request #837 from Tria-plc/freight_feature/usermanagement
contrat nad booking modification
2026-07-20 15:25:51 +03:00
Marshal
b90afadfba contrat nad booking modification 2026-07-20 12:24:58 +00:00
Nathnael
804c72f14a Merge branch 'dev' into freight/feat/fixes-v1 2026-07-20 12:12:30 +00:00
Hagernesh
c8a70593cf fix(mile): apply one truck-load rule to customer and EDR haulage alike
A truck holds one 40ft or two 20ft, a container booking takes no more trucks
than it has containers, and a bulk booking takes trucks until its tonnage is
hauled away. The same physics whoever drives, but the rule was written out
four times — addTruck, updateTruck, departTruck and LastMileService — beside
a byte-identical container-size query. Copies drift: that is how the
self-haul guard ended up enforced on one side only.

The bulk cap was the real gap. EDR summed net_weight_tons of departed trucks
and refused another once the booking was drawn down. The customer side had
no cap at all: for bulk it skipped straight past every check, so a self-haul
bulk booking could take unlimited trucks.

It could not simply reuse the EDR sum. customer_truck_assignments had no net
and no tare, only a gross_weight_kg that holds tonnes despite its name and
that nothing in the live flow ever wrote — release() recorded exit weights
against the EDR table alone, which is why all five customer trucks on dev
have neither weight nor departure. Any drawdown keyed on it would have
summed zero forever and never fired.

So the customer table now carries tare_weight_tons and net_weight_tons to
match the EDR one, release() records the customer truck's exit as it already
did for EDR, and the drawdown counts both sources — a booking hauls by one
path or the other and "until no tonnage is left" means the same either way.

Also locks a load once its truck has arrived on the EDR side, which the
customer side has always done, and fills the arrival form from the customer
truck on file: the prefill read booking.customer_truck_*, which multi-truck
self-haul leaves null, so a booking with a truck assigned opened blank.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 11:41:57 +00:00
Marshal
0727de0f4d Refactor clearance terminology to document approval across services and UI components 2026-07-20 11:41:57 +00:00
Nathnael
5bf82bf531 fix: notify the backoffice of new booking 2026-07-20 11:28:18 +00:00
Hagernesh
c1c362ab9d fix(mile): only send bookings that bought EDR haulage to the mile queues
The rule that a customer's own truck and an EDR road leg are alternatives
existed on the truck side only (CustomerTruckService.assertSelfHaulPaid).
LastMileService had no counterpart: create checked payment and nothing else,
so any paid booking could be accepted into the queue. A booking took a
customer truck at 06:42 and an EDR last-mile leg with a real EDR truck at
06:47, neither side aware of the other, on a contract that had chosen no
road legs at all.

The road legs are chosen on the contract and copied onto the booking, and
the pickup/delivery address is the only per-booking record of that choice.
service_types cannot serve: every type ships with includes_first_mile and
includes_last_mile set to true, so reading them would mean no booking could
ever self-haul. That same always-true flag had already killed the first-mile
guard, whose `address || serviceType.includesFirstMile` admitted every paid
export booking.

One shared rule now answers it for both sides, so the two halves cannot
drift apart again: last-mile create rejects a booking that chose no road
legs and one already carrying a customer truck; first-mile no longer honours
the service-type flag; the customer-truck guard reads the same helper.

Existing legs are untouched — the guards are on creation, so the one booking
already carrying both needs a human to reconcile it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 08:03:16 +00:00
Marshal
e22b336e8c Refactor clearance terminology to document approval across services and UI components 2026-07-20 07:46:38 +00:00
Marshal
771aa2a605 Add train deactivation feature and import train number management
- Introduced DEACTIVATED status for trains, allowing staff to park trains indefinitely.
- Implemented methods to deactivate and reactivate trains in the TrainBuilderService.
- Added UI components for train deactivation and reactivation in TrainBuilderDetailPage.
- Created a dropdown setting for admin-managed import train numbers, with corresponding migrations.
- Updated yard code length to accommodate soft-delete suffix.
- Enhanced train status handling to include DEACTIVATED state.
2026-07-20 07:04:23 +00:00
Marshal
4969f62896 changes 2026-07-20 03:05:28 +00:00
Marshal
0dead281ce add per-container handling options for hazardous, reefer, and return services
- Introduced new boolean fields (isHazardous, isReefer, isReturn) in UnitDraft and related interfaces to allow individual container handling options.
- Updated emptyUnit function to initialize these new fields.
- Modified GlCreateBookingForm to handle and display these options for each container.
- Adjusted calculations for hazardous, reefer, and return quantities based on the new handling options.
- Updated the schema for container units and booking container lines to include handling options.
- Added migration to support the new return flag in the database.
- Enhanced various components to reflect gross weight calculations, ensuring consistency across the application.
2026-07-18 19:20:45 +00:00
Marshal
406fbf6c45 split export 2026-07-18 09:12:52 +00:00
Marshal
3a1a08b1e1 add lashing surcharge for cargo types with hasLashing flag
add lashing surcharge for cargo types with hasLashing flag
2026-07-17 23:25:53 +00:00
Marshal
6467173c76 fix 2026-07-17 13:57:59 +00:00
Marshal
308df1c61c fix schule issue and contianer type issue 2026-07-17 09:18:26 +00:00
Marshal
7b7e7c3f62 fix schule issue and contianer type issue 2026-07-17 09:16:35 +00:00
Nathnael Wondisha
f769d97135 Merge pull request #752 from Tria-plc/freight/feat/fixes-v1
Freight/feat/fixes v1
2026-07-17 10:01:44 +03:00
Marshal
35c53e3f36 changes 2026-07-16 20:03:35 +00:00
Nathnael
f71bbbf782 feat: setup account page for customer and centeralize the otps and phone usages to use the iam user 2026-07-16 12:08:45 +00:00
Nathnael
6dde17fa4d fix: premature payable invoice 2026-07-16 08:38:49 +00:00
marshal
ea22f38adf Merge pull request #720 from Tria-plc/freight_feature/usermanagement
fix issue
2026-07-16 03:34:14 +03:00
Marshal
41fe04652f fix issue 2026-07-16 00:33:31 +00:00
marshal
67bc835458 Merge pull request #719 from Tria-plc/freight_feature/usermanagement
implement empty-container return service: add return quantity handlin…
2026-07-16 02:06:08 +03:00
Marshal
234a74e812 implement empty-container return service: add return quantity handling, update related DTOs, services, and UI components 2026-07-15 22:48:04 +00:00
marshal
e3fccbd24d Merge pull request #717 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-07-15 23:18:55 +03:00
Marshal
fc44eee25e implement update train details feature: add DTO, service method, and UI modal for editing train name and run numbers 2026-07-15 20:14:39 +00:00
marshal
6391ba837a Merge pull request #707 from Tria-plc/freight_feature/usermanagement
changes
2026-07-15 16:30:28 +03:00
Marshal
19c9da28ae changes 2026-07-15 13:29:01 +00:00
marshal
7700aa6358 Merge pull request #701 from Tria-plc/freight_feature/usermanagement
Freight feature/usermanagement
2026-07-15 13:32:37 +03:00
Marshal
11771e5f92 remove reopen delay minutes from global rules and update related types
- Removed the  field from  and related components.
- Updated  to reflect the removal of the reopen delay input field.
- Modified  to include new train number fields:  and .
- Added  interface to manage active schedules with trade direction.
- Introduced  interface to track wagon shortages in bookings.
- Updated  logic to ensure consistent UI state representation.
- Created migrations to drop the  column and add  and  columns to the  table.
- Added tests for the new booking window display logic and wagon planning functionality.
2026-07-15 09:13:02 +00:00