mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 12:41:04 +00:00
Origin marshalling (import + export) now prints leg slots as TO BE LOADED AT <board yard> with board/alight stations and keeps their containers out of the loaded tallies. Intercity Marshalling 2 no longer hides whole-route cargo whose allocation never left PLANNED (import flow confirms loading at schedule level), so the on-board view matches the physical consist before and after mid-corridor coupling.
313 lines
19 KiB
HTML
313 lines
19 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>EDR Freight Portal — Priority Flows</title>
|
|
<style>
|
|
@page { size: A4; margin: 0; }
|
|
* { box-sizing: border-box; }
|
|
body {
|
|
font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
|
|
color: #1a1a1a;
|
|
margin: 0;
|
|
font-size: 13px;
|
|
line-height: 1.45;
|
|
}
|
|
.cover {
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: flex-start;
|
|
padding: 60px 70px;
|
|
background: linear-gradient(135deg, #0b6b4f 0%, #0e8a63 60%, #14a074 100%);
|
|
color: white;
|
|
page-break-after: always;
|
|
}
|
|
.cover .tag { font-size: 14px; letter-spacing: 3px; text-transform: uppercase; opacity: .85; margin-bottom: 18px; }
|
|
.cover h1 { font-size: 42px; margin: 0 0 14px 0; line-height: 1.15; }
|
|
.cover p.sub { font-size: 17px; opacity: .92; max-width: 520px; }
|
|
.cover .meta { margin-top: 60px; font-size: 12px; opacity: .8; border-top: 1px solid rgba(255,255,255,.35); padding-top: 16px; max-width: 520px; }
|
|
.cover .meta div { margin-bottom: 4px; }
|
|
|
|
.toc { padding: 60px 70px; page-break-after: always; }
|
|
.toc h2 { font-size: 22px; margin-bottom: 24px; color: #0b6b4f; }
|
|
.toc ol { padding-left: 22px; }
|
|
.toc li { margin-bottom: 10px; font-size: 14px; }
|
|
.toc .section-label { font-weight: 700; color: #0b6b4f; }
|
|
|
|
section.flow { padding: 40px 60px 10px 60px; }
|
|
section.flow > h2 {
|
|
font-size: 24px;
|
|
color: #0b6b4f;
|
|
border-bottom: 3px solid #0b6b4f;
|
|
padding-bottom: 8px;
|
|
margin-bottom: 6px;
|
|
page-break-before: always;
|
|
}
|
|
section.flow > p.lede { color: #444; font-size: 13.5px; margin-bottom: 22px; }
|
|
|
|
.step { margin-bottom: 28px; page-break-inside: avoid; }
|
|
.step .step-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
|
|
.step .num {
|
|
background: #0b6b4f; color: white; font-weight: 700; font-size: 13px;
|
|
width: 26px; height: 26px; border-radius: 50%;
|
|
display: flex; align-items: center; justify-content: center; flex-shrink: 0;
|
|
}
|
|
.step .title { font-weight: 700; font-size: 14.5px; }
|
|
.step .desc { margin: 0 0 10px 36px; color: #333; font-size: 13px; }
|
|
.step img {
|
|
display: block;
|
|
max-width: 100%;
|
|
border: 1px solid #d8dde3;
|
|
border-radius: 6px;
|
|
box-shadow: 0 1px 3px rgba(0,0,0,.08);
|
|
}
|
|
|
|
.note {
|
|
margin: 10px 36px 18px 36px;
|
|
padding: 10px 14px;
|
|
border-left: 4px solid #2f7fd6;
|
|
background: #eef5fd;
|
|
border-radius: 4px;
|
|
font-size: 12.5px;
|
|
}
|
|
.note.limit { border-left-color: #c98a1c; background: #fdf6e8; }
|
|
.note.bug { border-left-color: #c0392b; background: #fbeceb; }
|
|
.note.howto { border-left-color: #0b6b4f; background: #eaf6f0; }
|
|
.note b { display: block; margin-bottom: 3px; }
|
|
.note ol { margin: 6px 0 0 0; padding-left: 18px; }
|
|
.note ol li { margin-bottom: 4px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="cover">
|
|
<div class="tag">EDR Freight — Priority Flows</div>
|
|
<h1>Portal Side<br>Contract Signing · Booking · Payment</h1>
|
|
<p class="sub">A step-by-step walkthrough of the same three flows, driven live as the real
|
|
customer — every screen, button, and validation message as the account actually saw it.</p>
|
|
<div class="meta">
|
|
<div>Driven live against the shared dev environment (edr_dev)</div>
|
|
<div>Personas: hager@gmail.com (Hagernesh Tadesse) for contract & booking; nati@gmail.com (NAti Wondish) for payment</div>
|
|
<div>Companion document to EDR-Freight-Priority-Flows.pdf (backoffice/staff side)</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="toc">
|
|
<h2>Contents</h2>
|
|
<ol>
|
|
<li><span class="section-label">1. Contract creation & signing</span> — Home, Contracts list, the New Contract wizard (Setup → Cargo/Route → Review), the unit-rate quotation approval step, the duplicate-contract validation, and how/where a customer signs once EDR approves.</li>
|
|
<li><span class="section-label">2. Booking</span> — the Bookings list and the document-review flow a customer works through on an existing booking.</li>
|
|
<li><span class="section-label">3. Payment</span> — the customer's Invoices page, filtering to what's actually payable, the invoice detail screen with its "Pay" action, and the bank-transfer steps behind it.</li>
|
|
</ol>
|
|
</div>
|
|
|
|
<section class="flow">
|
|
<h2>1 · Contract creation & signing</h2>
|
|
<p class="lede">Portal customer hager@gmail.com, logged into the freight portal (localhost:5273).</p>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">1</div><div class="title">Sign in</div></div>
|
|
<div class="desc">The portal login form. A customer signs in with their email and password — no OTP step for an already-onboarded account (OTP only applies during self-signup).</div>
|
|
<img src="{{02-login-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">2</div><div class="title">Home</div></div>
|
|
<div class="desc">Landing page after login: quick stats and shortcuts into Contracts, Bookings, and Invoices.</div>
|
|
<img src="{{05-home-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">3</div><div class="title">Contracts list</div></div>
|
|
<div class="desc">The customer's contracts: one Active (CTR-2026-00043, Fully Executed) and two In Progress (CTR-2026-00086, CTR-2026-00087 — both Submitted, awaiting EDR review). "New Contract" starts a fresh one.</div>
|
|
<img src="{{04-contracts-list-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">4</div><div class="title">New Contract — Step 1: Setup</div></div>
|
|
<div class="desc">Operation Type, Contract Kind (One-Time vs. Framework), New-vs-Renewal, and the Service Type cards — the entry point of the wizard.</div>
|
|
<img src="{{07-contract-step1-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">5</div><div class="title">Step 1 filled — Operation Type + Service</div></div>
|
|
<div class="desc">Operation Type set to Import and "Rail Transport with Customs" selected — this reveals the trucking/customs options below (first mile, last mile, and the included customs clearing service).</div>
|
|
<img src="{{08-contract-step1-filled-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">6</div><div class="title">Step 2: Cargo & Route</div></div>
|
|
<div class="desc">Cargo scope (containerised, both 20ft/40ft), and the origin/destination yard pair that defines the route.</div>
|
|
<img src="{{09-contract-step2-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">7</div><div class="title">Step 3: Review & Submit</div></div>
|
|
<div class="desc">Final review of the assembled contract terms — operation, service, route, cargo scope, and customs handling — before submitting.</div>
|
|
<img src="{{10-contract-step3-review-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">8</div><div class="title">Approve your quotation</div></div>
|
|
<div class="desc">Submitting immediately opens a per-unit rate quotation for the customer to approve — freight rates for 20ft/40ft containers plus the customs clearance service fee per container size. The dialog is explicit that these are per-unit rates, not a total: the payable amount is computed per booking from the quantities actually shipped. Approving submits the contract for EDR staff review.</div>
|
|
<img src="{{11b-quotation-approve-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">9</div><div class="title">Real validation: duplicate contract blocked</div></div>
|
|
<div class="desc">Re-submitting a route/service/cargo-scope combination that already has an active or in-review contract is rejected outright, naming the conflicting contract by number. This is a genuine business rule hit live, not staged.</div>
|
|
<img src="{{11-contract-duplicate-blocked-full.png}}">
|
|
</div>
|
|
|
|
<div class="note howto">
|
|
<b>Once EDR approves the contract, the customer signs it</b>
|
|
A submitted contract moves through EDR review as: <i>Submitted → Pending Approval → Approved →
|
|
Approved Pending Signature → Contract Ready.</i> The "View & sign contract" button only
|
|
appears once the contract reaches <b>Contract Ready</b> — it shows on the Contracts list row and
|
|
on the contract's own detail page, and opens a dedicated preview-and-sign page
|
|
(<code>/contracts/:id/view</code>), not a plain button on the detail page.
|
|
<ol>
|
|
<li>EDR staff approve the contract and price it.</li>
|
|
<li>The customer is notified the moment it's ready to sign — <b>SMS, email, and an in-app
|
|
notification</b> all fire together (per the customer's description of the real notification
|
|
flow — not re-verified against the notification-sending code for this document).</li>
|
|
<li>The customer opens the notification or the Contracts list, clicks "View & sign
|
|
contract", scrolls the full contract text, and ticks the consent checkbox.</li>
|
|
<li>They draw or reuse a saved signature, upload a company stamp, then verify by OTP
|
|
(sent to their registered phone/email) to finalize the signature.</li>
|
|
<li>Status moves to Signed — Awaiting Staff, then Fully Executed once EDR counter-signs.</li>
|
|
</ol>
|
|
CTR-2026-00086 and CTR-2026-00087 above are still at Submitted — EDR hasn't approved them yet,
|
|
so no sign button is showing for either.
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">11</div><div class="title">Where "View & sign" actually shows (a different customer's contract list)</div></div>
|
|
<div class="desc">A second real account (nati@gmail.com, 17 contracts) confirms the button live: its Action column carries "View", "Request shipment", "Book shipment", and "Initiate booking" depending on each row's status — the same column shows "View & sign" the moment a row reaches Contract Ready.</div>
|
|
<img src="{{16-nati-contracts-list-actions.png}}">
|
|
</div>
|
|
|
|
<div class="note limit">
|
|
<b>The signable window is real and it closes</b>
|
|
This account's own CTR-2026-00089 was captured with a live "View & sign" button two days ago
|
|
(per the customer's own screenshot) — by the time this document was rebuilt, that same contract
|
|
had already moved to <b>Expired</b> with no button left to click. Contract Ready is a real,
|
|
time-boxed state, not a permanent one. No currently-open contract exists on either test account
|
|
at time of writing, so the sign page itself (scroll-to-consent → draw signature → stamp → OTP)
|
|
could not be re-captured live in this pass; it was documented from the customer's own screenshots
|
|
and code inspection instead.
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">10</div><div class="title">Fully executed contract — signatures</div></div>
|
|
<div class="desc">CTR-2026-00043's detail page: both STAFF and CUSTOMER signatures are complete and the contract is Fully Executed — the end state of the flow described above.</div>
|
|
<img src="{{06-contract-detail-signed-full.png}}">
|
|
</div>
|
|
</section>
|
|
|
|
<section class="flow">
|
|
<h2>2 · Booking</h2>
|
|
<p class="lede">A portal customer does not have a bare "New booking" button on the Bookings page
|
|
itself — booking creation is triggered from a signed contract's row, once EDR has cleared it for
|
|
shipment (contract status Active). What that entry point actually is depends on the contract's
|
|
state: "Initiate booking" opens a brand-new booking; "Book shipment" / "Book" continues one EDR
|
|
has already pre-cleared.</p>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">1</div><div class="title">Initiate booking — confirmation</div></div>
|
|
<div class="desc">Clicking "Initiate booking" on an Active contract (CTR-2026-00071) doesn't create the booking immediately — it confirms first: "This creates a new shipment booking under contract CTR-2026-00071. You'll upload the import documents next, and the shipment quantity is drawn down from your contract's reserved capacity." Cancelled here rather than completed, since creating a live booking is a real mutation.</div>
|
|
<img src="{{17-initiate-booking-confirm.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">2</div><div class="title">Complete Your Booking — cargo details</div></div>
|
|
<div class="desc">Following an already-cleared booking's "Book" action (BK-2026-000209, Bulk cargo under CTR-2026-00093) lands on this form: the contract's fixed route, a cargo-details block (Total weight for Bulk cargo — a Container-scoped contract shows an Excel-import table instead), and a Schedule block picking the binding shipment day. The billing currency here is fixed to ETB, paid through the payment gateway. The calendar is real and reactive: it read <i>"Enter your cargo details first — available shipment days depend on the wagons your cargo needs,"</i> and no day was actually open on this route at the time of capture (0 available days) — the same live batch-window behaviour documented in Section 1.</div>
|
|
<img src="{{19-complete-booking-cargo-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">3</div><div class="title">Bookings list — one contract's view</div></div>
|
|
<div class="desc">This account's one existing booking, BK-2026-000068 on CTR-2026-00043 — status "In review," amount still ETB 0.00 because pricing is finalised after document review, not at booking creation. Every row carries a "Review documents" action.</div>
|
|
<img src="{{13-bookings-list-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">4</div><div class="title">Import documents dialog</div></div>
|
|
<div class="desc">Clicking "Review documents" opens this in place, no page navigation. All four required import documents — Bill of Lading/Waybill, Packing List, Import declaration, and Ethiopia T1 & Djibouti T1 — show status "Under review," each with View/Download and a "Replace file" drop zone. The banner is explicit: <i>"Only re-upload the documents flagged with a query below — approved documents stay as they are."</i> "Submit documents" stays disabled while nothing is flagged.</div>
|
|
<img src="{{14-booking-documents-modal-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">5</div><div class="title">Bookings list — the fuller picture (nati@gmail.com, 38 bookings)</div></div>
|
|
<div class="desc">Across a larger real history the Action column carries every state at once: "Book" (cleared, awaiting cargo details), "View" (nothing to do), "Rebook wagons" (a cancelled reservation), "Pay [amount]" (booked, payment outstanding), "Review documents" / "Documents", and "Track" once a train is assigned. BK-2026-000188 shows "Pay 16,323.25 ETB" while its own Status column reads Cancelled — a live inconsistency (the booking lapsed after its payment window closed, but the stale Pay action hadn't been cleared from the row).</div>
|
|
<img src="{{18-nati-bookings-list-actions.png}}">
|
|
</div>
|
|
</section>
|
|
|
|
<section class="flow">
|
|
<h2>3 · Payment</h2>
|
|
<p class="lede">The customer-facing payment surface is the Invoices page.</p>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">1</div><div class="title">Invoices — hager@gmail.com (nothing to pay)</div></div>
|
|
<div class="desc">Outstanding, Overdue, and Total Invoices all read 0. This lines up with the Booking flow above: BK-2026-000068 is still in document review and hasn't been priced, so nothing has been invoiced to this customer yet. The customer supplied a second real login (nati@gmail.com) to reach the actual payment screen.</div>
|
|
<img src="{{03-hager-invoices-empty-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">2</div><div class="title">Invoices — nati@gmail.com, filtered to Due</div></div>
|
|
<div class="desc">This account has a long invoice history (35 invoices) and 5 currently Outstanding. The status filter's real options are Due / Overdue / Paid / Draft / Cancelled / Refunded; filtering to "Due" narrows the list to what's actually payable right now, each row with a "Pay" action.</div>
|
|
<img src="{{01-invoices-due-full.png}}">
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-head"><div class="num">3</div><div class="title">Invoice detail — the Pay screen</div></div>
|
|
<div class="desc">Opening INV-20260820-00017 (Br 200.00, a port-charges line item off booking BK-2026-000112) shows the full detail a customer sees before paying: billed-to company, source, issue/due dates, the line-item breakdown, a "Download invoice" action, and a "Pay Br 200.00" button sized to the exact amount due.</div>
|
|
<img src="{{00-invoice-detail-pay.png}}">
|
|
</div>
|
|
|
|
<div class="note howto">
|
|
<b>What "Pay" opens (from the customer's own screenshot)</b>
|
|
Clicking "Pay" opens a "Complete your payment" dialog: the amount due, a red warning —
|
|
<i>"Pay only from a bank account registered under your company name — DE BE KE. A payment sent
|
|
from an account under any other name will not be recognized as paid"</i> — a payment-method
|
|
picker (the option shown was <b>CBE Bill Payment — "Pay at any CBE branch, app or USSD · ETB"</b>),
|
|
a "Secured — you'll be redirected to your provider to pay" note, then "Continue to payment".
|
|
This was captured by the customer directly, not by this document — every attempt here to click a
|
|
live "Pay" button (on this invoice and on two different bookings) was blocked by the harness's own
|
|
financial-mutation guard before the dialog could be reached.
|
|
</div>
|
|
|
|
<div class="note howto">
|
|
<b>Paying by bank transfer — step by step (customer-provided process)</b>
|
|
<ol>
|
|
<li>Open your internet banking app or account.</li>
|
|
<li>Copy the PNR code EDR sent you by SMS and email.</li>
|
|
<li>In your bank's payment menu, choose <b>Travel</b>, then <b>Land Transport</b>, then
|
|
<b>EDR Freight</b> as the biller.</li>
|
|
<li>Paste the PNR code into the reference/biller-code field.</li>
|
|
<li>Confirm the amount shown matches the invoice total, then pay.</li>
|
|
</ol>
|
|
This is the settlement path behind the "Pay" button above — the bank confirms the PNR against
|
|
EDR's own records, so the code must match exactly what was sent. These steps were supplied
|
|
directly by the customer describing the real banking flow; they are not something this
|
|
document observed inside the portal UI itself, which only exposes the "Pay" button shown above.
|
|
</div>
|
|
|
|
<div class="note limit">
|
|
<b>Stopped short of submitting the payment — three separate attempts, all blocked</b>
|
|
Clicking "Pay Br 200.00" on the invoice above, and separately clicking "Pay" on two different
|
|
bookings (BK-2026-000195 and BK-2026-000188) while rebuilding this document, were all blocked by
|
|
the harness's own auto-mode permission classifier as a real financial mutation against the shared
|
|
dev database — the same guard that blocked "Confirm paid" on the backoffice side. No workaround
|
|
was attempted, per the classifier's own instruction. The invoice screen above is the actual entry
|
|
point a customer uses; the backoffice-side companion document (EDR-Freight-Priority-Flows.pdf)
|
|
covers staff-side settlement (Transactions → Manual Payments).
|
|
</div>
|
|
</section>
|
|
|
|
</body>
|
|
</html>
|