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.
278 lines
6.8 KiB
Markdown
278 lines
6.8 KiB
Markdown
# 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_approval`
|
|
* `approved`
|
|
* `cancelled`
|
|
* operational statuses
|
|
* legacy `pending_payment`
|
|
|
|
A new `Shipment.review_state` represents:
|
|
|
|
* `pending`
|
|
* `changes_requested`
|
|
* `approved`
|
|
* `rejected`
|
|
|
|
### Target workflow
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
Shipment
|
|
ShipmentPackage[]
|
|
ShipmentItem[]
|
|
```
|
|
|
|
### Required behavior
|
|
|
|
Resubmission must:
|
|
|
|
1. validate the complete order payload;
|
|
2. recalculate volumetric and chargeable weight server-side;
|
|
3. recalculate pricing server-side;
|
|
4. update Shipment fields;
|
|
5. synchronize Packages;
|
|
6. synchronize Items;
|
|
7. create a new review revision;
|
|
8. return the shipment in `pending` review 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:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
Approved → payment available
|
|
```
|
|
|
|
but the target architecture is:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
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 expects `sender_name`, `sender_phone`, etc.
|
|
* Laravel returns `receiver.*`, WordPress expects flattened receiver fields.
|
|
* Laravel returns tracking event keys `date`, `description`, `location`; WordPress expects `event_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:
|
|
|
|
1. `ShipmentStatus::isPaid()` is semantically unsafe.
|
|
2. `Shipment::isDelivered()` compares an Enum-cast field with a string.
|
|
3. `StaffOrderController` lacks explicit role/permission authorization.
|
|
4. Order Detail sender/receiver API contract is inconsistent with WordPress.
|
|
5. Tracking event API contract is inconsistent with WordPress.
|
|
6. PDF download uses a different user-meta token key from the standard Bridge token.
|
|
7. Commitment-form shipment requirements are not currently snapshotted.
|
|
8. Customer signed-document uploads currently use public storage semantics.
|
|
9. `ShipmentPackage` and `ShipmentItem` are not included in the current detailed customer order response.
|
|
10. Payment state is coupled to Shipment status.
|
|
11. Price calculation and discount consumption require a clear distinction between preview and committed pricing.
|
|
12. Existing status/schema migration history should be preserved; do not rewrite historical migrations.
|