# GuaranteeApp — نمای کلی سیستم (نسخهٔ ۲.۱)

> این مجموعه، تنها مرجع معتبر برای طراحی و ساخت سیستم از صفر است. هیچ سند قدیمی‌ای لازم نیست.
> **ترتیب خواندن:** این فایل ← `01-Database` ← `02-Backend-API` ← سپس هر بخش دلخواه.

| فایل | محتوا |
|---|---|
| `00-Overview` | تصمیم‌ها، معماری، واژه‌نامه، جریان کامل (همین فایل) |
| `01-Database` | اسکیمای MySQL و SQLite، قوانین داده |
| `02-Backend-API` | ساختار PHP، همهٔ Endpointها، امنیت، لاگ |
| `03-Desktop-App` | اپ WPF: مدل‌ها، Part Number، سریال، سینک، بازیابی |
| `04-BarTender-Printing` | چاپ لیبل با CSV + BarTender، پروفایل‌ها، پشتیبان قالب، آزمایش فاز ۰ |
| `05-WebPanel` | پنل بسته‌بندی/انبار + صفحهٔ عمومی گارانتی |
| `06-TelegramBot` | ربات: گزارش، موجودی، اسکن عکس، اعلان |
| `07-Deployment` | استقرار روی cPanel + پیش‌نیاز سیستم چاپ |
| `08-BuildPlan-Acceptance` | فازبندی، تست پذیرش، سؤال‌های باز، ریسک‌ها |

---

## ۱. هدف سیستم

یک کارگاه تولید دوربین/دستگاه، برای هر واحد:

1. **سریال یکتا** می‌سازد و **دو لیبل** چاپ می‌کند (روی دستگاه و روی جعبه).
2. **مسیر محصول** را ردیابی می‌کند: تولید ← بسته‌بندی ← خروج از انبار ← فعال‌سازی گارانتی توسط مشتری.
3. به ادمین **گزارش و اعلان** تلگرام می‌دهد.
4. اگر کامپیوتر تولید خراب شود، **همه‌چیز را از سرور بازیابی** می‌کند.

---

## ۲. تصمیم‌های نهایی

| # | موضوع | تصمیم |
|---|---|---|
| ۱ | زیرساخت | هاست اشتراکی cPanel: PHP (بدون فریم‌ورک) + MySQL. **Supabase نیست.** |
| ۲ | اپ تولید | WPF (`net10.0-windows`)، SQLite محلی، Offline-first، سینک به PHP API |
| ۳ | تعداد سیستم | **فقط یک سیستم تولید/چاپ.** چند سیستم هم‌زمان خارج از دامنه است |
| ۴ | اپراتور | **مفهوم اپراتور وجود ندارد** (نه نام، نه کد، نه ستون دیتابیس) |
| ۵ | روش چاپ | **CSV ثابت + قالب `.btw` متصل به آن** (BarTender 11.8 Enterprise). بدون SDK/Bridge/Engine؛ اپ طراح لیبل ندارد |
| ۶ | پرینتر | BIXOLON SLP-TX403 |
| ۷ | قالب‌ها | **پروفایل‌های نام‌دار (نام = برند/فروشگاه)** برای هر نوع لیبل، سراسری برای همهٔ مدل‌ها |
| ۸ | نمایش قبل از چاپ | BarTender همیشه باز می‌شود، یک لیبل دیده می‌شود، چاپ با Ctrl+P (*Records = All*) |
| ۹ | تأیید چاپ | ندارد؛ ثبت = «ارسال شد به BarTender» |
| ۱۰ | CSV | یک فایل مشترک برای هر دو نوع لیبل |
| ۱۱ | تاریخ روی لیبل | ندارد (تاریخ تولید داخل سریال است) |
| ۱۲ | گارانتی | روی **مدل محصول** اجباری (ماه). چاپ متنش روی هر لیبل به انتخاب اپراتور. وب پایان گارانتی را نشان نمی‌دهد |
| ۱۳ | بازیابی | سیستم جدید به سرور وصل می‌شود و مدل‌ها، دسته‌ها، سریال‌ها، وضعیت چاپ و قالب‌ها را برمی‌گرداند |
| ۱۴ | پشتیبان قالب | خودکار، در MySQL (BLOB) |
| ۱۵ | فعال‌سازی گارانتی | صفحهٔ وب عمومی (QR مستقیم به وب)، نه تلگرام |
| ۱۶ | ربات تلگرام | Webhook (نه Polling)؛ فقط گزارش/موجودی/استعلام/اعلان |
| ۱۷ | کد Part Number | طرح دو‌رقمی: حداکثر ۹ خانواده × ۹ مقدار |
| ۱۸ | موجودی انبار | بسته‌بندی‌شده − خارج‌شده، به‌ازای مدل |
| ۱۹ | منطقهٔ زمانی | `Asia/Tehran` در همه‌جا |

---

## ۳. معماری

