Commit Graph

30 Commits

Author SHA1 Message Date
Marshal
d25612c2f0 feat(user-management): implement staff reference permissions for various controllers and update sidebar permissions 2026-07-21 23:25:43 +00:00
Hagernesh
61e59036cd Browser testing for modern teams
Create tests, debug failures, and improve quality faster than ever. Get AI-powered guidance at every stage of testing, with full code ownership, on a platform that connects your team.
2026-07-21 12:57:37 +00:00
Hagernesh
1fe8c2fd8e feat(export): gate receive on payment and loading on received + GRN
Three export rules that the flow left open.

An unpaid export booking could be received at the warehouse. Receiving is
what starts storage and mints a GRN, so it must not happen against cargo the
customer has not settled. receive() now rejects an unpaid EXPORT booking.
Import is untouched — it arrives OFF a train and its receive is the unload,
so gating that on payment would strand cargo already at the yard.

An allocated export booking could be marked loaded onto its train without
ever reaching the warehouse. An allocation is a plan; the GRN is the proof
the goods are in hand. Two loading paths skipped that check — the per-yard
loadBooking and the workspace confirmScheduleLoading — and both now require
every export booking to be received with a GRN first, however it arrived
(first-mile or the customer's own truck) and whatever it is allocated to.
The rule lives in one shared guard (assertExportReceivedWithGrn) so the two
paths cannot drift.

Export self-haul without a first-mile leg already worked and is unchanged:
assertSelfHaulPaid allows a customer truck when there is no EDR mile leg and
the booking is paid, and addTruck applies the same one-40ft-or-two-20ft rule
to containers and the tonnage drawdown to bulk, exactly as import does.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 08:01:32 +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
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
Nathnael
6cb921e617 fix: 194 and 183 plane takss 2026-07-20 11:41:57 +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
Hagernesh
21df861979 back date validator 2026-07-20 07:13:52 +00:00
Hagernesh
a73faecbe3 feat(intercity): raise a GRN when a facility loads or unloads cargo
Every facility raises a GRN — the goods changed hands, whether or not anyone
stores them. What differs is what happens next: Indode has a warehouse, so cargo
left there goes through the existing warehouse flow and accrues storage and
demurrage; Sebeta, Modjo, Adama and Dire Dawa only move cargo between train and
truck, so the handling event and its GRN are the whole record.

facility_handling_events carries that record because warehouse_inventory cannot:
its warehouse/yard/zone are NOT NULL, so a facility with equipment but no
warehouse could never have a row there. inventory_id links the storage record
when the facility does keep the cargo, which is what ties an Indode handover to
its demurrage.

generateGrnNumber moves to common/grn.util.ts so a GRN raised at a facility is
indistinguishable from one raised in a warehouse — the two live in different
tables, and a second generator would let the formats drift.

Recording is best-effort: the cargo moved regardless, so paperwork must never
fail the journey.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 10:40:16 +00:00
Marshal
801872c106 fix rate edit 2026-07-17 10:15:26 +00:00
Hagernesh
2798fed6d8 fix(train-scheduling): block dispatch when allocated cargo is not loaded
dispatchSchedule guarded status, Djibouti departure rules, locomotives and
wagons — but never checked the cargo. A train could be dispatched while the
bookings allocated to it sat received in the warehouse, silently leaving them
behind. Dispatch now refuses when an allocated booking has warehouse inventory
in RECEIVED/STORED/READY_FOR_LOADING, naming the bookings and pointing at the
two ways out: load them, or drop the wagon allocation so they ride a later
train. Bookings with no inventory at all are not blocked — allocating a wagon
before the goods arrive is normal planning.

Also drops RESERVED from the Load-to-Train filters: reserved stock is not
awaiting loading.

The sched_bookings CTE moves to common/schedule-bookings.sql so the warehouse
loading queue and this dispatch guard resolve a train's bookings identically —
if they drift, a train departs leaving cargo the warehouse still expects to load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 08:01:57 +00:00
Marshal
b5a97d344a train 2026-07-14 13:10:00 +00:00
Marshal
6d0cf50b4d train 2026-07-14 11:06:49 +00:00
Marshal
4b7f6d2548 enhance contract and booking services with server-side search and validation improvements
- Added  parameter to  and  for server-side free-text search on contract reference, company name, and booking details.
- Introduced new validation errors in  for container clashes and space issues when creating bookings.
- Implemented paginated dropdown settings retrieval in .
- Updated  to fetch active yards using a new method that handles pagination.
- Enhanced  with a  method to fetch all records by walking through pages.
- Refactored  to support filtering and pagination in schedule listings.
- Improved  to return a paginated list of facilities.
- Updated UI components in  and  to utilize debounced search inputs for better performance.
- Added alerts in  to inform users about booking constraints related to splits and capacity.
- Enhanced  to display notifications for split bookings and capacity usage.
2026-07-12 10:51:31 +00:00
Marshal
fed5f2f43f implement intercity booking management and booking window websocket integration 2026-07-06 13:28:21 +00:00
Marshal
bb2cedc87f Add allocation management features and update permissions for container allocation 2026-07-03 04:15:16 +00:00
hagiye
8ee31789c6 merge conflict fix 2026-06-24 12:31:59 +03:00
hagiye
0255adffe6 changes 2026-06-24 09:56:12 +03:00
Marshal
dc708a2473 Refactor phone input handling across onboarding and settings forms
- Replaced PhoneInput component with ControlledPhoneField for better integration with react-hook-form.
- Updated validation for phone numbers using isValidPhone function to ensure proper formatting.
- Removed country code handling from forms, simplifying phone number management.
- Introduced new phone field component with consistent styling and behavior.
- Added phone number validation on the backend using class-validator.
- Removed unused phone utility functions and cleaned up related code.
2026-06-21 10:34:40 +00:00
Marshal
648f4f2ee4 Add fleet management and admin permissions, and update controllers to enforce new permissions 2026-06-17 01:56:56 +00:00
marshal
484151d909 payments 2026-06-14 15:59:52 +03:00
marshal
ef0abf1c41 auto allocation and batch managemnt, tracking the train 2026-06-12 11:42:46 +03:00
marshal
5774d7db9d booking operations and trains scheduling also allocations 2026-06-10 00:48:32 +03:00
marshal
35c9bdfce4 resolve confilict 2026-06-05 14:07:26 +03:00
marshal
d226d7ef22 booking flow,summtion, approval, contract, mock payemnt and integration to back office, and also add permissions 2026-06-05 10:38:31 +03:00
marshal
125ee18308 implement booking flow 2026-06-04 15:16:27 +03:00
marshal
452ebdbc0a rule engine and configration and fix booking for custoemr 2026-06-01 23:15:11 +03:00
Michael Abebe
1c5ee19388 chore: fmt 2026-05-12 16:50:18 +03:00
Muluhabt
3b8b6979db Project Initialization 2026-05-12 15:17:16 +03:00