# GuaranteeApp — ربات تلگرام

> پیش‌نیاز: `00-Overview`، `02-Backend-API`. ربات مسئول فعال‌سازی گارانتی نیست (آن در وب است)؛ نقشش: گزارش، موجودی، استعلام، اعلان فوری.

---

## ۱. قابلیت‌ها

| قابلیت | نوع | توضیح |
|---|---|---|
| گزارش روزانه | خودکار (Cron ۲۰:۰۰) | تولید/بسته‌بندی/خروج |
| `/inventory` | دستی | موجودی فعلی هر مدل |
| `/report` | دستی | همان گزارش روزانه، آنی |
| عکس QR | دستی | تاریخچهٔ کامل یک سریال |
| متن سریال | دستی | همان تاریخچه |
| اعلان Orphan | خودکار (لحظه‌ای) | سریال ناشناخته در پنل |
| اعلان گارانتی بدون سابقهٔ انبار | خودکار (لحظه‌ای) | فعال‌سازی بدون رویداد انباری |
| `/start`، `/help` | دستی | راهنما |

اعلان‌های خودکار از **PHP API** در لحظهٔ رویداد (با `TelegramNotifier`) ارسال می‌شوند، نه از داخل webhook.

---

## ۲. معماری

### ۲.۱ Webhook (نه Polling)
هاست اشتراکی پروسهٔ دائمی ندارد. `telegram/webhook.php` با `setWebhook` ثبت می‌شود؛ تلگرام هر پیام را POST می‌کند. اسکریپت **همیشه HTTP 200** برمی‌گرداند تا Update تکرار نشود.

### ۲.۲ امنیت webhook
1. **secret_token:** هنگام `setWebhook` تعریف و در هر درخواست از هدر `X-Telegram-Bot-Api-Secret-Token` سنجیده می‌شود. مقدار قطعی از توکن ربات مشتق می‌شود (`substr(hash('sha256', TOKEN), 0, 48)` — یک تابع مشترک در `TgApi` برای setup و webhook). secret نامعتبر ← بی‌پاسخ + لاگ.
2. **مجاز بودن chat_id:** فقط `chat_id`های `telegram_admins` با `active=1`. کاربر ناشناس: «⛔️ شما در فهرست ادمین‌ها ثبت نشده‌اید» + **نمایش chat_id خودش** (برای ثبت آسان ادمین جدید).
3. بیرون‌کردن موقت یک ادمین = `active=0`.

### ۲.۳ Cron گزارش روزانه
`telegram/daily_report.php`، دو حالت: **CLI** (`php .../daily_report.php`، ترجیحی) یا **URL** با `?key=TEST_KEY` (`wget -q -O /dev/null "..."`). ساعت کرون بر اساس ساعت سرور است (اگر UTC بود، اختلاف تهران لحاظ شود)؛ اسکریپت خودش تاریخ را با `Asia/Tehran` می‌سازد. ارسال به همهٔ ادمین‌های فعال با `TelegramNotifier::sendToAllAdmins`.

---

## ۳. فایل‌ها

```
telegram/
├── webhook.php          ← secret → مجاز بودن chat_id → مسیریابی دستور/عکس/متن
├── daily_report.php     ← کرون ۲۰:۰۰ (CLI یا URL)
├── setup_webhook.php    ← set / info / delete (با TEST_KEY؛ پس از راه‌اندازی حذف شود)
└── lib/
    ├── TgApi.php        ← sendMessage/getFile/دانلود + faDigits + webhookSecret
    └── ReportService.php← متن گزارش/موجودی/تاریخچه + تبدیل میلادی→جلالی (الگوریتم استاندارد، بدون وابستگی)
```
از زیرساخت وب استفاده می‌کند: `config.php`، `lib/db.php`، `lib/Logger.php`، `lib/TelegramNotifier.php`، `lib/ProductService.php`، `lib/InventoryService.php`. جدول جدیدی لازم نیست.

---

## ۴. دستورها و پاسخ‌ها

