Move StaffApiMiddleware from the Controllers directory to the correct Middleware directory to adhere to Laravel directory structure standards. - Relocate StaffApiMiddleware from `app/Http/Controllers` to `app/Http/Middleware` - Update `api.php` to use the correct namespace for `StaffApiMiddleware` - Add `IFNEX_Logistics_Review_Workflow_HANDOFF.md` documentation for the review workflow
636 lines
12 KiB
Markdown
636 lines
12 KiB
Markdown
# IFNEX Logistics — Review Workflow & Continuation Handoff
|
||
|
||
## وضعیت پروژه
|
||
|
||
مسیر Laravel:
|
||
`C:\xampp\htdocs\IFNEX-Logistics\04_Laravel`
|
||
|
||
هدف فعلی: تکمیل Client Delivery و Hardening؛ سپس Productization.
|
||
|
||
---
|
||
|
||
## 1. Review Architecture
|
||
|
||
Review از Shipment Operational Status جدا شده است.
|
||
|
||
Review State:
|
||
- `pending`
|
||
- `changes_requested`
|
||
- `approved`
|
||
- `rejected`
|
||
|
||
جریان:
|
||
|
||
```text
|
||
Create Order
|
||
-> review_state=pending / status=pending_approval
|
||
-> Staff Review
|
||
-> Request Changes -> Customer Edit -> Resubmit -> pending
|
||
-> Approve -> review_state=approved / status=approved
|
||
-> Reject -> review_state=rejected / status=cancelled
|
||
```
|
||
|
||
Review History با مدل `ShipmentReview` و revision مستقل نگهداری میشود و جایگزین `ShipmentStatusHistory` نیست.
|
||
|
||
---
|
||
|
||
## 2. وضعیت Filament
|
||
|
||
در لیست مرسولات Actionها ساخته و تست شدهاند:
|
||
|
||
- نمایش
|
||
- ویرایش
|
||
- تأیید
|
||
- درخواست اصلاح
|
||
- رد سفارش
|
||
|
||
Approve تست شده:
|
||
- Dialog تأیید نمایش داده شد.
|
||
- پیام موفقیت نمایش داده شد.
|
||
- Status به `Approved` تغییر کرد.
|
||
- Actionهای Review از ردیف حذف شدند.
|
||
- مشتری پس از تأیید وارد مرحله پرداخت میشود.
|
||
|
||
Reject نیز تست شده:
|
||
- با موفقیت انجام شد.
|
||
- عنوان/وضعیت به «رد شد» تغییر کرد.
|
||
- Actionهای Review حذف شدند.
|
||
|
||
Request Changes هنوز باید از API و End-to-End تست شود.
|
||
|
||
---
|
||
|
||
## 3. APIهای Staff Review
|
||
|
||
در `routes/api.php` این مسیرها وجود دارند:
|
||
|
||
```text
|
||
GET /api/v1/staff/orders/pending-approval
|
||
POST /api/v1/staff/orders/{shipment}/request-changes
|
||
POST /api/v1/staff/orders/{shipment}/approve
|
||
POST /api/v1/staff/orders/{shipment}/reject
|
||
```
|
||
|
||
این گروه با:
|
||
|
||
```php
|
||
\App\Http\Middleware\StaffApiMiddleware::class
|
||
```
|
||
|
||
محافظت میشود.
|
||
|
||
---
|
||
|
||
## 4. Authorization
|
||
|
||
User از Spatie Permission استفاده میکند.
|
||
|
||
Roleهای مهم:
|
||
- `super_admin`
|
||
- `admin`
|
||
- `staff`
|
||
- `customer`
|
||
|
||
تستها:
|
||
|
||
Customer با Token معتبر -> `403 Forbidden`
|
||
|
||
Super Admin -> دسترسی موفق.
|
||
|
||
User شماره 1:
|
||
- name: مدیر کاظم
|
||
- role: `super_admin`
|
||
- Spatie role: `super_admin`
|
||
|
||
---
|
||
|
||
## 5. Pending Approval API — موفق
|
||
|
||
Endpoint:
|
||
|
||
```text
|
||
GET /api/v1/staff/orders/pending-approval
|
||
```
|
||
|
||
با Super Admin و Bearer Token تست شد و:
|
||
|
||
```text
|
||
HTTP/1.1 200 OK
|
||
```
|
||
|
||
برگشت.
|
||
|
||
یک Shipment فعلی در پاسخ:
|
||
|
||
```text
|
||
id = 22
|
||
awb_no = IFN-2026-39337
|
||
status.value = pending_approval
|
||
review.state = pending
|
||
```
|
||
|
||
API شامل:
|
||
- shipment id
|
||
- AWB
|
||
- direction/type
|
||
- status
|
||
- review
|
||
- from/to country
|
||
- user
|
||
- weight
|
||
- chargeable_weight
|
||
- total_fee
|
||
- created_at
|
||
- created_at_jalali
|
||
- pagination
|
||
|
||
است.
|
||
|
||
---
|
||
|
||
## 6. مشکل ShipmentStatus — حل شد
|
||
|
||
در `StaffOrderController.php` این import اضافه/اصلاح شده:
|
||
|
||
```php
|
||
use App\Enums\ShipmentStatus;
|
||
```
|
||
|
||
و:
|
||
|
||
```php
|
||
->where('status', ShipmentStatus::PendingApproval)
|
||
```
|
||
|
||
ابتدا خطای:
|
||
|
||
```text
|
||
Class "App\Http\Controllers\Api\ShipmentStatus" not found
|
||
```
|
||
|
||
وجود داشت.
|
||
|
||
بعد از اصلاح، Tinker تأیید کرد:
|
||
|
||
```php
|
||
\App\Enums\ShipmentStatus::PendingApproval
|
||
```
|
||
|
||
و:
|
||
|
||
```text
|
||
value = pending_approval
|
||
```
|
||
|
||
پس این مشکل حل شده است.
|
||
|
||
---
|
||
|
||
## 7. ShipmentStatus.php
|
||
|
||
فایل:
|
||
|
||
`app\Enums\ShipmentStatus.php`
|
||
|
||
Enum شامل statusهای اصلی است:
|
||
|
||
```text
|
||
pending_approval
|
||
approved
|
||
pending_payment
|
||
cancelled
|
||
processed
|
||
picked_up
|
||
in_transit
|
||
out_for_delivery
|
||
failed
|
||
delivered
|
||
returned
|
||
archived
|
||
```
|
||
|
||
متدهای مهم:
|
||
|
||
```php
|
||
isApproved()
|
||
isPendingApproval()
|
||
canBeApprovedByStaff()
|
||
canBePaid()
|
||
```
|
||
|
||
انتهای فایل بررسی شد و `canBeApprovedByStaff()` و `canBePaid()` بهدرستی بسته شدهاند.
|
||
|
||
---
|
||
|
||
## 8. مشکل ShipmentPdfController — حل شد
|
||
|
||
`route:list` ابتدا به علت نبود import صحیح برای `ShipmentPdfController` خطا میداد.
|
||
|
||
فایل واقعی:
|
||
|
||
`app\Http\Controllers\ShipmentPdfController.php`
|
||
|
||
Namespace:
|
||
|
||
```php
|
||
namespace App\Http\Controllers;
|
||
```
|
||
|
||
پس import صحیح باید بر اساس همین namespace باشد.
|
||
|
||
بعد از اصلاح، این دستور موفق شد:
|
||
|
||
```powershell
|
||
php artisan route:list --path=api/v1/staff
|
||
```
|
||
|
||
و 6 route نشان داده شد:
|
||
- customers/search
|
||
- customers/{customer}/financial-status
|
||
- orders/pending-approval
|
||
- orders/{shipment}/approve
|
||
- orders/{shipment}/reject
|
||
- orders/{shipment}/request-changes
|
||
|
||
---
|
||
|
||
## 9. مشکل PSR-4 — هنوز حل نشده
|
||
|
||
این دستور دو فایل پیدا کرده:
|
||
|
||
```powershell
|
||
Get-ChildItem .\app -Recurse -Filter "StaffApiMiddleware.php" | Select-Object FullName
|
||
```
|
||
|
||
نتیجه:
|
||
|
||
```text
|
||
app\Http\Controllers\StaffApiMiddleware.php
|
||
app\Http\Middleware\StaffApiMiddleware.php
|
||
```
|
||
|
||
Composer هشدار میدهد:
|
||
|
||
```text
|
||
Class App\Http\Middleware\StaffApiMiddleware located in
|
||
./app/Http/Controllers/StaffApiMiddleware.php
|
||
does not comply with psr-4 autoloading standard.
|
||
```
|
||
|
||
بنابراین باید قبل از هر چیز دو فایل را مقایسه کنیم.
|
||
|
||
### قدم بعدی دقیق
|
||
|
||
اجرا:
|
||
|
||
```powershell
|
||
Get-Content .\app\Http\Controllers\StaffApiMiddleware.php
|
||
```
|
||
|
||
و:
|
||
|
||
```powershell
|
||
Get-Content .\app\Http\Middleware\StaffApiMiddleware.php
|
||
```
|
||
|
||
سپس:
|
||
|
||
```powershell
|
||
Select-String -Path .\app\**\*.php -Pattern "StaffApiMiddleware"
|
||
```
|
||
|
||
هدف:
|
||
1. مشخص شود کدام فایل Middleware واقعی است.
|
||
2. بررسی شود فایل Controllers duplicate است یا خیر.
|
||
3. فقط پس از تأیید، duplicate حذف شود.
|
||
4. سپس:
|
||
|
||
```powershell
|
||
composer dump-autoload
|
||
```
|
||
|
||
و هشدار PSR-4 دیگر نباید ظاهر شود.
|
||
|
||
---
|
||
|
||
## 10. پاکسازیها
|
||
|
||
اینها با موفقیت اجرا شدهاند:
|
||
|
||
```powershell
|
||
php artisan optimize:clear
|
||
composer dump-autoload
|
||
```
|
||
|
||
Composer package discovery و Filament upgrade نیز موفق بودهاند.
|
||
|
||
---
|
||
|
||
## 11. PowerShell
|
||
|
||
نوشتن:
|
||
|
||
```text
|
||
GET /api/v1/staff/orders/pending-approval
|
||
```
|
||
|
||
مستقیم در PowerShell اشتباه است؛ PowerShell آن را command تلقی میکند.
|
||
|
||
برای تست HTTP:
|
||
|
||
```powershell
|
||
curl.exe -i `
|
||
-H "Authorization: Bearer YOUR_TOKEN" `
|
||
-H "Accept: application/json" `
|
||
http://127.0.0.1:8000/api/v1/staff/orders/pending-approval
|
||
```
|
||
|
||
---
|
||
|
||
## 12. Token
|
||
|
||
یک Token تستی برای Super Admin ساخته و استفاده شد. Token واقعی را در این فایل ثبت نکردهایم.
|
||
|
||
برای ادامه، در صورت نیاز Token جدید بساز و Token تستی را credential دائمی تلقی نکن.
|
||
|
||
---
|
||
|
||
## 13. StaffOrderController
|
||
|
||
فایل:
|
||
|
||
`app\Http\Controllers\Api\StaffOrderController.php`
|
||
|
||
متدهای اصلی:
|
||
|
||
```text
|
||
pendingApproval()
|
||
requestChanges()
|
||
approve()
|
||
reject()
|
||
formatShipment()
|
||
toJalali()
|
||
```
|
||
|
||
Business logic Review به:
|
||
|
||
```text
|
||
ShipmentReviewService
|
||
```
|
||
|
||
سپرده شده و نباید منطق اصلی Review را داخل Controller کپی کنیم.
|
||
|
||
---
|
||
|
||
## 14. تستهای بعدی
|
||
|
||
### A — Request Changes
|
||
|
||
```text
|
||
POST /api/v1/staff/orders/{shipment}/request-changes
|
||
```
|
||
|
||
نمونه:
|
||
|
||
```json
|
||
{
|
||
"reason": "لطفاً اطلاعات گیرنده اصلاح شود.",
|
||
"notes": "شماره تماس کامل نیست."
|
||
}
|
||
```
|
||
|
||
انتظار:
|
||
- `review_state = changes_requested`
|
||
- ایجاد Review History
|
||
- سفارش قابل ویرایش/Resubmit باشد.
|
||
|
||
### B — Approve API
|
||
|
||
```text
|
||
POST /api/v1/staff/orders/{shipment}/approve
|
||
```
|
||
|
||
انتظار:
|
||
|
||
```text
|
||
review_state = approved
|
||
status = approved
|
||
```
|
||
|
||
### C — Reject API
|
||
|
||
```text
|
||
POST /api/v1/staff/orders/{shipment}/reject
|
||
```
|
||
|
||
با reason اجباری.
|
||
|
||
انتظار:
|
||
|
||
```text
|
||
review_state = rejected
|
||
status = cancelled
|
||
```
|
||
|
||
### D — Customer Resubmit
|
||
|
||
پس از Request Changes:
|
||
- Customer دلیل اصلاح را ببیند.
|
||
- سفارش را اصلاح کند.
|
||
- Resubmit کند.
|
||
- Review State دوباره `pending` شود.
|
||
- revision جدید ایجاد شود.
|
||
- AWB تغییر نکند.
|
||
- Shipment/Packages/Items transactional بهروزرسانی شوند.
|
||
|
||
---
|
||
|
||
## 15. API Contract
|
||
|
||
Laravel منبع canonical Order Detail API است.
|
||
|
||
ساختار هدف:
|
||
|
||
```text
|
||
shipment
|
||
├── status
|
||
├── review
|
||
├── sender
|
||
├── receiver
|
||
├── packages[]
|
||
├── items[]
|
||
├── financial
|
||
├── documents[]
|
||
└── tracking_events[]
|
||
```
|
||
|
||
WordPress باید این contract را مصرف کند، نه اینکه روی flattened legacy fields تکیه کند.
|
||
|
||
Mismatchهای شناختهشده:
|
||
|
||
Laravel:
|
||
```text
|
||
sender.*
|
||
receiver.*
|
||
```
|
||
|
||
WordPress قدیمی:
|
||
```text
|
||
sender_name
|
||
sender_phone
|
||
receiver_name
|
||
receiver_phone
|
||
```
|
||
|
||
Tracking:
|
||
|
||
Laravel:
|
||
```text
|
||
date
|
||
description
|
||
location
|
||
```
|
||
|
||
WordPress:
|
||
```text
|
||
event_date
|
||
event_description
|
||
event_time
|
||
```
|
||
|
||
---
|
||
|
||
## 16. موارد Hardening شناختهشده
|
||
|
||
1. `ShipmentStatus::isPaid()` از نظر semantic امن نیست.
|
||
2. `Shipment::isDelivered()` باید از نظر Enum/string بررسی شود.
|
||
3. Staff authorization باید صریح و role-aware بماند.
|
||
4. Sender/receiver API contract باید یکسان شود.
|
||
5. Tracking event contract باید یکسان شود.
|
||
6. PDF token key باید با Bridge token استاندارد هماهنگ شود.
|
||
7. Commitment Form requirement باید برای Shipment snapshot شود.
|
||
8. Signed-document upload باید از public storage semantics خارج/harden شود.
|
||
9. `ShipmentPackage` و `ShipmentItem` در detailed customer response بررسی شوند.
|
||
10. Payment state نباید در بلندمدت از Shipment status استنتاج شود.
|
||
11. Preview pricing و committed pricing باید تفکیک شوند.
|
||
12. Migrationهای تاریخی rewrite نشوند.
|
||
|
||
---
|
||
|
||
## 17. Payment Architecture
|
||
|
||
هدف نهایی:
|
||
|
||
```text
|
||
Shipment Operational Status
|
||
Review State
|
||
Payment State
|
||
```
|
||
|
||
سه domain مستقل.
|
||
|
||
فعلاً:
|
||
|
||
```text
|
||
Approved -> payment available
|
||
```
|
||
|
||
اما این coupling باید در معماری نهایی حذف/deprecate شود.
|
||
|
||
---
|
||
|
||
## 18. Commitment Documents
|
||
|
||
`CommitmentForm` = template
|
||
|
||
`ShipmentCommitmentForm` = requirement/instance برای Shipment
|
||
|
||
برای Client فعلی:
|
||
- physical delivery فرآیند اصلی است.
|
||
- online upload اختیاری است.
|
||
- signed document نباید بدون business policy صریح approval/payment را block کند.
|
||
|
||
هدف بعدی: snapshot شدن required documents برای هر Shipment.
|
||
|
||
---
|
||
|
||
## 19. Finance Boundary
|
||
|
||
IFNEX نباید accounting system کامل شود.
|
||
|
||
حوزه مالی IFNEX:
|
||
- wallet
|
||
- receivable/debt
|
||
- order financial status
|
||
- payment transactions
|
||
- credit/settlement
|
||
- audit trail
|
||
|
||
Accounting عمیق در صورت نیاز باید external integration باشد.
|
||
|
||
---
|
||
|
||
## 20. End-to-End هدف
|
||
|
||
```text
|
||
Customer creates order
|
||
↓
|
||
Pending Approval
|
||
↓
|
||
Staff Review
|
||
┌────┼─────┐
|
||
↓ ↓ ↓
|
||
Changes Approve Reject
|
||
↓
|
||
Customer Edit
|
||
↓
|
||
Resubmit
|
||
↓
|
||
Pending Approval
|
||
↓
|
||
Approve
|
||
↓
|
||
Payment
|
||
```
|
||
|
||
---
|
||
|
||
## 21. ترتیب ادامه کار
|
||
|
||
1. مقایسه دو `StaffApiMiddleware.php`.
|
||
2. رفع duplicate/PSR-4 warning.
|
||
3. `composer dump-autoload`.
|
||
4. `php artisan route:list --path=api/v1/staff`.
|
||
5. تست Pending Approval مجدد.
|
||
6. تست Request Changes API.
|
||
7. تست Approve API.
|
||
8. تست Reject API.
|
||
9. بررسی `ShipmentReviewService` و `ShipmentReview`.
|
||
10. تست Customer Resubmit.
|
||
11. بررسی Customer Order Detail API.
|
||
12. هماهنگسازی WordPress Bridge با Laravel canonical contract.
|
||
13. تست End-to-End کامل.
|
||
14. سپس سایر Hardeningهای Client Delivery.
|
||
|
||
---
|
||
|
||
## 22. پیام شروع پیشنهادی برای چت جدید
|
||
|
||
```text
|
||
ما روی پروژه IFNEX-Logistics کار میکنیم.
|
||
فایل IFNEX_Logistics_Review_Workflow_HANDOFF.md را مبنا قرار بده.
|
||
|
||
آخرین وضعیت:
|
||
GET /api/v1/staff/orders/pending-approval با super_admin موفقاً HTTP 200 میدهد.
|
||
Approve و Reject در Filament تست شدهاند.
|
||
Request Changes و Resubmit هنوز باید تست شوند.
|
||
|
||
اولین کار:
|
||
دو فایل زیر را مقایسه کنیم و PSR-4 warning را بدون خراب کردن Middleware واقعی رفع کنیم:
|
||
|
||
app\Http\Controllers\StaffApiMiddleware.php
|
||
app\Http\Middleware\StaffApiMiddleware.php
|
||
|
||
بعد APIهای request-changes / approve / reject و customer resubmit را تست کنیم.
|
||
```
|