اضافه شدن فایل های توضیحی
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)
|
||||
|
||||
تاریخ ایجاد: 2023-10-27 (بر اساس جلسات و تحلیل فایل های عملیاتی) نوع پروژه: سیستم ERP لجستیکی و رهگیری محموله (B2B & B2C) توسعهدهنده ارشد: [مهندس کاظم القاصی]
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
⚠️ هشدار: این سند قدیمی است و با نقشهی راه جدید (۴ فازی) تناقض دارد.برای آخرین وضعیت، فایل Phase0_Proposal.md را بخوانید.این سند فقط برای مرجع تاریخی نگه داشته شده است.
|
||||
|
||||
|
||||
|
||||
نقشه راه و چکلیست پروژه 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