Files
edr-platform/apps/edr-freight-api/py/README.md

2.7 KiB
Raw Blame History

Contract seed driver

Creates freight contracts across every flow variant by driving the freight API over HTTP end-to-end — from DRAFT through both signatures (customer sign + staff counter-sign). It stops right after the staff counter-sign; no clearance or booking steps are run.

What it builds

20 real flows (movement × kind × customs × freight), each created twice → 40 contracts on all.

Movement Kind Customs Freight Count
intercity (DOMESTIC) one-time / general without only¹ bulk / container 4
import (IMPORT) one-time / general with / without bulk / container 8
export (EXPORT) one-time / general with / without bulk / container 8

¹ intercity + customs is not a real combo — DOMESTIC has no clearance gate, so the customs flag is ignored. Those four are skipped, leaving 20 (16 working + 4 with-customs + bulk).

The four with-customs + bulk flows are still built here: the known break is downstream in clearance (customs output docs are container-only), which this script does not reach, so all 20 reach a signed state.

Terminal status after both signatures (by dimension)

  • DOMESTIC one-time → FULLY_EXECUTED
  • any GENERAL, and DOMESTIC general → CONTRACT_ACTIVE
  • IMPORT/EXPORT one-time (customs or self-clearance) → AWAITING_CLEARANCE_DOCUMENTS (fully signed; clearance not driven)

Setup

cd apps/edr-freight-api/py
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env      # then fill it in

Fill .env: customer + admin IAM credentials (admin should be a super_admin), OTP_PHONE, and the Postgres connection (used only to read the sign-OTP).

Run

python create_contracts.py                 # all 20 flows
python create_contracts.py intercity       # only DOMESTIC flows (4)
python create_contracts.py import          # only IMPORT flows (8)
python create_contracts.py import export   # IMPORT + EXPORT (16)

Filters are by movement: intercity, import, export (pass one or many); no arg or all runs everything.

How auth + OTP work

  • Login: POST /api/auth/login with { email, password } returns a JWT (token), sent as Authorization: Bearer <token>. MFA accounts are not supported — the script errors out clearly if MFA is required.
  • Actors: the customer token does create/submit/customer-sign; the admin token does staff-accept/approve/generate/counter-sign.
  • Sign OTP: customer sign needs a fresh 6-digit OTP. The script calls POST /api/otp/send { phone }, reads the plaintext code from <schema>.otp_verifications in Postgres, then signs within the 5-minute TTL.