| ورودی | خروجی |
|---|---|
| `/start`، `/help` | راهنمای دستورها |
| `/inventory` | `📦 موجودی فعلی انبار` + یک خط به‌ازای هر مدل با موجودی مثبت؛ خالی: «انبار خالی است…» |
| `/report` | گزارش امروز (قالب §۴.۱) |
| عکس QR | خواندن QR ← استخراج سریال ← تاریخچه (§۴.۳)؛ ناموفق: «سریال را متنی بفرستید» |
| متنِ فقط سریال | همان تاریخچه |
| متن نامشخص | «دستور نامشخص است. /help را بزنید.» |

**تشخیص «متنِ فقط سریال»:** `^[A-Za-z0-9][A-Za-z0-9._-]*-\d{6}-\d{4}$`.

### ۴.۱ قالب گزارش روزانه
```
📊 گزارش روزانه — ۱۴۰۵/۰۷/۰۳ (۲۶۰۹۲۵)

🏭 تولید شده امروز: ۱۲۰ عدد
   • دوربین IP 4mm WiFi: ۵۰
   • دوربین AHD 2.8mm: ۷۰

📦 وارد انبار شده (بسته‌بندی): ۸۵ عدد
📤 خارج شده از انبار: ۴۰ عدد
```
هدر: تاریخ جلالی + (YYMMDD میلادی). همهٔ ارقام فارسی. فعلاً فقط اعداد خام (بدون مقایسه با دیروز).

### ۴.۲ موجودی
حالت پیش‌فرض **A:** بسته‌بندی − خروج به‌ازای مدل (`GW_INVENTORY_MODE` در config؛ `'B'` = تولید − خروج).
```
📦 موجودی فعلی انبار

• دوربین IP 4mm WiFi: ۲۳ عدد
• دوربین AHD 2.8mm: ۱۴ عدد
```

### ۴.۳ قالب تاریخچهٔ سریال
```
🔍 IP0756z-1223-260923-0001

📷 مدل: دوربین IP 4mm WiFi
📅 تاریخ تولید: ۲۶۰۹۲۳
📦 تاریخ ورود به انبار: ۲۶۰۹۲۴ ساعت ۱۴:۱۰
📤 تاریخ خروج از انبار: — (هنوز خارج نشده)
🛡 گارانتی: غیرفعال
```
اگر ورود به انبار ثبت نشده، هر دو خط انبار «—» نمایش داده می‌شوند.

### ۴.۴ خواندن QR از عکس
- دانلود فایل (`getFile`) ← ارسال به سرویس `api.qrserver.com/v1/read-qr-code/` ← متن QR یک URL است ← پارامتر `serial` استخراج می‌شود (اگر متن خام سریال بود همان).
- ریسک: اتصال خروجی هاست به این سرویس. اگر بسته بود: «سریال را متنی بفرستید»؛ جایگزین: کتابخانهٔ خالص PHP (پورت ZXing).

---

## ۵. اعلان‌های فوری (قالب‌ها)

### ۵.۱ Orphan (از `api/scan.php`، فقط اولین اسکن هر سریال)
```
⚠️ اسکن محصول ناشناخته

سریال: IP0756z-1223-260923-0001
نوع عملیات: بسته‌بندی
زمان: ۲۶۰۹۲۵ ساعت ۱۱:۲۰

این سریال هنوز در دیتابیس سینک نشده (احتمالاً اپ دسکتاپ آپدیت نشده).
رویداد ثبت شد و بعد از سینک بعدی خودکار به محصول متصل می‌شود.
```

### ۵.۲ گارانتی بدون سابقهٔ انبار (از `api/warranty/activate.php`)
```
🚨 فعال‌سازی گارانتی بدون سابقهٔ انبار

سریال: IP0756z-1223-260923-0001
مدل: دوربین IP 4mm WiFi
تاریخ تولید: ۲۶۰۹۲۳
زمان فعال‌سازی گارانتی: ۲۶۰۹۲۵ ساعت ۱۸:۴۵

⚠️ این محصول نه رویداد بسته‌بندی و نه خروج از انبار ثبت‌شده دارد،
اما گارانتی‌اش توسط مشتری فعال شده است.
```

---

## ۶. تنظیم و تست
مراحل استقرار در `07-Deployment §۶`. تست‌های ربات در `08`: `/start`، کاربر ثبت‌نشده، `/inventory`، `/report`، عکس QR، متن سریال، اجرای دستی URL کرون، رویدادهای webhook در لاگ.