```
                       MySQL (cPanel) ← منبع حقیقت
                            ▲
                     PHP API (تنها راه دسترسی)
      ┌──────────────┬──────┴───────┬──────────────────┐
      ▼              ▼              ▼                  ▼
 اپ دسکتاپ      پنل وب عملیات   صفحهٔ عمومی      ربات تلگرام
 (WPF+SQLite)   (بسته‌بندی/خروج) گارانتی           (webhook + cron)
      │
      ▼  «چاپ لیبل ۱/۲»
 LabelPrintCoordinator
      │ ۱) انتخاب پروفایل  ۲) بک‌آپ قالب  ۳) نوشتن اتمیک CSV  ۴) باز کردن .btw
      ▼
 C:\ProgramData\GuaranteeApp\LabelData\current.csv
      ▼
 BarTender Designer 11.8 → یک لیبل نمایش → Ctrl+P → BIXOLON SLP-TX403
```

- اپ دسکتاپ با BarTender ارتباط برنامه‌نویسی ندارد و نمی‌داند چاپ انجام شد یا نه.
- MySQL مستقیماً در دسترس هیچ کلاینتی نیست (افشای Credential)؛ منطق کسب‌وکار (تکراری، Orphan، قفل مدل) سمت سرور است.

---

## ۴. واژه‌نامه

| اصطلاح | تعریف |
|---|---|
| **Part Number (کد محصول ثابت)** | کد ثابت هر مدل: `base_code` + کد خانواده‌های انتخابی. برای همهٔ واحدهای مدل یکسان. مثال `IP0756z-1223` |
| **سریال** | کد یکتای هر واحد: `{PartNumber}-{YYMMDD}-{####}`. مثال `IP0756z-1223-260923-0001` |
| **خانوادهٔ آپشن** | دسته‌ای از آپشن‌ها (لنز، نوع اتصال) با شمارهٔ ۱ تا ۹ |
| **کد آپشن** | دو رقم: شمارهٔ خانواده + اندیس مقدار. مثال لنز 4mm = `12` |
| **دستهٔ تولید** | سریال‌هایی که در یک عملیات «تولید» ساخته شدند. کد `YYMMDD-B{n}` |
| **لیبل ۱** | روی دستگاه: بارکد (Part Number یا سریال) + سریال |
| **لیبل ۲** | روی جعبه: QR لینک گارانتی + سریال + دسته |
| **پروفایل لیبل** | یک فایل `.btw` با نام برند، برای یک نوع لیبل |
| **Orphan** | رویداد انباری که سریالش هنوز در MySQL نیست (سینک نشده)؛ بعداً خودکار وصل می‌شود |
| **بازیابی** | بازگرداندن همهٔ دادهٔ سیستم تولید از سرور روی کامپیوتر جدید |

---

## ۵. جریان کامل (سر تا ته)

1. اپراتور مدل و تعداد را انتخاب و «تولید» می‌زند ← یک دسته + N سریال در SQLite (`Synced=false`)؛ سینک خودکار best-effort انجام می‌شود.
2. «چاپ لیبل ۱» ← انتخاب پروفایل برند ← CSV نوشته و BarTender باز می‌شود ← Ctrl+P. زمان ارسال ثبت می‌شود.
3. هر زمان بعد (حتی روزها بعد) از تاریخچه «چاپ لیبل ۲» برای دسته یا سریال‌های انتخابی.
4. **بسته‌بندی:** کارمند پنل وب را روی گوشی باز و QR جعبه را اسکن می‌کند:
   - سریال در MySQL و اولین‌بار ← «ثبت شد».
   - تکراری ← «تکراریه».
   - سریال در MySQL نیست ← «در دیتابیس نیست»؛ رویداد Orphan ذخیره و هشدار تلگرام؛ بعد از سینک بعدی خودکار وصل می‌شود.
5. **خروج از انبار:** همان پنل با حالت «خروج از انبار».
6. **مشتری:** QR را با دوربین گوشی اسکن می‌کند ← صفحهٔ وب عمومی ← «گارانتی فعال شد». اگر محصول هیچ رویداد انباری نداشت، هشدار تلگرام به ادمین می‌رود (مشتری چیزی نمی‌بیند).
7. **ربات:** هر شب ۲۰:۰۰ گزارش؛ `/inventory`، `/report`، استعلام با عکس QR یا متن سریال.
8. **خرابی سیستم:** نصب روی کامپیوتر جدید ← «بازیابی از سرور».

---

## ۶. خارج از دامنه و ریسک‌های شناخته‌شده

- **چند سیستم هم‌زمان:** اگر لازم شد، شمارندهٔ سریال باید برای هر سیستم فضای جدا بگیرد (مثلاً حرف سیستم در سریال)؛ طراحی جدا لازم است.
- **سریال‌های چاپ‌شده ولی سینک‌نشده** با خرابی سیستم از بین می‌روند و سیستم جدید ممکن است همان شماره‌ها را دوباره بسازد. کاهش ریسک: سینک خودکار بعد از هر تولید + نشانگر «N رکورد سینک‌نشده». دستورالعمل اپراتور: بعد از بازیابی، قبل از تولید جدید، شمارندهٔ همان روز را با آخرین لیبل فیزیکی تطبیق بده.
- **حذف محلی** مدل/آپشن (فقط وقتی قفل نیست) به سرور منتقل نمی‌شود؛ بی‌ضرر است ولی در بازیابی برمی‌گردد.
- اپ نمی‌داند چاپ واقعاً انجام شد؛ راه‌حل = «چاپ مجدد» از تاریخچه.
