refactor(api): relocate StaffApiMiddleware and update routes

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
This commit is contained in:
Kazem Alghasi 2026-09-28 17:25:40 +03:30
parent 61a2643dd0
commit 69800a2b1e
4 changed files with 639 additions and 1 deletions

View File

@ -9,6 +9,7 @@ use App\Services\ShipmentReviewService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Enums\ShipmentStatus;
class StaffOrderController extends Controller
{

View File

@ -12,9 +12,11 @@ use App\Http\Controllers\Api\StaffOrderController;
use App\Http\Controllers\Api\TrackController;
use App\Http\Controllers\Api\WalletController;
use App\Http\Middleware\ApiKeyMiddleware;
use App\Http\Middleware\StaffApiMiddleware;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\BridgeAuthController;
use App\Http\Controllers\ShipmentPdfController;
// ══════════════════════════════════════════════════════════════
@ -97,7 +99,7 @@ Route::middleware(['auth:sanctum'])->prefix('v1')->group(function () {
});
// ─── Staff Orders API (تأیید سفارشات) ───
Route::middleware([\App\Http\Middleware\StaffApiMiddleware::class])
Route::middleware([StaffApiMiddleware::class])
->prefix('staff')
->group(function () {

View File

@ -0,0 +1,635 @@
# 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 را تست کنیم.
```