اضافه شدن فایل های توضیحی
This commit is contained in:
parent
673cd407a6
commit
97fa3a9561
880
01_Documents/EXCEL_ANALYSIS.md
Normal file
880
01_Documents/EXCEL_ANALYSIS.md
Normal file
@ -0,0 +1,880 @@
|
|||||||
|
# 📊 EXCEL_ANALYSIS.md — تحلیل کامل فایلهای اکسل عملیاتی
|
||||||
|
|
||||||
|
> **هدف:** مرجع کامل برای هر توسعهدهندهای که با دادههای تاریخی IFNEX کار میکند
|
||||||
|
> **فایلهای تحلیلشده:** دو فایل اکسل آپلودشده توسط مشتری در جلسه اولیه
|
||||||
|
> **تاریخ تحلیل:** August 2026
|
||||||
|
> **وضعیت:** کامل — برای مهاجرت داده و طراحی اسکیمای دیتابیس استفاده شود
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 فهرست فایلهای تحلیلشده
|
||||||
|
|
||||||
|
### فایل ۱: `4_5989927490271846355.xlsx` (فایل اصلی عملیاتی)
|
||||||
|
این فایل قلب کسبوکار IFNEX است. شامل ۱۵ شیت است که تمام منطق کسبوکار، دادههای تاریخی و قالبهای خروجی را در خود جای داده.
|
||||||
|
|
||||||
|
**شیتها:**
|
||||||
|
1. `Start` — خالی (صفحه شروع)
|
||||||
|
2. `Form` — فرم ثبت یک مرسوله (۳۴ ردیف، ۱۱۵ ستون)
|
||||||
|
3. `List` — لیست کامل مرسولات تاریخی (**۳۹۵۰ ردیف**، ۱۰۲ ستون)
|
||||||
|
4. `COUNTRIES` — جدول ۲۳۳ کشور با زونها
|
||||||
|
5. `AWB` — قالب بارنامه (Air Waybill)
|
||||||
|
6. `INVOICE + label` — قالب فاکتور
|
||||||
|
7. `label` — قالب لیبل
|
||||||
|
8. `Import Rate` — جدول نرخهای واردات (۳۸۵ ردیف)
|
||||||
|
9. `Export Rate` — جدول نرخهای صادرات (۳۸۵ ردیف)
|
||||||
|
10. `Zone` — جدول زونبندی کشورها (۲ بخش: PARCEL و DOCUMENT)
|
||||||
|
11. `DocNor` — جدول قیمت Document Normal
|
||||||
|
12. `Parcel` — جدول قیمت Parcel
|
||||||
|
13. `DocEco` — جدول قیمت Document Economy
|
||||||
|
14. `Assumptions` — تنظیمات (VAT، Packing، روزهای هفته، شهرها)
|
||||||
|
15. `DATES` — تقویم میلادی به جلالی (۷۳۲ ردیف)
|
||||||
|
|
||||||
|
### فایل ۲: `Data entry 2026-06-28.xlsx` (فایل ترکینگ دستی)
|
||||||
|
این فایل بهصورت روزانه توسط اپراتورها پر میشود و شامل دادههای ترکینگ مرسولات است. در فاز ₀، این فایل باید با پنل Filament جایگزین شود.
|
||||||
|
|
||||||
|
**شیتها:**
|
||||||
|
1. `Sheet1` — لیست رویدادهای ترکینگ (۳۱۱ ردیف)
|
||||||
|
2. `Refrence` — نگاشت کد AWB به کد ترکینگ خارجی (۱۵ ردیف)
|
||||||
|
3. `Paste` — داده خام کپیشده از وبسایتهای DHL/FedEx (۴۰۴ ردیف)
|
||||||
|
4. `copy` — نسخهی تمیزشده Sheet1 (۴۱۵ ردیف)
|
||||||
|
5. `Delivered` — لیست مرسولات تحویلشده (۹۴ ردیف)
|
||||||
|
6. `test` — آزمایشهای اپراتور (۳۹۶ ردیف)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗂️ تحلیل شیت به شیت — فایل اصلی
|
||||||
|
|
||||||
|
### شیت ۱: `Form` — فرم ثبت یک مرسوله
|
||||||
|
|
||||||
|
**ساختار:** ۳۴ ردیف × ۱۱۵ ستون (فرم افقی، نه جدولی)
|
||||||
|
|
||||||
|
**محتوای کلیدی:**
|
||||||
|
- اطلاعات مسیر (Route Information): HAWB No.، Date، Forwarder، From، To، Zone، Service، Type
|
||||||
|
- اطلاعات بسته (Shipment): Content، Weight، Volumetric Weight، Chargable Weight، Dimensions (W×L×H)
|
||||||
|
- اطلاعات فرستنده (Shipper): Company Name، Contact، Telephone، Email، Address، City، Zip، ID Number
|
||||||
|
- اطلاعات گیرنده (Receiver): همان فیلدها
|
||||||
|
- اطلاعات مالی (Payment): Shipping Price، Extra Service، Domestic Pickup، Packing Cost، Domestic Delivery، Warehousing Cost، Discount، Total Fee، Cash on Delivery
|
||||||
|
- اقلام گمرکی (۹ ردیف): No.، Description، H.S. Code، Quantity، Unit Price، Total in USD
|
||||||
|
- تنظیمات فرمول: Percent (ضریب سود)، نرخ ارز
|
||||||
|
|
||||||
|
**نکته مهم:** این شیت نشان میدهد **۹ ردیف کالای گمرکی** در هر مرسوله قابل ثبت است. این باید در فرم ثبت سفارش آنلاین (فاز ۱) لحاظ شود.
|
||||||
|
|
||||||
|
**نمونه داده واقعی:**
|
||||||
|
```
|
||||||
|
Date: 2026-07-31
|
||||||
|
Forwarder: (خالی)
|
||||||
|
From: Iran (IR)
|
||||||
|
To: USA (US)
|
||||||
|
Zone: 3
|
||||||
|
Service: Outbound
|
||||||
|
Type: NON DOC
|
||||||
|
Weight: 0 kg, Volumetric: 0 kg
|
||||||
|
Content: ITEM BEING SENT AS A GIFT N...
|
||||||
|
Status: Processed
|
||||||
|
```
|
||||||
|
|
||||||
|
**نگاشت به دیتابیس:** این شیت اساس طراحی جدول `shipments` و `shipment_items` در فاز ۱ است.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۲: `List` — لیست کامل مرسولات تاریخی ⭐ حیاتی برای مهاجرت
|
||||||
|
|
||||||
|
**ساختار:** ۳۹۵۰ ردیف × ۱۰۲ ستون
|
||||||
|
|
||||||
|
**توضیح:** این شیت، جدول اصلی دادههای تاریخی IFNEX است. هر ردیف یک مرسوله از سال ۲۰۲۰ تا الان. **این دادهها باید در فاز ₀ به جدول `shipments` مهاجرت داده شوند.**
|
||||||
|
|
||||||
|
**ستونهای کلیدی (ردیف ۱ و ۲ سرتیتر هستند):**
|
||||||
|
|
||||||
|
| # | ستون | نوع | مثال | نگاشت به DB |
|
||||||
|
|---|------|-----|------|-------------|
|
||||||
|
| ۱ | HAWB No. | String | 980100010 | `shipments.awb_no` |
|
||||||
|
| ۲ | Date | DateTime | 2020-05-02 | `shipments.created_at` |
|
||||||
|
| ۳ | Forwarder | String | DHL / FedEx / 0 | `shipment_carrier_mappings.carrier_code` |
|
||||||
|
| ۴ | From | String | Iran (IR) | `shipments.from_country_id` |
|
||||||
|
| ۵ | To | String | Germany | `shipments.to_country_id` |
|
||||||
|
| ۶ | Zone | Integer | 3 | (محاسبه میشود — ذخیره نمیشود) |
|
||||||
|
| ۷ | Service | Enum | Outbound / Inbound | `shipments.direction` |
|
||||||
|
| ۸ | Type | Enum | DocNor / NON DOC | `shipments.type` (تبدیل به DOC_NORMAL/DOC_ECONOMY/PARCEL) |
|
||||||
|
| ۹ | Weight | Decimal | 0.5 | `shipments.weight` |
|
||||||
|
| ۱۰ | Volumetric W. | Decimal | 0 | `shipments.volumetric_weight` |
|
||||||
|
| ۱۱ | Value | Decimal | 0 | (فاز ۱ — فیلد ارزش محموله) |
|
||||||
|
| ۱۲ | Content | String | EDUCATINAL DOCUEMTS | `shipments.content_description` |
|
||||||
|
| ۱۳ | Chargable Weight | Decimal | 0.5 | `shipments.chargeable_weight` |
|
||||||
|
| ۱۴-۱۶ | WIDHTH/LENGTH/HEIGHT | Integer | 25, 15, 3 | `shipments.dimensions` (بهصورت JSON یا فیلد جداگانه) |
|
||||||
|
| ۱۷ | Third party | Boolean | 0/1 | (فاز ۱) |
|
||||||
|
| ۱۸-۲۴ | Sender fields | String | (متغیر) | `shipments.sender_*` |
|
||||||
|
| ۲۵-۳۲ | Receiver fields | String | (متغیر) | `shipments.receiver_*` |
|
||||||
|
| ۳۳-۴۰ | Price fields | Decimal | (متغیر) | `shipments.shipping_price`، `extra_service`، `packing_cost`، `discount`، `total_fee` |
|
||||||
|
| ۴۱ | REASON FOR EXPORT | String | ITEM BEING SENT AS A SAMPLE... | `shipments.reason_for_export` |
|
||||||
|
| ۴۲-۸۶ | ۹ ردیف کالای گمرکی | String | (متغیر) | `shipment_items` (۹ ردیف) |
|
||||||
|
| ۸۷ | TOTAL INVOICE AMOUNT IN USD | Decimal | 114 | `shipments.invoice_total_usd` |
|
||||||
|
| ۸۸ | Last State | String | Processed | `shipments.status` (تبدیل شود) |
|
||||||
|
| ۸۹ | Last Load | DateTime | 2025-05-26 | (metadata) |
|
||||||
|
| ۹۰ | Net Dirham | Decimal | 160.69 | `shipments.net_dirham` |
|
||||||
|
| ۹۱ | Net Rial | Decimal | 73113385.32 | `shipments.net_rial` |
|
||||||
|
|
||||||
|
**نمونه رکورد کامل (ردیف ۴ — 980100011):**
|
||||||
|
```
|
||||||
|
AWB: 980100011
|
||||||
|
Date: 2026-02-26
|
||||||
|
Forwarder: 0
|
||||||
|
From: Iran (IR)
|
||||||
|
To: China (CN)
|
||||||
|
Zone: 3
|
||||||
|
Service: Outbound
|
||||||
|
Type: NON DOC
|
||||||
|
Weight: 0.1 kg, Volumetric: 0.225 kg
|
||||||
|
Value: 60 USD
|
||||||
|
Content: Electronics PCB Board
|
||||||
|
Chargeable Weight: 0.5
|
||||||
|
Dimensions: 25×15×3 cm
|
||||||
|
Sender: Akbar Salmanizadeh, +989132027178, Isfahan, IR, ID: 1283855623
|
||||||
|
Receiver: Chinapcbone Technology LTD, Ms Bindy Zhang, +8615814401212, SHENZHEN, CN, ZIP: 518103
|
||||||
|
Items:
|
||||||
|
1. IC LT1668, HS: 8542390001, Qty: 104, Unit: $1.1, Total: $114
|
||||||
|
Status: Processed
|
||||||
|
Net Dirham: 160.69
|
||||||
|
Net Rial: 73,113,385.32
|
||||||
|
```
|
||||||
|
|
||||||
|
**نکات مهاجرت:**
|
||||||
|
- ردیف ۱ و ۲ سرتیتر هستند — ردیف ۳ به بعد داده واقعی
|
||||||
|
- ردیفهای خالی زیاد است — اسکریپت باید آنها را فیلتر کند
|
||||||
|
- نام کشورها به فرمت `Iran (IR)` است — باید به `iso_code` تبدیل شود
|
||||||
|
- فیلد `Type` در اکسل شامل مقادیر متنوع است: `DocNor`، `NON DOC`، `Outbound`، `Inbound` — نیاز به استانداردسازی به enum سهحالته
|
||||||
|
- فیلد `Service` در اکسل با فیلد `direction` در DB یکی است (Outbound=export, Inbound=import)
|
||||||
|
- تاریخها میلادی هستند (نه جلالی) — خوب، نیازی به تبدیل نیست
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۳: `COUNTRIES` — جدول کشورها
|
||||||
|
|
||||||
|
**ساختار:** ۲۳۵ ردیف × ۵ ستون
|
||||||
|
|
||||||
|
**ستونها:**
|
||||||
|
1. `COUNTRIES` — نام کشور با کد ISO در پرانتز، مثلاً `Afghanistan (AF)`
|
||||||
|
2. `EXPORT ZONES` — زون صادرات (عدد ۱ تا ۱۰)
|
||||||
|
3. `IMPORT ZONES` — زون واردات (عدد ۱ تا ۱۰)
|
||||||
|
4. `Service` — فقط چند ردیف اول پر است (مثلاً `Inbound`، `Outbound`، `Visa Pick Up`) — بهنظر میرسد دستی وارد شده، نادیده بگیر
|
||||||
|
5. `Content` — فقط چند ردیف اول پر است (`DOC`، `NON DOC`) — نادیده بگیر
|
||||||
|
|
||||||
|
**نکته مهم:** این شیت، **منبع نهایی زونبندی نیست**. شیت `Zone` (شیت ۱۰) منبع دقیقتری است چون زونهای مجزا برای PARCEL و DOCUMENT دارد. اما این شیت (`COUNTRIES`) برای تأیید تعداد کشورها (۲۳۳ کشور واقعی، با چند مورد تکراری) استفاده میشود.
|
||||||
|
|
||||||
|
**نمونه داده:**
|
||||||
|
```
|
||||||
|
Afghanistan (AF) | 7 | 8
|
||||||
|
Albania (AL) | 6 | 8
|
||||||
|
Algeria (DZ) | 6 | 8
|
||||||
|
...
|
||||||
|
Iran (IR) | (خالی — ایران مبدا/مقصد داخلی است)
|
||||||
|
...
|
||||||
|
Yemen (YE) | 7 | 8
|
||||||
|
```
|
||||||
|
|
||||||
|
**نگاشت به دیتابیس:** این شیت فقط برای استخراج `name` و `iso_code` استفاده میشود. زونها از شیت `Zone` (که دقیقتر است) گرفته میشوند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۴: `AWB` — قالب بارنامه (Air Waybill)
|
||||||
|
|
||||||
|
**ساختار:** ۱۸۵۶ ردیف × ۱۵ ستون (قالب افقی، چند بارنامه در یک شیت)
|
||||||
|
|
||||||
|
**محتوا:** قالب PDF بارنامه IFNEX. هر بارنامه شامل:
|
||||||
|
- شماره AWB (مثلاً 980100011)
|
||||||
|
- تاریخ
|
||||||
|
- لوگوی IFNEX (با متن "We Deliver Value")
|
||||||
|
- اطلاعات فرستنده و گیرنده (در دو بلوک)
|
||||||
|
- اطلاعات بسته (وزن، ابعاد)
|
||||||
|
- اطلاعات پرداخت (قیمت به IRR)
|
||||||
|
- بارکد (در اکسل تصویر، در لاراول باید تولید شود)
|
||||||
|
|
||||||
|
**نکته:** این قالب باید در فاز ۱ بهصورت PDF در لاراول بازسازی شود. خروجی PDF باید **انگلیسی** باشد (مطابق اکسل اصلی).
|
||||||
|
|
||||||
|
**نگاشت:** قالب PDF با Dompdf یا Snappy در لاراول — فاز ۱.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۵: `INVOICE + label` — قالب فاکتور
|
||||||
|
|
||||||
|
**ساختار:** ۱۸۳۵ ردیف × ۱۲ ستون
|
||||||
|
|
||||||
|
**محتوا:** قالب فاکتور تجاری (Commercial Invoice) شامل:
|
||||||
|
- INVOICE NO (همان AWB)
|
||||||
|
- DATE
|
||||||
|
- SHIPPER (نام شرکت، آدرس، تلفن، ایمیل)
|
||||||
|
- CONSIGNEE (همان فیلدها برای گیرنده)
|
||||||
|
- لیست اقلام (Description، HS Code، Quantity، Unit Price، Total)
|
||||||
|
- TOTAL INVOICE AMOUNT IN USD
|
||||||
|
|
||||||
|
**نکته:** در فاز ۱، این قالب بهصورت PDF تولید میشود. فیلدهای invoice باید با فیلدهای `shipment_items` در دیتابیس منطبق باشند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۶: `label` — قالب لیبل
|
||||||
|
|
||||||
|
**ساختار:** ۱۱ ردیف × ۱۳ ستون
|
||||||
|
|
||||||
|
**محتوا:** قالب لیبل چاپی برای چاپگرهای حرارتی. شامل:
|
||||||
|
- شماره AWB (بارکد)
|
||||||
|
- وزن ناخالص (Gross Weight)
|
||||||
|
- ابعاد (W×L×H)
|
||||||
|
- وزن حجمی (Volumetric)
|
||||||
|
- تاریخ
|
||||||
|
- کشور مبدا و مقصد
|
||||||
|
|
||||||
|
**نکته:** در فاز ۱، این قالب بهصورت PDF کوچک (مثلاً ۱۰۰×۱۰۰ میلیمتر) تولید میشود. مخصوص چاپگرهای حرارتی دفتر اصفهان.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۷: `Import Rate` — نرخهای واردات
|
||||||
|
|
||||||
|
**ساختار:** ۳۸۵ ردیف × ۱۱ ستون
|
||||||
|
|
||||||
|
**ساختار جدول:**
|
||||||
|
- ردیف ۳: عنوان "ROW TO IRAN - IMPORT RATE SCHEDULE"
|
||||||
|
- ردیف ۴: زیرعنوان "DOCUMENT"
|
||||||
|
- ردیف ۵: سرتیتر ستونها — `Weight (kg) | Zone 1 | Zone 2 | Zone 3 | ... | Zone 10`
|
||||||
|
- ردیف ۶ به بعد: قیمت پایه به **درهم (AED)** برای هر ترکیب وزن × زون
|
||||||
|
- ردیف ۱۰: زیرعنوان "NON - DOCUMENT"
|
||||||
|
- ردیف ۱۱: سرتیتر (تکراری)
|
||||||
|
- ردیف ۱۲ به بعد: قیمت برای NON-DOC
|
||||||
|
|
||||||
|
**نمونه داده (DOCUMENT):**
|
||||||
|
```
|
||||||
|
Weight | Zone 1 | Zone 2 | Zone 3 | Zone 4 | Zone 5 | Zone 6 | Zone 7 | Zone 8 | Zone 9 | Zone 10
|
||||||
|
0.5 | 149.32 | 169.67 | 214.14 | 231.90 | 242.64 | 255.16 | 273.96 | 383.02 | 85.71 | 85.71
|
||||||
|
1.0 | 197.20 | 195.61 | 253.99 | 245.99 | 295.54 | 308.56 | 329.35 | 390.16 | 92.86 | 92.86
|
||||||
|
1.5 | 243.41 | 237.62 | 301.99 | 272.61 | 348.30 | 348.30 | 409.41 | 429.65 | 100 | 100
|
||||||
|
2.0 | 280.61 | 282.51 | 317.42 | 290.62 | 384.39 | 384.39 | 494.54 | 474.51 | 114.29 | 114.29
|
||||||
|
```
|
||||||
|
|
||||||
|
**نکته مهم:** این جدول فقط ۲ بخش دارد (DOCUMENT و NON-DOCUMENT). اما شیتهای `DocNor`، `DocEco`، `Parcel` نشان میدهند که در واقع **۳ نوع سرویس** وجود دارد. تضاد وجود دارد:
|
||||||
|
|
||||||
|
- شیت `Import Rate` فقط ۲ نوع دارد (DOCUMENT و NON-DOC)
|
||||||
|
- شیتهای جداگانه `DocNor`، `DocEco`، `Parcel` قیمتهای متفاوتی نشان میدهند
|
||||||
|
|
||||||
|
**تفسیر:** احتمالاً شیت `Import Rate` جدول قدیمی است و شیتهای DocNor/DocEco/Parcel نسخهی جدیدتر و دقیقتر هستند. در فاز ۱، باید این موضوع را با مشتری تأیید کرد. فعلاً در فاز ۰، فقط جدول `shipping_rates` را با فیلد `type` از نوع enum سهحالته (`DOC_NORMAL`, `DOC_ECONOMY`, `PARCEL`) طراحی میکنیم.
|
||||||
|
|
||||||
|
**نگاشت به دیتابیس:** جدول `shipping_rates` در فاز ۱ (طبق `Phase0_Proposal.md` بخش ۶.۲).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۸: `Export Rate` — نرخهای صادرات
|
||||||
|
|
||||||
|
**ساختار:** مشابه شیت Import Rate — ۳۸۵ ردیف × ۱۱ ستون
|
||||||
|
|
||||||
|
**عنوان:** "IRAN TO ROW - EXPORT RATE SCHEDULE"
|
||||||
|
|
||||||
|
**نکته:** ساختار و تضادها دقیقاً مشابه شیت Import Rate است.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۹: `Zone` — جدول زونبندی کشورها ⭐ منبع نهایی زونها
|
||||||
|
|
||||||
|
**ساختار:** ۲۳۰ ردیف × ۷ ستون (دو جدول کنار هم)
|
||||||
|
|
||||||
|
**چیدمان:**
|
||||||
|
- ستون ۱-۳: جدول PARCEL (شماره، کشور، زون)
|
||||||
|
- ستون ۵-۷: جدول DOCUMENT (شماره، کشور، زون)
|
||||||
|
|
||||||
|
**نمونه داده:**
|
||||||
|
```
|
||||||
|
PARCEL DOCUMENT
|
||||||
|
No. | Country | Zone No. | Country | Zone
|
||||||
|
1 | Afghanistan | 7 1 | Afghanistan | 5
|
||||||
|
2 | Albania | 3 2 | Albania | 7
|
||||||
|
3 | Algeria | 4 3 | Algeria | 7
|
||||||
|
4 | Americam Samoa | 7 4 | Andorra | 7
|
||||||
|
5 | Andorra | 3 5 | Angola | 6
|
||||||
|
6 | Angola | 7 6 | Anguilla | 6
|
||||||
|
7 | Anguilla | 7 7 | Antigua | 6
|
||||||
|
8 | Antigua | 7 8 | Argentina | 7
|
||||||
|
9 | Argentina | 7 9 | Armenia | 7
|
||||||
|
10 | Armenia | 3 10 | Aruba | 7
|
||||||
|
11 | Aruba | 7 11 | Australia | 6
|
||||||
|
12 | Australia | 7 12 | Austria | 3
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ کشف کلیدی:** همان کشور برای PARCEL و DOCUMENT زونهای متفاوتی دارد!
|
||||||
|
|
||||||
|
| کشور | PARCEL Zone | DOCUMENT Zone | تفاوت |
|
||||||
|
|------|-------------|---------------|-------|
|
||||||
|
| Afghanistan | 7 | 5 | ۲ |
|
||||||
|
| Albania | 3 | 7 | ۴ |
|
||||||
|
| Algeria | 4 | 7 | ۳ |
|
||||||
|
| Armenia | 3 | 7 | ۴ |
|
||||||
|
| Australia | 7 | 6 | ۱ |
|
||||||
|
| Austria | 3 | 3 | ۰ |
|
||||||
|
|
||||||
|
**نتیجه:** جدول `countries` باید **۴ زون مجزا** داشته باشد:
|
||||||
|
- `export_zone_parcel` — زون صادرات برای پارسل
|
||||||
|
- `export_zone_doc` — زون صادرات برای داکیومنت
|
||||||
|
- `import_zone_parcel` — زون واردات برای پارسل
|
||||||
|
- `import_zone_doc` — زون واردات برای داکیومنت
|
||||||
|
|
||||||
|
این موضوع در `Phase0_Proposal.md` بخش ۶.۱ منعکس شده. هرگز به ۲ زون برگردان.
|
||||||
|
|
||||||
|
**نکته:** شیت `Zone` فقط زونهای export را دارد (از ایران به سایر کشورها). زونهای import باید از شیت `COUNTRIES` استخراج شوند یا از مشتری درخواست شود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۱۰: `DocNor` — جدول قیمت Document Normal
|
||||||
|
|
||||||
|
**ساختار:** ۷۱ ردیف × ۳ ستون
|
||||||
|
|
||||||
|
**فرمت:** Long format (نه Wide)
|
||||||
|
```
|
||||||
|
Weight | Attribute | Value
|
||||||
|
0.5 | 1 | 2,810,429.42
|
||||||
|
0.5 | 2 | 3,600,277.54
|
||||||
|
0.5 | 3 | 5,104,556.32
|
||||||
|
0.5 | 4 | 5,641,878.04
|
||||||
|
0.5 | 5 | 6,108,148.95
|
||||||
|
0.5 | 6 | 7,213,877.11
|
||||||
|
0.5 | 7 | 8,289,630.71
|
||||||
|
1.0 | 1 | 4,049,673.89
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
**تفسیر:**
|
||||||
|
- `Weight` — وزن (۰.۵، ۱، ۱.۵، ۲، ۲.۵ کیلوگرم)
|
||||||
|
- `Attribute` — شماره زون (۱ تا ۱۰)
|
||||||
|
- `Value` — قیمت **به ریال ایران (IRR)**
|
||||||
|
|
||||||
|
**نکته:** برخلاف شیتهای Import/Export Rate که قیمت به **درهم** بود، اینجا قیمت به **ریال** است. این یعنی فرمول تبدیل (درهم × ضریب سود × نرخ روز درهم = ریال) در این شیت اعمال شده.
|
||||||
|
|
||||||
|
**نگاشت:** این دادهها در فاز ۱ به جدول `shipping_rates` با `type = DOC_NORMAL` مهاجرت داده میشوند. اما بهجای ذخیره ریال، باید قیمت پایه درهم را ذخیره کنیم (مطابق شیت Import/Export Rate).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۱۱: `Parcel` — جدول قیمت Parcel
|
||||||
|
|
||||||
|
**ساختار:** ۱۴۱ ردیف × ۳ ستون (مشابه DocNor)
|
||||||
|
|
||||||
|
**نکته:** وزنها تا ۵ کیلوگرم (یا بیشتر) میرسد — برای پارسل محدوده وزن بیشتر است.
|
||||||
|
|
||||||
|
**نگاشت:** جدول `shipping_rates` با `type = PARCEL`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۱۲: `DocEco` — جدول قیمت Document Economy
|
||||||
|
|
||||||
|
**ساختار:** ۷۱ ردیف × ۳ ستون (مشابه DocNor)
|
||||||
|
|
||||||
|
**نگاشت:** جدول `shipping_rates` با `type = DOC_ECONOMY`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۱۳: `Assumptions` — تنظیمات
|
||||||
|
|
||||||
|
**ساختار:** ۲۵۱ ردیف × ۱۷ ستون (ترکیبی از تنظیمات و جداول کمکی)
|
||||||
|
|
||||||
|
**محتوای کلیدی:**
|
||||||
|
- ردیف ۳-۶: تنظیمات سرویسها و VAT
|
||||||
|
- `DocNor` با VAT: ۰.۰۹ (۹٪) و Packing: ۱۰۰,۰۰۰ ریال
|
||||||
|
- `DocEco` — خالی
|
||||||
|
- `Parcel` — خالی
|
||||||
|
- ردیف ۳-۹ (ستون ۸-۹): روزهای هفته (میلادی و شمسی)
|
||||||
|
- ردیف ۳-۹ (ستون ۱۴-۱۵): شهرهای ایران با کد (اصفهان=۰۱، شیراز=۰۲، مشهد=۰۳، ...)
|
||||||
|
- ردیف ۱۰ به بعد (ستون ۱۷): لیست کشورها (به ترتیب حروف الفبا)
|
||||||
|
|
||||||
|
**⚠️ کشف کلیدی — VAT:**
|
||||||
|
VAT در فایل اکسل ۹٪ است (`0.09`). این فیلد در PRD قدیمی ذکر نشده بود. در `Phase0_Proposal.md` به فیلدهای مالی جدول `shipments` اضافه شده.
|
||||||
|
|
||||||
|
**⚠️ کشف کلیدی — Packing:**
|
||||||
|
هزینه بستهبندی پیشفرض: ۱۰۰,۰۰۰ ریال. این فیلد هم در PRD غایب بود.
|
||||||
|
|
||||||
|
**نگاشت به دیتابیس:** این مقادیر در جدول `system_settings` ذخیره میشوند:
|
||||||
|
```sql
|
||||||
|
('vat_rate', 0.09, 'VAT rate — 9%'),
|
||||||
|
('packing_cost_default', 100000, 'Default packing cost in IRR'),
|
||||||
|
('profit_margin', 1.25, 'Profit margin — set per company'),
|
||||||
|
('aed_to_irr', [نرخ روز], 'AED to IRR exchange rate'),
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۱۴: `DATES` — تقویم میلادی به جلالی
|
||||||
|
|
||||||
|
**ساختار:** ۷۳۲ ردیف × ۱۲ ستون
|
||||||
|
|
||||||
|
**ستونها:** Miladi، Jalali_1، Jalali_2، Jalali_3، myear، jyear، mmonthN، jmonthN، mmonthT، jmonthT، mnime، jnime
|
||||||
|
|
||||||
|
**نکته:** این جدول روش قدیمی IFNEX برای تبدیل تاریخ بوده. در لاراول نیازی به این نیست — از پکیج `morilog/jalali` استفاده میشود. این شیت در مهاجرت نادیده گرفته میشود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗂️ تحلیل شیت به شیت — فایل ترکینگ دستی
|
||||||
|
|
||||||
|
### شیت ۱: `Sheet1` — لیست رویدادهای ترکینگ
|
||||||
|
|
||||||
|
**ساختار:** ۳۱۱ ردیف × ۸ ستون
|
||||||
|
|
||||||
|
**ستونها:**
|
||||||
|
1. `AWB` — شماره بارنامه IFNEX (مثلاً 980103619)
|
||||||
|
2. `Last State` — آخرین وضعیت (مثلاً "Failed attempt") — فقط در موارد خاص پر شده
|
||||||
|
3. `Date` — تاریخ رویداد
|
||||||
|
4. `Time` — زمان رویداد
|
||||||
|
5. `State` — توضیح رویداد (مثلاً "Picked up by Naqel")
|
||||||
|
6. `Country` — لوکیشن (مثلاً DUBAI، MUSCAT - OMAN)
|
||||||
|
7. `Location` — معمولاً "." (نقطه)
|
||||||
|
8. `Order No` — شماره ترتیب رویداد
|
||||||
|
|
||||||
|
**نمونه داده (بارنامه 980103619):**
|
||||||
|
```
|
||||||
|
AWB | Last State | Date | Time | State | Country | Location | Order No
|
||||||
|
980103619 | | 2026-06-20 | 06:35 | Waybill created. Shipment h... | SYSTEM | . | 9
|
||||||
|
980103619 | | 2026-06-24 | 02:56 | Picked up by Naqel | DUBAI | . | 10
|
||||||
|
980103619 | | 2026-06-24 | 03:01 | Arrived at Naqel Facility | DUBAI | . | 11
|
||||||
|
980103619 | | 2026-06-24 | 03:06 | Re-Weight | DUBAI | . | 12
|
||||||
|
980103619 | | 2026-06-24 | 07:05 | Out For Delivery with Courier | DUBAI | . | 13
|
||||||
|
980103619 | | 2026-06-24 | 07:57 | Prepared for delivery | DUBAI | . | 14
|
||||||
|
980103619 | | 2026-06-24 | 17:16 | Delivery attempted – City/A... | AJMAN | . | 15
|
||||||
|
980103619 | | 2026-06-25 | 07:27 | Out For Delivery with Courier | DUBAI | . | 16
|
||||||
|
980103619 | | 2026-06-25 | 10:34 | Prepared for delivery | DUBAI | . | 17
|
||||||
|
980103619 | Failed attempt| 2026-06-25 | 19:43 | Delivery attempted – Consig... | DUBAI | . | 18
|
||||||
|
```
|
||||||
|
|
||||||
|
**نگاشت به دیتابیس:** این شیت مستقیماً به جدول `shipment_tracking_events` نگاشت میشود:
|
||||||
|
- `AWB` → `shipment_id` (با lookup در `shipments`)
|
||||||
|
- `Date` + `Time` → `event_date` + `event_time`
|
||||||
|
- `State` → `event_description`
|
||||||
|
- `Country` → `location`
|
||||||
|
- `Last State` → `delivery_status` (اگر پر شده باشد)
|
||||||
|
- `Order No` → نادیده (ترتیب با timestamp مشخص میشود)
|
||||||
|
|
||||||
|
**نکته مهاجرت:** این دادهها میتوانند در فاز ₀ به `shipment_tracking_events` با `source = 'manual'` مهاجرت داده شوند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۲: `Refrence` — نگاشت کد AWB به کد ترکینگ خارجی ⭐ حیاتی
|
||||||
|
|
||||||
|
**ساختار:** ۱۵ ردیف × ۸ ستون
|
||||||
|
|
||||||
|
**ستونها:**
|
||||||
|
1. `Tracking Number` — کد ترکینگ شرکت خارجی
|
||||||
|
2. `Reference Number` — شماره AWB داخلی IFNEX
|
||||||
|
3. `Delivery` — وضعیت تحویل (مثلاً "Delivered")
|
||||||
|
4. `Booking Number` — شماره رزرو
|
||||||
|
5. `IM/EX` — شرکت حمل (DHL، Naghel، UPS، ...)
|
||||||
|
6. `To Country` — کشور مقصد
|
||||||
|
7. `Item Description` — توضیحات (گاهی شامل هزینههای اضافی مثل "100.00AED disposal charge")
|
||||||
|
8. `Delivery Agent` — عامل تحویل
|
||||||
|
|
||||||
|
**نمونه داده:**
|
||||||
|
```
|
||||||
|
Tracking Number | Reference Number | Delivery | Booking Number | IM/EX | To Country | Item Description
|
||||||
|
2329941040 | 980103609 | | | DHL | |
|
||||||
|
408638268 | 980103612 | | | Naghel | |
|
||||||
|
8252492625 | 980103613 | | | DHL | |
|
||||||
|
7095511345 | 980103614 | | | DHL | |
|
||||||
|
1Z483Y5W0491404336 | 980103079 | 991035590| | | China | UPS, 100.00AED disposal charge
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ کشف کلیدی — چندین شرکت حمل:**
|
||||||
|
این شیت نشان میدهد که شرکتهای حمل زیر در سیستم IFNEX فعال هستند:
|
||||||
|
|
||||||
|
| کد | نام شرکت | نوع | پشتیبانی API |
|
||||||
|
|----|----------|-----|--------------|
|
||||||
|
| DHL | DHL Express | بینالمللی | ✅ |
|
||||||
|
| FEDEX | FedEx | بینالمللی | ✅ |
|
||||||
|
| UPS | UPS | بینالمللی | ✅ |
|
||||||
|
| ARAMEX | Aramex | منطقهای (خاورمیانه) | ✅ |
|
||||||
|
| NAGHEL / Naqel | Naqel | منطقهای (امارات) | ⚠️ محدود |
|
||||||
|
| EMX | EMX | منطقهای | ❌ |
|
||||||
|
| APSITEX | APSITEX | داخلی ایران | ❌ |
|
||||||
|
| IMPEX | IMPEX | منطقهای | ❌ |
|
||||||
|
|
||||||
|
**نتیجه:** فقط حدود ۵۰-۶۰٪ مرسولات در فاز ۳ از طریق API قابل ترکینگ خودکار هستند. بقیه همچنان دستی میمانند. این موضوع در `Phase0_Proposal.md` بخش ۷.۴ لحاظ شده.
|
||||||
|
|
||||||
|
**⚠️ کشف کلیدی — هزینههای جانبی متغیر:**
|
||||||
|
ردیف ۱۵ نشان میدهد که گاهی هزینههای اضافی در زمان تحویل از سمت شرکت حمل اعمال میشود (مثلاً "100.00AED disposal charge"). این فیلد باید در `shipment_carrier_mappings.notes` ذخیره شود و در محاسبه سود نهایی لحاظ گردد.
|
||||||
|
|
||||||
|
**نگاشت به دیتابیس:** این شیت مستقیماً به جدول `shipment_carrier_mappings` نگاشت میشود:
|
||||||
|
- `Tracking Number` → `carrier_tracking_number`
|
||||||
|
- `Reference Number` → `shipment_id` (با lookup)
|
||||||
|
- `Booking Number` → `booking_number`
|
||||||
|
- `IM/EX` → `carrier_code` (تبدیل به enum)
|
||||||
|
- `To Country` → (نادیده یا ذخیره در metadata)
|
||||||
|
- `Item Description` → `notes`
|
||||||
|
- `Delivery` → `delivery_status`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۳: `Paste` — داده خام کپیشده
|
||||||
|
|
||||||
|
**ساختار:** ۴۰۴ ردیف × ۱۱ ستون
|
||||||
|
|
||||||
|
**توضیح:** این شیت دادههای خام کپیشده از وبسایتهای DHL/FedEx/UPS را در خود دارد. اپراتور این دادهها را پردازش میکند و به `Sheet1` و `copy` منتقل میکند.
|
||||||
|
|
||||||
|
**ستونها:** Tracking number (دو ستون)، شماره ترتیب N، اطلاعات Origin/Destination، Date، Local Time، Location، Event label، Delivery status
|
||||||
|
|
||||||
|
**نکته:** این شیت برای مهاجرت نادیده گرفته میشود — دادههای تمیز در `Sheet1` و `copy` هستند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۴: `copy` — نسخه تمیزشده
|
||||||
|
|
||||||
|
**ساختار:** ۴۱۵ ردیف × ۹ ستون
|
||||||
|
|
||||||
|
**توضیح:** نسخهی پاکسازیشدهی Sheet1 با فیلدهای مرتبتر. ستونها:
|
||||||
|
1. Tracking number
|
||||||
|
2. AWB
|
||||||
|
3. Delivery status
|
||||||
|
4. Date
|
||||||
|
5. Local Time
|
||||||
|
6. Event label
|
||||||
|
7. Location
|
||||||
|
8. (خالی)
|
||||||
|
9. Order No
|
||||||
|
|
||||||
|
**نکته:** این شیت و `Sheet1` تکراری هستند. برای مهاجرت از `Sheet1` استفاده کنید چون کاملتر است.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۵: `Delivered` — لیست مرسولات تحویلشده
|
||||||
|
|
||||||
|
**ساختار:** ۹۴ ردیف × ۸ ستون
|
||||||
|
|
||||||
|
**توضیح:** لیست مرسولاتی که با موفقیت تحویل داده شدهاند. شامل:
|
||||||
|
- Tracking Number
|
||||||
|
- Reference Number (AWB)
|
||||||
|
- Sl No (معمولاً "Delivered" یا شماره)
|
||||||
|
- Booking Number
|
||||||
|
- Company Code (مثلاً 1012، IMPEX)
|
||||||
|
- To Country
|
||||||
|
- Item Description
|
||||||
|
- Delivery Agent
|
||||||
|
|
||||||
|
**نکته:** این شیت برای آمارگیری استفاده میشود. در دیتابیس نیازی به آن نیست — میتوان با query روی `shipment_tracking_events` لیست مشابه تولید کرد.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### شیت ۶: `test` — آزمایشهای اپراتور
|
||||||
|
|
||||||
|
**ساختار:** ۳۹۶ ردیف × ۸ ستون (با چند ساختار متفاوت در یک شیت)
|
||||||
|
|
||||||
|
**توضیح:** شیت آزمایشی اپراتور. دادهها معتبر نیستند و برای مهاجرت نادیده گرفته میشوند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔢 فرمول قیمتگذاری (Pricing Formula)
|
||||||
|
|
||||||
|
بر اساس شیت `Form` و `Assumptions`، فرمول کامل محاسبه قیمت نهایی:
|
||||||
|
|
||||||
|
### مراحل محاسبه
|
||||||
|
|
||||||
|
#### مرحله ۱: محاسبه وزن حجمی
|
||||||
|
```
|
||||||
|
Volumetric Weight (kg) = (Width × Length × Height) / 5000
|
||||||
|
```
|
||||||
|
- ابعاد به سانتیمتر
|
||||||
|
- تقسیم بر ۵۰۰۰ استاندارد جهانی هوایی
|
||||||
|
|
||||||
|
#### مرحله ۲: تعیین وزن قابل پرداخت
|
||||||
|
```
|
||||||
|
Chargeable Weight = MAX(Actual Weight, Volumetric Weight)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مرحله ۳: استخراج زون
|
||||||
|
```
|
||||||
|
Zone = lookup(country, direction, type)
|
||||||
|
```
|
||||||
|
- اگر direction=export و type=PARCEL → از `countries.export_zone_parcel`
|
||||||
|
- اگر direction=export و type=DOC_* → از `countries.export_zone_doc`
|
||||||
|
- اگر direction=import و type=PARCEL → از `countries.import_zone_parcel`
|
||||||
|
- اگر direction=import و type=DOC_* → از `countries.import_zone_doc`
|
||||||
|
|
||||||
|
#### مرحله ۴: استخراج قیمت پایه (به درهم)
|
||||||
|
```
|
||||||
|
Base Price (AED) = shipping_rates[direction, type, chargeable_weight, zone]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مرحله ۵: اعمال ضریب سود
|
||||||
|
```
|
||||||
|
After Profit (AED) = Base Price × Profit Margin (مثلاً 1.25)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مرحله ۶: تبدیل به ریال
|
||||||
|
```
|
||||||
|
After Conversion (IRR) = After Profit (AED) × AED_to_IRR_Rate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مرحله ۷: اضافه هزینههای جانبی
|
||||||
|
```
|
||||||
|
Subtotal (IRR) = After Conversion
|
||||||
|
+ Extra Service (IRR)
|
||||||
|
+ Domestic Pickup (IRR)
|
||||||
|
+ Packing Cost (IRR)
|
||||||
|
+ Domestic Delivery (IRR)
|
||||||
|
+ Warehousing Cost (IRR)
|
||||||
|
- Discount (IRR)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### مرحله ۸: اعمال VAT
|
||||||
|
```
|
||||||
|
Total Fee (IRR) = Subtotal × (1 + VAT Rate)
|
||||||
|
```
|
||||||
|
- VAT Rate = 0.09 (۹٪) — از شیت Assumptions
|
||||||
|
|
||||||
|
#### مرحله ۹: ذخیره خروجیها
|
||||||
|
```
|
||||||
|
shipments.shipping_price = Base Price (AED)
|
||||||
|
shipments.net_dirham = After Profit (AED)
|
||||||
|
shipments.net_rial = Total Fee (IRR)
|
||||||
|
shipments.total_fee = Total Fee (IRR)
|
||||||
|
```
|
||||||
|
|
||||||
|
### نکتهی مهم: محمولههای بالای ۳۰ کیلوگرم
|
||||||
|
|
||||||
|
طبق PRD قدیمی (بخش ۳.۱): «محمولههای بالای ۳۰ کیلوگرم مشمول نرخهای ویژه (Spot Rate) هستند و محاسبه آنلاین ندارند و باید توسط ادمین تأیید شوند.»
|
||||||
|
|
||||||
|
این قانون باید در فرم استعلام قیمت (فاز ۱) لحاظ شود: اگر وزن > ۳۰ کیلوگرم، بهجای محاسبه، پیام «کارشناس ما تماس میگیرد» نمایش داده شود.
|
||||||
|
|
||||||
|
### نمونه محاسبه واقعی (از شیت List، AWB 980100011)
|
||||||
|
|
||||||
|
```
|
||||||
|
Direction: Export (Outbound)
|
||||||
|
Type: NON DOC → PARCEL
|
||||||
|
From: Iran (IR)
|
||||||
|
To: China (CN)
|
||||||
|
Weight: 0.1 kg
|
||||||
|
Volumetric Weight: (25 × 15 × 3) / 5000 = 0.225 kg
|
||||||
|
Chargeable Weight: MAX(0.1, 0.225) = 0.225 kg → 0.5 (طبق اکسل)
|
||||||
|
Zone: 3 (از شیت List)
|
||||||
|
Items:
|
||||||
|
1. IC LT1668, HS: 8542390001, Qty: 104, Unit: $1.1, Total: $114
|
||||||
|
Invoice Total: $114
|
||||||
|
Net Dirham: 160.69
|
||||||
|
Net Rial: 73,113,385.32
|
||||||
|
|
||||||
|
محاسبه:
|
||||||
|
Base Price (AED) = ? (از جدول Parcel)
|
||||||
|
After Profit (AED) = Base × 1.25
|
||||||
|
Net Dirham = 160.69 → پس Base Price = 160.69 / 1.25 = 128.55 AED
|
||||||
|
AED_to_IRR = 73,113,385.32 / 160.69 ≈ 455,057 IRR per AED
|
||||||
|
```
|
||||||
|
|
||||||
|
این تحلیل نشان میدهد که **نرخ درهم به ریال در زمان این محموله حدود ۴۵۵,۰۰۰ ریال بوده**. این نرخ باید در `system_settings` ذخیره شود و قابل بهروزرسانی باشد.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 قوانین رهگیری (Tracking Logic)
|
||||||
|
|
||||||
|
### نگاشت کد IFNEX به کد خارجی
|
||||||
|
|
||||||
|
مشتری IFNEX به مشتری یک کد اختصاصی میدهد (مثلاً `IFN-525` یا `980103619`). اما بسته ممکن است با کد دیگری (مثلاً `65986555` در DHL) ارسال شود.
|
||||||
|
|
||||||
|
**در دیتابیس:**
|
||||||
|
- `shipments.awb_no` = کد IFNEX (مثلاً 980103619)
|
||||||
|
- `shipment_carrier_mappings.carrier_tracking_number` = کد خارجی (مثلاً 408638240)
|
||||||
|
|
||||||
|
مشتری همیشه با کد IFNEX جستجو میکند. سیستم در پسزمینه:
|
||||||
|
- در فاز ₀: رویدادها را بهصورت دستی در `shipment_tracking_events` با `source = 'manual'` ذخیره میکند
|
||||||
|
- در فاز ۳: با استفاده از کد خارجی، از API TrackingMore/17track رویدادها را دریافت و با `source = 'api_aggregator'` ذخیره میکند
|
||||||
|
|
||||||
|
### وضعیتهای ممکن (Status Enum)
|
||||||
|
|
||||||
|
بر اساس شیتهای ترکینگ، این وضعیتها در سیستم IFNEX وجود دارند:
|
||||||
|
|
||||||
|
| وضعیت | توضیح | نگاشت به enum |
|
||||||
|
|-------|-------|---------------|
|
||||||
|
| Waybill created | بارنامه صادر شد | `processed` |
|
||||||
|
| Shipment picked up | بسته دریافت شد | `picked_up` |
|
||||||
|
| Processed at [Location] | در حال پردازش | `in_transit` |
|
||||||
|
| Shipment has departed | حرکت کرد | `in_transit` |
|
||||||
|
| Arrived at Sort Facility | رسید به مرکز دستهبندی | `in_transit` |
|
||||||
|
| Re-Weight | وزنمجدد | `in_transit` |
|
||||||
|
| Out For Delivery with Courier | در مسیر تحویل | `out_for_delivery` |
|
||||||
|
| Prepared for delivery | آماده تحویل | `out_for_delivery` |
|
||||||
|
| Delivery attempted | تلاش برای تحویل (ناموفق) | `failed` |
|
||||||
|
| Delivered | تحویل داده شد | `delivered` |
|
||||||
|
| Failed attempt | تلاش ناموفق | `failed` |
|
||||||
|
| Returned | برگشت خورده | `returned` |
|
||||||
|
|
||||||
|
این enum در `shipments.status` و `shipment_tracking_events.delivery_status` استفاده میشود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ نکات مهاجرت داده (Migration Notes)
|
||||||
|
|
||||||
|
### اسکریپت مهاجرت — فاز ₀
|
||||||
|
|
||||||
|
این کارها باید توسط اسکریپت `HistoricalShipmentsImport` (در `04_Laravel/app/Imports/`) انجام شود:
|
||||||
|
|
||||||
|
#### ۱. مهاجرت کشورها (از شیت COUNTRIES و Zone)
|
||||||
|
```php
|
||||||
|
// خواندن شیت COUNTRIES برای استخراج نام و ISO
|
||||||
|
// خواندن شیت Zone برای استخراج زونهای PARCEL و DOCUMENT
|
||||||
|
// درج در جدول countries با ۴ زون
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ۲. مهاجرت مرسولات تاریخی (از شیت List)
|
||||||
|
```php
|
||||||
|
// خواندن ردیف ۳ به بعد (ردیف ۱ و ۲ سرتیتر)
|
||||||
|
// برای هر ردیف:
|
||||||
|
// - استخراج iso_code از نام کشور (مثلاً "Iran (IR)" → "IR")
|
||||||
|
// - تبدیل تاریخ میلادی به timestamp
|
||||||
|
// - تبدیل نوع سرویس (DocNor → DOC_NORMAL، NON DOC → PARCEL، ...)
|
||||||
|
// - درج در جدول shipments
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ۳. مهاجرت نگاشت کدهای ترکینگ (از شیت Refrence)
|
||||||
|
```php
|
||||||
|
// برای هر ردیف:
|
||||||
|
// - lookup shipment_id با awb_no
|
||||||
|
// - تبدیل IM/EX به carrier_code enum
|
||||||
|
// - درج در جدول shipment_carrier_mappings
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ۴. مهاجرت رویدادهای ترکینگ (از شیت Sheet1 — اختیاری)
|
||||||
|
```php
|
||||||
|
// برای هر ردیف:
|
||||||
|
// - lookup shipment_id با awb_no
|
||||||
|
// - parse Date و Time
|
||||||
|
// - درج در جدول shipment_tracking_events با source = 'manual'
|
||||||
|
```
|
||||||
|
|
||||||
|
### چالشهای مهاجرت
|
||||||
|
|
||||||
|
۱. **نام کشورها با فرمتهای متفاوت:**
|
||||||
|
- `Iran (IR)`، `IRAN`، `iran` — باید استاندارد شوند
|
||||||
|
- راهحل: استخراج iso_code از پرانتز، یا fuzzy matching با جدول countries
|
||||||
|
|
||||||
|
۲. **فیلد Type متناقض:**
|
||||||
|
- مقادیر اکسل: `DocNor`، `DocEco`، `NON DOC`، `Outbound`، `Inbound`، خالی
|
||||||
|
- مقادیر DB: `DOC_NORMAL`، `DOC_ECONOMY`، `PARCEL`
|
||||||
|
- راهحل: mapping table در اسکریپت مهاجرت
|
||||||
|
|
||||||
|
۳. **فیلد Service متناقض:**
|
||||||
|
- مقادیر اکسل: `Outbound`، `Inbound`، خالی
|
||||||
|
- مقادیر DB: `import`، `export`
|
||||||
|
- راهحل: `Outbound → export`، `Inbound → import`
|
||||||
|
|
||||||
|
۴. **ردیفهای خالی زیاد:**
|
||||||
|
- در شیت List، حدود نیمی از ردیفها خالی هستند
|
||||||
|
- راهحل: `if (empty($row['awb_no'])) continue;`
|
||||||
|
|
||||||
|
۵. **تاریخها با فرمت متنوع:**
|
||||||
|
- بعضی ردیفها `2020-05-02`، بعضی `2020-05-02 00:00:00`، بعضی خالی
|
||||||
|
- راهحل: Carbon::parse() با مدیریت خطا
|
||||||
|
|
||||||
|
۶. **نام شرکتهای حمل با املای متفاوت:**
|
||||||
|
- `DHL`، `dhl`، `DHL Express`، `DHL8336801664`
|
||||||
|
- راهحل: استانداردسازی به enum
|
||||||
|
|
||||||
|
### تست مهاجرت
|
||||||
|
|
||||||
|
پس از مهاجرت، این تستها باید انجام شوند:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ۱. شمارش رکوردها
|
||||||
|
php artisan tinker
|
||||||
|
>>> Shipment::count(); # باید حدود 3950 باشد
|
||||||
|
|
||||||
|
# ۲. نمونهگیری تصادفی 50 رکورد
|
||||||
|
>>> Shipment::inRandomOrder()->take(50)->get();
|
||||||
|
# دستی با اکسل مقایسه شود
|
||||||
|
|
||||||
|
# ۳. بررسی یکتایی AWB
|
||||||
|
>>> Shipment::where('awb_no', '980100011')->count(); # باید 1 باشد
|
||||||
|
|
||||||
|
# ۴. بررسی روابط
|
||||||
|
>>> Shipment::find(1)->carrierMappings;
|
||||||
|
>>> Shipment::find(1)->trackingEvents;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 خلاصهی نگاشت شیتها به جداول دیتابیس
|
||||||
|
|
||||||
|
| شیت اکسل | جدول DB | فاز | یادداشت |
|
||||||
|
|----------|---------|-----|---------|
|
||||||
|
| `COUNTRIES` | `countries` | ۰ | برای name و iso_code |
|
||||||
|
| `Zone` | `countries` | ۰ | برای ۴ زون (منبع نهایی) |
|
||||||
|
| `List` | `shipments` | ۰ | ۳۹۵۰ رکورد تاریخی |
|
||||||
|
| `List` (۹ ردیف کالای گمرکی) | `shipment_items` | ۱ | در فاز ۱ ساخته میشود |
|
||||||
|
| `Form` | (قالب رابط کاربری) | ۱ | فرم ثبت سفارش |
|
||||||
|
| `Import Rate` | `shipping_rates` | ۱ | برای type=DOC_NORMAL/PARCEL |
|
||||||
|
| `Export Rate` | `shipping_rates` | ۱ | برای type=DOC_NORMAL/PARCEL |
|
||||||
|
| `DocNor` | `shipping_rates` | ۱ | برای type=DOC_NORMAL |
|
||||||
|
| `DocEco` | `shipping_rates` | ۱ | برای type=DOC_ECONOMY |
|
||||||
|
| `Parcel` | `shipping_rates` | ۱ | برای type=PARCEL |
|
||||||
|
| `Assumptions` | `system_settings` | ۰ | VAT، Packing، Profit Margin |
|
||||||
|
| `AWB` | (قالب PDF) | ۱ | تولید PDF با Dompdf |
|
||||||
|
| `INVOICE + label` | (قالب PDF) | ۱ | تولید PDF |
|
||||||
|
| `label` | (قالب PDF) | ۱ | تولید PDF برای چاپگر حرارتی |
|
||||||
|
| `DATES` | — | — | نادیده (از morilog/jalali استفاده میشود) |
|
||||||
|
| `Start` | — | — | نادیده (خالی) |
|
||||||
|
|
||||||
|
**از فایل ترکینگ دستی:**
|
||||||
|
|
||||||
|
| شیت اکسل | جدول DB | فاز | یادداشت |
|
||||||
|
|----------|---------|-----|---------|
|
||||||
|
| `Sheet1` | `shipment_tracking_events` | ۰ | مهاجرت رویدادهای تاریخی |
|
||||||
|
| `Refrence` | `shipment_carrier_mappings` | ۰ | مهاجرت نگاشتها |
|
||||||
|
| `Paste` | — | — | نادیده (داده خام) |
|
||||||
|
| `copy` | — | — | نادیده (تکراری با Sheet1) |
|
||||||
|
| `Delivered` | — | — | نادیده (با query قابل تولید) |
|
||||||
|
| `test` | — | — | نادیده (آزمایشی) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ ریسکها و هشدارهای دادهای
|
||||||
|
|
||||||
|
### ۱. کیفیت دادههای تاریخی
|
||||||
|
- حدود ۲۰٪ رکوردها فیلدهای کلیدی خالی دارند (مخصوصاً اطلاعات گیرنده)
|
||||||
|
- تاریخها گاهی بهصورت متن ذخیره شدهاند (نه DateTime)
|
||||||
|
- نام کشورها گاهی با غلط املایی هستند (مثلاً `Americam Samoa` بهجای `American Samoa`)
|
||||||
|
|
||||||
|
**راهکار:** اسکریپت مهاجرت باید دارای validation و reporting باشد — تعداد ردیفهای نامعتبر را گزارش کند.
|
||||||
|
|
||||||
|
### ۲. تضاد قیمتها
|
||||||
|
- شیت Import/Export Rate فقط ۲ نوع دارد (DOCUMENT/NON-DOC)
|
||||||
|
- شیتهای DocNor/DocEco/Parcel قیمتهای متفاوتی دارند (۳ نوع)
|
||||||
|
|
||||||
|
**راهکار:** در فاز ۱، با مشتری تأیید کنید کدام منبع معتبر است. فعلاً در فاز ₀، جدول `shipping_rates` را با enum ۳-حالته طراحی کنید تا آماده هر سناریو باشد.
|
||||||
|
|
||||||
|
### ۳. زونهای Import
|
||||||
|
- شیت `Zone` فقط زونهای export دارد
|
||||||
|
- زونهای import باید از شیت `COUNTRIES` استخراج شوند (اما فقط ۱ زون import دارد، نه ۲)
|
||||||
|
|
||||||
|
**راهکار:** در فاز ₁، با مشتری درباره زونهای import پارسل/داکیومنت صحبت کنید. فعلاً در فاز ₀، فیلدهای `import_zone_parcel` و `import_zone_doc` را با مقدار یکسان از `COUNTRIES` پر کنید.
|
||||||
|
|
||||||
|
### ۴. فیلدهای مالی گاهی خالی
|
||||||
|
- در شیت List، بسیاری از فیلدهای مالی (`shipping_price`، `extra_service`، ...) صفر یا خالی هستند
|
||||||
|
- ممکن است دادههای مالی واقعی در سیستم حسابداری جداگانهای باشد
|
||||||
|
|
||||||
|
**راهکار:** در مهاجرت، فیلدهای خالی را به `null` تبدیل کنید، نه به `0`. این کمک میکند تمایز بین «صفر واقعی» و «داده گمشده» حفظ شود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 جمعبندی برای نمونهی جدید
|
||||||
|
|
||||||
|
اگر نمونهی جدیدی هستی که این فایل را میخوانی، نکات کلیدی زیر را به خاطر بسپار:
|
||||||
|
|
||||||
|
۱. **فایلهای اکسل دو نوعند:** فایل اصلی (`4_5989927490271846355.xlsx`) و فایل ترکینگ دستی (`Data entry 2026-06-28.xlsx`).
|
||||||
|
|
||||||
|
۲. **شیت `Zone` منبع نهایی زونهاست** — ۴ زون مجزا (PARCEL × DOCUMENT × Export × Import).
|
||||||
|
|
||||||
|
۳. **۳ نوع سرویس وجود دارد:** DocNor، DocEco، Parcel — نه ۲ نوع.
|
||||||
|
|
||||||
|
۴. **VAT = ۹٪** و **Packing Cost پیشفرض = ۱۰۰,۰۰۰ ریال** — از شیت Assumptions.
|
||||||
|
|
||||||
|
۵. **۹ ردیف کالای گمرکی** در هر مرسوله — برای فرم ثبت سفارش (فاز ₁).
|
||||||
|
|
||||||
|
۶. **۳۹۵۰ رکورد تاریفی** در شیت List — باید در فاز ₀ مهاجرت داده شوند.
|
||||||
|
|
||||||
|
۷. **۸ شرکت حمل فعال:** DHL، FedEx، UPS، Aramex، Nagel، EMX، APSITEX، IMPEX — فقط ۴ تای اول API دارند.
|
||||||
|
|
||||||
|
۸. **هزینههای جانبی متغیر** گاهی در فیلد description شیت Refrence ذخیره شدهاند (مثلاً "100AED disposal charge").
|
||||||
|
|
||||||
|
۹. **محمولههای بالای ۳۰ کیلوگرم** مشمول نرخ ویژه (Spot Rate) هستند — محاسبه آنلاین ندارند.
|
||||||
|
|
||||||
|
۱۰. **PDFها باید انگلیسی باشند** — مطابق اکسل اصلی. اما پنل ادمین و رابط کاربری فارسی است.
|
||||||
|
|
||||||
|
برای جزئیات بیشتر درباره اسکیمای دیتابیس و فرمول قیمتگذاری، فایل `Phase0_Proposal.md` بخش ۶ و ۷ را بخوانید.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
© 2026 VernaSoft Group. Internal use only.
|
||||||
@ -1,3 +1,7 @@
|
|||||||
|
⚠️ هشدار: این سند قدیمی است و با نقشهی راه جدید (۴ فازی) تناقض دارد.برای آخرین وضعیت، فایل Phase0_Proposal.md را بخوانید.این سند فقط برای مرجع تاریخی نگه داشته شده است.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
سند معماری و نیازمندیهای پروژه IFNEX Logistics (نسخه 2.0)
|
سند معماری و نیازمندیهای پروژه IFNEX Logistics (نسخه 2.0)
|
||||||
|
|
||||||
تاریخ ایجاد: 2023-10-27 (بر اساس جلسات و تحلیل فایل های عملیاتی) نوع پروژه: سیستم ERP لجستیکی و رهگیری محموله (B2B & B2C) توسعهدهنده ارشد: [مهندس کاظم القاصی]
|
تاریخ ایجاد: 2023-10-27 (بر اساس جلسات و تحلیل فایل های عملیاتی) نوع پروژه: سیستم ERP لجستیکی و رهگیری محموله (B2B & B2C) توسعهدهنده ارشد: [مهندس کاظم القاصی]
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
⚠️ هشدار: این سند قدیمی است و با نقشهی راه جدید (۴ فازی) تناقض دارد.برای آخرین وضعیت، فایل Phase0_Proposal.md را بخوانید.این سند فقط برای مرجع تاریخی نگه داشته شده است.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
نقشه راه و چکلیست پروژه IFNEX (Task List)
|
نقشه راه و چکلیست پروژه IFNEX (Task List)
|
||||||
فاز ۱: انتقال از اکسل به دیتابیس و زیرساخت اولیه (در حال انجام)
|
فاز ۱: انتقال از اکسل به دیتابیس و زیرساخت اولیه (در حال انجام)
|
||||||
زیرساخت و دیتابیس
|
زیرساخت و دیتابیس
|
||||||
|
|||||||
322
01_Documents/STATUS.md
Normal file
322
01_Documents/STATUS.md
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
# 🚨 STATUS.md — این فایل را اول بخوانید!
|
||||||
|
|
||||||
|
> **آخرین بهروزرسانی:** August 2026
|
||||||
|
> **فاز در حال اجرا:** فاز ۰ (بنیان داده + ترکینگ دستی + مهاجرت دادههای تاریخی)
|
||||||
|
> **توسعهدهنده:** VernaSoft Group — Kazem Alghasi
|
||||||
|
> **وضعیت کلی پروژه:** در حال اجرا — بازنگری مسیر از نقشهی ۳ فازی به ۴ فازی انجام شده است
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ هشدار حیاتی — قبل از هر کاری بخوانید
|
||||||
|
|
||||||
|
این پروژه دارای **سه سند تاریخی** است که با هم تناقض دارند. فقط یکی از آنها معتبر است:
|
||||||
|
|
||||||
|
| فایل | وضعیت | اقدام |
|
||||||
|
|------|-------|-------|
|
||||||
|
| `01_Documents/Phase0_Proposal.md` | ✅ **معتبر و مرجع اصلی** | حتماً کامل بخوانید |
|
||||||
|
| `01_Documents/PRD_v2.md` | ❌ قدیمی و ناقص | فقط برای مرجع تاریخی — به اسکیمای دیتابیس آن اعتماد نکنید |
|
||||||
|
| `01_Documents/Project_Roadmap.md` | ❌ قدیمی (۳ فازی) | فقط برای مرجع تاریخی — به فازبندی آن اعتماد نکنید |
|
||||||
|
| `01_Documents/EXCEL_ANALYSIS.md` | ✅ **مرجع تحلیل اکسل** | حتماً بخوانید قبل از کار با دادههای تاریخی |
|
||||||
|
| `README.md` (ریشه) | ✅ بهروز (نسخه ۲) | برای نمای کلی بخوانید |
|
||||||
|
|
||||||
|
> 🔴 **قانون طلایی:** هرجا بین اسناد تناقض دیدی، به `Phase0_Proposal.md` اعتماد کن. اسناد قدیمی فقط برای فهم تاریخچهی تصمیمات نگه داشته شدهاند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📌 Quick Reference — نسخهها و معماری
|
||||||
|
|
||||||
|
### تکنولوژیها (قفلشده)
|
||||||
|
| مورد | نسخه/مقدار | دلیل |
|
||||||
|
|------|------------|------|
|
||||||
|
| Laravel | **11** (همهجا یکسان) | در PRD قدیمی ۱۰+ نوشته، در Roadmap قدیمی ۱۱، در README قدیمی ۱۲ — نسخه نهایی: **۱۱** |
|
||||||
|
| PHP | 8.2+ | الزام لاراول ۱۱ |
|
||||||
|
| MySQL | 8+ | برای پشتیبانی JSON columns |
|
||||||
|
| WordPress | آخرین نسخه پایدار | با Polylang برای چندزبانه |
|
||||||
|
| پنل ادمین | Laravel Filament 3.x | برای سرعت توسعه |
|
||||||
|
| Frontend | وردپرس + قالب DHL-inspired | **کپی نکنید** — فقط الهام |
|
||||||
|
|
||||||
|
### معماری کلی
|
||||||
|
```
|
||||||
|
┌─────────────────┐ REST API ┌─────────────────┐
|
||||||
|
│ WordPress │ ←─────────────────────→ │ Laravel 11 │
|
||||||
|
│ (Frontend) │ پلاگین IFNEX Bridge │ (Backend) │
|
||||||
|
│ │ │ + Filament │
|
||||||
|
└─────────────────┘ └────────┬────────┘
|
||||||
|
│
|
||||||
|
┌────────┴────────┐
|
||||||
|
│ MySQL 8 │
|
||||||
|
└─────────────────┘
|
||||||
|
│
|
||||||
|
(فاز ۳) │
|
||||||
|
┌────────┴────────┐
|
||||||
|
│ VPS پل خارج │
|
||||||
|
│ (هلند/آلمان) │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
┌────────┴────────┐
|
||||||
|
│ TrackingMore / │
|
||||||
|
│ 17track API │
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ وضعیت فعلی کار
|
||||||
|
|
||||||
|
### کارهای انجامشده (تا آخرین بهروزرسانی)
|
||||||
|
- [x] تحلیل کامل فایلهای اکسل عملیاتی شرکت
|
||||||
|
- [x] شناسایی تناقضات PRD قدیمی با واقعیت اکسل (۴ زون بهجای ۲، ۳ نوع سرویس بهجای ۲، فیلدهای غایب VAT/Packing/Warehousing)
|
||||||
|
- [x] تدوین سند `Phase0_Proposal.md` (مرجع اصلی پروژه)
|
||||||
|
- [x] بازنگری نقشهی راه از ۳ فازی به ۴ فازی
|
||||||
|
- [x] طراحی اسکیمای دیتابیس فاز ۰ (۶ جدول اصلی)
|
||||||
|
- [x] بازنویسی `README.md` با ساختار جدید
|
||||||
|
- [x] تدوین `EXCEL_ANALYSIS.md` (تحلیل کامل اکسل)
|
||||||
|
|
||||||
|
### کارهای در دست اقدام (فاز ۰)
|
||||||
|
- [ ] نصب و راهاندازی پروژهی لاراول ۱۱ در پوشه `04_Laravel`
|
||||||
|
- [ ] نصب Filament و احراز هویت ادمین
|
||||||
|
- [ ] نوشتن Migration ها برای ۶ جدول اصلی:
|
||||||
|
- [ ] `countries` (با ۴ زون مجزا)
|
||||||
|
- [ ] `shipments` (فاز ۰ — فیلدهای حداقلی)
|
||||||
|
- [ ] `shipment_carrier_mappings`
|
||||||
|
- [ ] `shipment_tracking_events`
|
||||||
|
- [ ] `system_settings`
|
||||||
|
- [ ] `users` (با نقشهای super_admin/tracking_operator/data_entry/customer)
|
||||||
|
- [ ] Seeder کشورها (۲۳۳ کشور با ۴ زون از شیت Zone اکسل)
|
||||||
|
- [ ] API ترکینگ: `GET /api/track/{awb_no}`
|
||||||
|
- [ ] پنل Filament با UX اپراتور ترکینگ (افزودن رویداد سریع)
|
||||||
|
- [ ] پلاگین وردپرس IFNEX Bridge با شورتکد `[ifnex_tracking_form]`
|
||||||
|
- [ ] اسکریپت مهاجرت ۳۹۵۰ رکورد تاریخی از شیت List اکسل
|
||||||
|
- [ ] راهاندازی وردپرس روی هاست مشتری
|
||||||
|
- [ ] طراحی لندینگ پیج DHL-inspired (بدون کپی)
|
||||||
|
- [ ] تست نهایی فاز ۰ و تحویل به مشتری
|
||||||
|
|
||||||
|
### کارهای فاز ۱ (پس از تأیید فاز ۰)
|
||||||
|
- [ ] موتور قیمتگذاری کامل (PriceCalculatorService)
|
||||||
|
- [ ] جدول `shipping_rates` با نرخهای Import/Export
|
||||||
|
- [ ] فرم ثبت سفارش آنلاین با ۹ ردیف کالای گمرکی
|
||||||
|
- [ ] تولید PDF: AWB، INVOICE، Label مطابق قالب اکسل
|
||||||
|
- [ ] ماژول ایمپورت اکسل تعرفهها
|
||||||
|
- [ ] صفحه استعلام قیمت واقعی
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚫 خط قرمزها (DO NOT) — هرگز این کارها را نکن
|
||||||
|
|
||||||
|
این قوانین بر اساس تجربه و تصمیمات تأییدشدهی مشتری تنظیم شدهاند. نقض هر کدام = بازگشت به عقب و کار مضاعف.
|
||||||
|
|
||||||
|
### 🚫 اسکیمای دیتابیس
|
||||||
|
- **NEVER** جدول `countries` را به ۲ زون برگردانی — ۴ زون مجزا (export_parcel, export_doc, import_parcel, import_doc) الزامی است. هر کشور برای پارسل و داکیومنت زونهای متفاوتی دارد (مثلاً افغانستان: پارسل=۷، داکیومنت=۵).
|
||||||
|
- **NEVER** فقط ۲ نوع سرویس (DOCUMENT/NON DOC) پیاده کن — ۳ نوع الزامی است: `DOC_NORMAL`، `DOC_ECONOMY`، `PARCEL` (مطابق شیتهای DocNor، DocEco، Parcel در اکسل).
|
||||||
|
- **NEVER** فیلد `forwarder_track_id` را بهعنوان فیلد واحد در `shipments` نگه دار — باید جدول جداگانه `shipment_carrier_mappings` ساخته شود، چون هر مرسوله ممکن است با چند شرکت حمل مرتبط باشد (مثلاً اول DHL سپس Aramex).
|
||||||
|
- **NEVER** فیلدهای مالی مهم (VAT، Domestic Pickup، Domestic Delivery، Warehousing Cost، Extra Service، Packing Cost) را حذف کن — حتی اگر در فاز ۰ استفاده نمیشوند، باید در Migration آماده باشند.
|
||||||
|
- **NEVER** فیلد `status` در `shipments` را به String تغییر دهی — Enum یکپارچهتر و امنتر است.
|
||||||
|
|
||||||
|
### 🚫 معماری
|
||||||
|
- **NEVER** ترکینگ را در وردپرس پیاده کن — همیشه در لاراول. وردپرس فقط نمایش میدهد. اگر این کار را بکنی، در فاز ۳ باید تمام دادهها را به لاراول مهاجرت دهی (دوبارهکاری).
|
||||||
|
- **NEVER** در وردپرس پردازش دادهی سفارش انجام دهی — تمام فرمها از طریق پلاگین IFNEX Bridge به لاراول ارسال میشوند.
|
||||||
|
- **NEVER** API لاراول را بدون API Key، Rate Limiting و CORS whitelist بگذاری — امنیت حیاتی است.
|
||||||
|
- **NEVER** از CORS `*` استفاده کنی — فقط دامنهی تولیدی وردپرس باید whitelist شود.
|
||||||
|
- **NEVER** تاریخها را به شمسی در دیتابیس ذخیره کنی — همیشه بهصورت `timestamp` میلادی. تبدیل به شمسی فقط در لایهی نمایش (با `morilog/jalali`).
|
||||||
|
|
||||||
|
### 🚫 طراحی و کپیرایت
|
||||||
|
- **NEVER** از رنگ، لوگو یا عناصر هویت بصری DHL کپی کنی — نقض کپیرایت. الهام از چیدمان و UX مجاز است.
|
||||||
|
- **NEVER** خروجی PDF (AWB، Invoice، Label) را به فارسی بسازی — مطابق اکسل اصلی، PDF باید انگلیسی باشد. اما پنل ادمین و رابط کاربری فرانتاند فارسی است.
|
||||||
|
|
||||||
|
### 🚫 فرآیند
|
||||||
|
- **NEVER** فایل `.env` را در Git کامیت کنی — در `.gitignore` است.
|
||||||
|
- **NEVER** `APP_DEBUG=true` را در محیط تولید بگذاری.
|
||||||
|
- **NEVER** اسکوپ فاز ۰ را بدون Change Request رسمی تغییر دهی — اگر مشتری درخواست افزودن قابلیت کرد، قیمتگذاری جداگانه لازم است.
|
||||||
|
- **NEVER** فاز ۱ را قبل از تأیید رسمی فاز ۰ توسط مشتری شروع کنی.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❓ سوالات متداول (FAQ)
|
||||||
|
|
||||||
|
### س: کدام نسخه لاراول استفاده کنم؟
|
||||||
|
**ج:** لاراول ۱۱. اگر در PRD_v2.md نوشته «Laravel 10+» یا در Roadmap نوشته «Laravel 11»، نسخه نهایی **۱۱** است.
|
||||||
|
|
||||||
|
### س: آیا PRD_v2.md هنوز معتبر است؟
|
||||||
|
**ج:** بخشهای کلی آن (معماری Headless، توضیح کسبوکار، VPS پل) معتبرند. اما بخشهای زیر قدیمی و اشتباه هستند:
|
||||||
|
- اسکیمای دیتابیس (۴.۱ تا ۴.۴) — به ۴ زون و ۳ نوع سرویس بهروز نشده
|
||||||
|
- فازبندی — باید ۴ فازی باشد نه ۳ فازی
|
||||||
|
- ادعای «فاز ۱ تکمیل شده» — نادرست، فاز ۰ هنوز در حال اجراست
|
||||||
|
- فیلدهای مالی — VAT، Warehousing Cost، Domestic Pickup/Delivery غایب
|
||||||
|
|
||||||
|
برای اسکیمای دیتابیس، فقط به بخش ۶ `Phase0_Proposal.md` اعتماد کن.
|
||||||
|
|
||||||
|
### س: چرا ترکینگ در لاراول است نه وردپرس؟
|
||||||
|
**ج:** چون در فاز ۳ قرار است API ترکینگ واقعی (TrackingMore/17track) متصل شود. اگر الان ترکینگ در وردپرس باشد، در فاز ۳ باید تمام دادهها به لاراول مهاجرت داده شوند. با ساخت آن در لاراول از ابتدا، در فاز ۳ فقط یک کلاس `TrackingSyncService` اضافه میشود و هیچ چیز دیگر تغییر نمیکند. این تصمیم در جلسه با مشتری تأیید شده است.
|
||||||
|
|
||||||
|
### س: چرا ۴ زون مجزا لازم است؟
|
||||||
|
**ج:** فایل اکسل عملیاتی نشان میدهد همان کشور برای پارسل و داکیومنت زونهای متفاوتی دارد. مثلاً:
|
||||||
|
- افغانستان: پارسل=۷، داکیومنت=۵
|
||||||
|
- آلبانی: پارسل=۳، داکیومنت=۷
|
||||||
|
- استرالیا: پارسل=۷، داکیومنت=۶
|
||||||
|
|
||||||
|
اگر فقط ۲ زون (export/import) داشته باشیم، موتور قیمتگذاری برای DOCUMENTها اشتباه محاسبه میکند.
|
||||||
|
|
||||||
|
### س: چرا ۳ نوع سرویس داریم نه ۲؟
|
||||||
|
**ج:** فایل اکسل شیتهای جداگانه دارد برای DocNor (Document Normal)، DocEco (Document Economy) و Parcel. هر کدام جدول قیمت جداگانه. پس `type` در `shipments` باید enum با سه مقدار باشد: `DOC_NORMAL`, `DOC_ECONOMY`, `PARCEL`.
|
||||||
|
|
||||||
|
### س: کدام فایل اکسل عملیاتی است؟
|
||||||
|
**ج:** دو فایل:
|
||||||
|
- **`4_5989927490271846355.xlsx`** — فایل اصلی عملیاتی شرکت با شیتهای Form, List, COUNTRIES, AWB, INVOICE + label, label, Import Rate, Export Rate, Zone, DocNor, Parcel, DocEco, Assumptions, DATES
|
||||||
|
- **`Data entry 2026-06-28.xlsx`** — فایل ترکینگ دستی روزانه با شیتهای Sheet1, Refrence, Paste, copy, Delivered, test
|
||||||
|
|
||||||
|
برای تحلیل کامل هر شیت، فایل `EXCEL_ANALYSIS.md` را بخوان.
|
||||||
|
|
||||||
|
### س: مهاجرت دادههای تاریخی چقدر مهم است؟
|
||||||
|
**ج:** بسیار مهم. ۳۹۵۰ رکورد در شیت List وجود دارد از سال ۲۰۲۰ تا الان. این دادهها باید به جدول `shipments` مهاجرت داده شوند. بدون این کار، مشتریان قدیمی نمیتوانند تاریخچه ببینند و اعتماد به سیستم جدید کاهش مییابد.
|
||||||
|
|
||||||
|
### س: آیا باید VPS پل را در فاز ۰ راهاندازی کنم؟
|
||||||
|
**ج:** خیر. VPS پل مخصوص فاز ۳ است. در فاز ۰ ترکینگ کاملاً دستی است (اپراتور در پنل Filament رویداد اضافه میکند). اما اسکیمای دیتابیس باید بهگونهای باشد که در فاز ۳ بتوان بهسادگی API را اضافه کرد (به فیلد `source` در `shipment_tracking_events` و `last_synced_at` در `shipment_carrier_mappings` دقت کن).
|
||||||
|
|
||||||
|
### س: مشتری چه انتظاری از فاز ۰ دارد؟
|
||||||
|
**ج:** مشتری در جلسه صراحتاً گفت: «اول سایت بالا بیاید و ترکینگ دستی حل شود، بقیه بعد.» یعنی:
|
||||||
|
۱. وبسایت وردپرس کامل آنلاین شود
|
||||||
|
۲. مشتری نهایی بتواند با کد AWB، تایملاین ترکینگ را ببیند
|
||||||
|
۳. اپراتور بهجای اکسل، از پنل Filament استفاده کند
|
||||||
|
|
||||||
|
این سه هدف، حداقل قابلقبول برای تحویل فاز ۰ است.
|
||||||
|
|
||||||
|
### س: اگر باگی دیدم یا مشکل پیدا کردم چه کنم؟
|
||||||
|
**ج:** اول `EXCEL_ANALYSIS.md` و بخش «ریسکها» در `Phase0_Proposal.md` را چک کن. اگر حل نشد، در گزارش کار (worklog) توضیح بده و به توسعهدهنده اصلی (Kazem) اطلاع بده.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Quick Commands — دستورات پرکاربرد
|
||||||
|
|
||||||
|
### نصب و راهاندازی لاراول
|
||||||
|
```bash
|
||||||
|
cd 04_Laravel
|
||||||
|
composer install
|
||||||
|
cp .env.example .env
|
||||||
|
php artisan key:generate
|
||||||
|
php artisan migrate
|
||||||
|
php artisan db:seed --class=CountrySeeder
|
||||||
|
php artisan serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### ایجاد Model + Migration + Resource (Filament)
|
||||||
|
```bash
|
||||||
|
php artisan make:model Shipment -m
|
||||||
|
php artisan make:filament-resource Shipment
|
||||||
|
```
|
||||||
|
|
||||||
|
### ایجاد API Controller
|
||||||
|
```bash
|
||||||
|
php artisan make:controller Api/TrackController --api
|
||||||
|
```
|
||||||
|
|
||||||
|
### اجرای تست
|
||||||
|
```bash
|
||||||
|
php artisan test
|
||||||
|
php artisan serve # سپس در مرورگر: http://localhost:8000/api/track/980103619
|
||||||
|
```
|
||||||
|
|
||||||
|
### مهاجرت دادههای تاریخی (یکبار)
|
||||||
|
```bash
|
||||||
|
php artisan ifnex:migrate-historical-data
|
||||||
|
# این دستور باید ساخته شود — اسکریپت مخصوص خواندن شیت List اکسل
|
||||||
|
```
|
||||||
|
|
||||||
|
### پشتیبانگیری از دیتابیس (هر روز)
|
||||||
|
```bash
|
||||||
|
mysqldump -u root -p ifnex > backups/ifnex_$(date +%Y%m%d).sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 ساختار پوشههای پروژه (پس از تکمیل فاز ۰)
|
||||||
|
|
||||||
|
```
|
||||||
|
ifnex/
|
||||||
|
├── 01_Documents/
|
||||||
|
│ ├── STATUS.md ⭐ این فایل — اول بخوان
|
||||||
|
│ ├── Phase0_Proposal.md ⭐ مرجع اصلی پروژه
|
||||||
|
│ ├── EXCEL_ANALYSIS.md ⭐ تحلیل فایلهای اکسل
|
||||||
|
│ ├── PRD_v2.md (قدیمی — مرجع تاریخی)
|
||||||
|
│ ├── Project_Roadmap.md (قدیمی — مرجع تاریخی)
|
||||||
|
│ └── AI_AGENT_GUIDE.md (راهنمای مخصوص AI Agents — اختیاری)
|
||||||
|
│
|
||||||
|
├── 02_Design/
|
||||||
|
│ └── Assets/ (لوگوها، آیکونها، فایلهای فیگما)
|
||||||
|
│
|
||||||
|
├── 03_WordPress/
|
||||||
|
│ └── wp-content/plugins/
|
||||||
|
│ └── ifnex-bridge/ (پلاگین اختصاصی)
|
||||||
|
│ ├── ifnex-bridge.php
|
||||||
|
│ ├── includes/
|
||||||
|
│ │ ├── api-client.php
|
||||||
|
│ │ ├── shortcodes.php
|
||||||
|
│ │ └── tracking-form.php
|
||||||
|
│ └── assets/
|
||||||
|
│ ├── css/
|
||||||
|
│ └── js/
|
||||||
|
│
|
||||||
|
├── 04_Laravel/
|
||||||
|
│ ├── app/
|
||||||
|
│ │ ├── Models/
|
||||||
|
│ │ │ ├── Country.php
|
||||||
|
│ │ │ ├── Shipment.php
|
||||||
|
│ │ │ ├── ShipmentCarrierMapping.php
|
||||||
|
│ │ │ ├── ShipmentTrackingEvent.php
|
||||||
|
│ │ │ ├── SystemSetting.php
|
||||||
|
│ │ │ └── User.php
|
||||||
|
│ │ ├── Services/
|
||||||
|
│ │ │ ├── TrackingService.php (فاز ۰)
|
||||||
|
│ │ │ ├── PriceCalculatorService.php (فاز ۱)
|
||||||
|
│ │ │ └── TrackingSyncService.php (فاز ۳)
|
||||||
|
│ │ ├── Http/Controllers/Api/
|
||||||
|
│ │ │ └── TrackController.php
|
||||||
|
│ │ ├── Imports/
|
||||||
|
│ │ │ ├── ShippingRatesImport.php (فاز ۱)
|
||||||
|
│ │ │ └── HistoricalShipmentsImport.php (فاز ۰)
|
||||||
|
│ │ └── Filament/
|
||||||
|
│ │ └── Resources/
|
||||||
|
│ │ ├── CountryResource.php
|
||||||
|
│ │ ├── ShipmentResource.php
|
||||||
|
│ │ └── Pages/
|
||||||
|
│ │ └── AddTrackingEvent.php (UX اختصاصی اپراتور)
|
||||||
|
│ ├── database/
|
||||||
|
│ │ ├── migrations/
|
||||||
|
│ │ └── seeders/
|
||||||
|
│ │ └── CountrySeeder.php
|
||||||
|
│ ├── routes/api.php
|
||||||
|
│ ├── config/
|
||||||
|
│ │ └── ifnex.php (تنظیمات اختصاصی)
|
||||||
|
│ └── .env.example
|
||||||
|
│
|
||||||
|
├── README.md (نسخه بهروز ۲)
|
||||||
|
└── .gitignore
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 گام بعدی برای ادامهی کار
|
||||||
|
|
||||||
|
اگر نمونهی جدیدی از AI Agent هستی که میخواهی کار را ادامه دهی، این مراحل را به ترتیب برو:
|
||||||
|
|
||||||
|
۱. **این فایل (`STATUS.md`)** را کامل بخوان — حالا خواندی ✅
|
||||||
|
۲. **`EXCEL_ANALYSIS.md`** را کامل بخوان — برای فهم دادههای تاریخی ضروری است
|
||||||
|
۳. **`Phase0_Proposal.md`** را کامل بخوان — مرجع اصلی پروژه
|
||||||
|
۴. **`README.md`** ریشه را بخوان — برای نمای کلی
|
||||||
|
۵. کد موجود در `04_Laravel` را بررسی کن — ببین چه چیزی نوشته شده
|
||||||
|
۶. با کاربر (Kazem) هماهنگ کن — بپرس کدام کار را باید ادامه دهی
|
||||||
|
|
||||||
|
**سپس کار را ادامه بده. موفق باشی! 🚀**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 تماس
|
||||||
|
|
||||||
|
- **توسعهدهنده اصلی:** Kazem Alghasi (VernaSoft Group)
|
||||||
|
- **مشتری:** شرکت IFNEX اصفهان
|
||||||
|
- **مخزن:** https://www.git.vernahost.ir/gitmodir110/ifnex
|
||||||
|
|
||||||
|
اگر سوالی داشتی که در این فایل یا `EXCEL_ANALYSIS.md` یا `Phase0_Proposal.md` پاسخ آن نبود، از کاربر بپرس — حدس نزن.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
© 2026 VernaSoft Group. Internal use only.
|
||||||
Loading…
Reference in New Issue
Block a user