Add comprehensive Architecture Decision Records (ADRs) detailing the new shipment review state machine, review history domain, and customer resubmission logic. This documentation establishes the separation between operational shipment status and the review lifecycle. Additionally, perform repository cleanup by removing obsolete Postman collections, environment files, test scripts, and unused migrations. - Add ADR-001 through ADR-005 regarding review workflow and state. - Add shipment review handoff documentation. - Remove redundant Postman resources and local environment configs. - Remove `test_pdf_generation.php` and `resubmit-test.json`. - Remove unused `shipment_packages` migration. - Rename and reorganize one-off maintenance scripts.
6.8 KiB
IFNEX Logistics — Architecture Decisions
ADR-001 — Shipment Review Workflow
Context
The current order workflow uses Shipment.status for operational, approval, and payment-related states simultaneously.
Current flow:
pending_approval → approved → payment → processed → ...
There is currently no independent representation for:
- review decision
- requested customer changes
- review history
- customer resubmission
Decision
Introduce an independent Review State and Review History domain without immediately removing or redesigning the existing ShipmentStatus enum.
Transitional model
Shipment.status remains backward-compatible:
pending_approvalapprovedcancelled- operational statuses
- legacy
pending_payment
A new Shipment.review_state represents:
pendingchanges_requestedapprovedrejected
Target workflow
Create Order
↓
review_state = pending
status = pending_approval
↓
Staff Review
├── Request Changes
│ ↓
│ review_state = changes_requested
│ ↓
│ Customer Edit
│ ↓
│ Resubmit
│ ↓
│ review_state = pending
│
├── Approve
│ ↓
│ review_state = approved
│ status = approved
│
└── Reject
↓
review_state = rejected
status = cancelled
Consequences
This allows the current client workflow to work without immediately breaking existing code that depends on ShipmentStatus.
Long term, approval/review state can be fully separated from operational Shipment status.
ADR-002 — Shipment Review History
Decision
Create a dedicated shipment_reviews domain instead of storing review reasons and decisions directly on shipments or using ShipmentStatusHistory as a substitute.
A review record should contain at minimum:
id
shipment_id
revision_no
decision
reason
notes
reviewed_by
reviewed_at
created_at
updated_at
The review record represents one submission/review cycle.
Rationale
ShipmentStatusHistory records operational status transitions. Review decisions are a different domain concern and require reviewer identity, reason, notes, and revision context.
ADR-003 — Customer Revision / Resubmission
Decision
Customer correction must not be implemented as a blind PATCH against the Shipment.
A resubmission updates the current shipment aggregate transactionally while creating a new review revision.
The aggregate includes:
Shipment
ShipmentPackage[]
ShipmentItem[]
Required behavior
Resubmission must:
- validate the complete order payload;
- recalculate volumetric and chargeable weight server-side;
- recalculate pricing server-side;
- update Shipment fields;
- synchronize Packages;
- synchronize Items;
- create a new review revision;
- return the shipment in
pendingreview state.
AWB remains unchanged because the customer is revising the same order.
ADR-004 — Request Changes vs Reject
Decision
These are distinct actions.
Request Changes
- order remains active;
- customer may edit;
- customer may resubmit;
- reason is mandatory;
- shipment remains operationally pre-approval.
Reject
- order is terminated;
- shipment becomes cancelled;
- customer cannot continue the same review cycle.
API concepts:
POST /staff/orders/{shipment}/request-changes
POST /staff/orders/{shipment}/approve
POST /staff/orders/{shipment}/reject
POST /customer/orders/{shipment}/resubmit
ADR-005 — Payment State
Decision
Do not derive payment state from Shipment.status.
The current implementation remains temporarily compatible with:
Approved → payment available
but the target architecture is:
Shipment Operational Status
Review State
Payment State
as separate domains.
ShipmentStatus::isPaid() must eventually be removed or deprecated because states such as cancelled, failed, and returned cannot safely imply payment completion.
ADR-006 — Order Detail API Contract
Laravel is the canonical source of the Order Detail API contract.
Target response structure:
shipment
├── status
├── review
├── sender
├── receiver
├── packages[]
├── items[]
├── financial
├── documents[]
└── tracking_events[]
WordPress must consume the canonical Laravel structure rather than relying on legacy flattened fields.
Known current contract mismatches:
- Laravel returns
sender.*, WordPress expectssender_name,sender_phone, etc. - Laravel returns
receiver.*, WordPress expects flattened receiver fields. - Laravel returns tracking event keys
date,description,location; WordPress expectsevent_date,event_description,event_time.
These mismatches must be corrected during API/UI hardening.
ADR-007 — Commitment Documents
CommitmentForm is the reusable template.
ShipmentCommitmentForm represents the requirement/instance for a particular shipment.
For the current client:
- physical delivery is the primary process;
- online upload is optional;
- signed-document upload must not block approval/payment unless explicitly required by business policy.
Required documents should eventually be instantiated/snapshotted per shipment instead of dynamically resolving the current active templates.
ADR-008 — Operational Finance Boundary
IFNEX is not intended to become a full accounting system.
IFNEX should provide logistics-relevant financial information:
- wallet
- customer receivable/debt status
- order financial status
- payment transactions
- credit/settlement information
- audit trail
A deeper accounting system should be integrated externally through API rather than recreated inside IFNEX.
ADR-009 — Production Hardening Findings
The following findings require later hardening:
ShipmentStatus::isPaid()is semantically unsafe.Shipment::isDelivered()compares an Enum-cast field with a string.StaffOrderControllerlacks explicit role/permission authorization.- Order Detail sender/receiver API contract is inconsistent with WordPress.
- Tracking event API contract is inconsistent with WordPress.
- PDF download uses a different user-meta token key from the standard Bridge token.
- Commitment-form shipment requirements are not currently snapshotted.
- Customer signed-document uploads currently use public storage semantics.
ShipmentPackageandShipmentItemare not included in the current detailed customer order response.- Payment state is coupled to Shipment status.
- Price calculation and discount consumption require a clear distinction between preview and committed pricing.
- Existing status/schema migration history should be preserved; do not rewrite historical migrations.