# GuaranteeApp — چاپ لیبل با BarTender (CSV + قالب `.btw`)

> پیش‌نیاز: `03-Desktop-App`. اپ هیچ طراح لیبل و SDK ندارد؛ فقط یک CSV می‌نویسد و قالب BarTender را باز می‌کند.

---

## ۱. تصمیم‌ها
BarTender **11.8 Enterprise (۶۴بیتی)**، پرینتر **BIXOLON SLP-TX403**، یک CSV مشترک برای هر دو لیبل، پروفایل‌های نام‌دار (برند)، بدون تأیید چاپ، بدون تاریخ روی لیبل، لیبل چندردیفه مسئولیت BarTender، فقط یک سیستم چاپ.

---

## ۲. چه چیزی کجا ذخیره می‌شود

| اطلاعات | محل |
|---|---|
| مدت و متن گارانتی | دیتابیس، روی مدل (`ProductModels`) |
| چیدمان، فونت، لوگو، اندازهٔ لیبل | داخل `.btw` |
| اتصال هر آبجکت به ستون CSV | داخل `.btw` |
| **مسیر `current.csv`** | داخل `.btw` (مسیر باید ثابت باشد) |
| پرینتر و تنظیم کاغذ | داخل `.btw` (اپ پرینتر را عوض نمی‌کند) |
| *Records = All* پیش‌فرض دیالوگ چاپ | احتمالاً داخل `.btw` ← در فاز ۰ تأیید شود |
| کدام `.btw` متعلق به کدام برند | SQLite (`LabelProfiles`) + پشتیبان در MySQL |
| آخرین پروفایل هر (مدل، نوع لیبل) | SQLite (`ModelLabelPreferences`) |
| تیک «چاپ گارانتی» | پیش‌فرض روی پروفایل، قابل تغییر هر بار چاپ |

---

## ۳. قرارداد ستون‌های `current.csv`

`C:\ProgramData\GuaranteeApp\LabelData\current.csv` — **UTF-8 با BOM**، جداکنندهٔ کاما، سطر اول = نام ستون‌ها. اپ **همیشه همهٔ ستون‌ها** را می‌نویسد.

| ستون | محتوا | مثال |
|---|---|---|
| `SerialNo` | سریال | `IP0756z-1223-261010-0001` |
| `PartNo` | Part Number | `IP0756z-1223` |
| `QR` | `WarrantyUrlTemplate` با سریال URL-encode | `https://.../warranty.php?serial=IP0756z-1223-261010-0001` |
| `Model` | نام مدل | `IP Camera 4mm WiFi` |
| `Batch` | کد دسته | `261010-B1` |
| `Warranty` | متن گارانتی؛ **خالی** اگر اپراتور چاپ را خاموش کند | `1 Year Warranty` |

قوانین:
1. بارکد و QR فقط از `SerialNo`/`PartNo`/`QR` تغذیه شوند؛ متن چاپی سریال هم `SerialNo` است. (لیبل ۱ معمولاً بارکد `PartNo` یا `SerialNo` + متن سریال؛ لیبل ۲ معمولاً QR + سریال + دسته — انتخاب نهایی با طراحی قالب.)
2. هر ردیف = یک سریال یکتا، مرتب صعودی. تعداد لیبل در ردیف و چندردیفه‌بودن با BarTender.
3. Escape کامل CSV (کاما، کوتیشن، خط جدید)، حذف کاراکتر کنترلی، سقف طول هر فیلد.
4. **نوشتن اتمیک:** `current.csv.tmp` ← `File.Move(overwrite)`. `IOException` (قفل) ← «پنجرهٔ BarTender را ببندید».
5. افزودن ستون جدید در آینده قالب‌های قدیمی را خراب نمی‌کند (`ColumnContractVersion`).
6. Unit test: کاما/کوتیشن/فارسی/۵۰۰ ردیف.

---

## ۴. پروفایل‌ها (برندها)

- **پروفایل** = یک فایل `.btw` با نام برند برای یک نوع لیبل. مثال: لیبل ۱: `BrandA`، `BrandB`، `OwnBrand`؛ لیبل ۲: همین‌ها.
- پروفایل‌ها **سراسری‌اند** (مستقل از مدل)، چون داده از CSV می‌آید. اگر مدلی چیدمان ویژه خواست، پروفایل جدا (مثلاً `BrandA-ModelX`).
- برای هر (مدل، نوع لیبل) آخرین پروفایل مصرف‌شده پیش‌انتخاب می‌شود.
- نام فایل: `L{نوع}_{slug}.btw` (مثل `L2_BrandA.btw`)؛ فقط کاراکتر امن. نام پروفایل در هر نوع لیبل یکتاست؛ نام نمایشی فارسی/انگلیسی در دیتابیس.
- `ContentHash` = SHA-256 فایل.

---

## ۵. آماده‌سازی هر قالب (یک‌بار برای هر فایل، داخل BarTender)

قالب‌های موجود کارفرما معمولاً Embedded هستند (`Name = <none>`، Serialization فعال). برای هر فایل:

1. از **کپی داخل پوشهٔ قالب‌های اپ** باز کن (فایل اصلی دست نخورد).
2. **Database Connection Setup → Text File** → مسیر `current.csv`؛ UTF-8، کاما، سطر اول = نام فیلد.
3. هر آبجکت متغیر را از *Embedded Data* به *Database Field* و ستون متناظر ببر؛ **Serialization و Pad را بردار.**
   بارکد ← `SerialNo` یا `PartNo`؛ QR ← `QR`؛ متن سریال ← `SerialNo`؛ گارانتی ← `Warranty`؛ مدل ← `Model`؛ دسته ← `Batch`.
4. پرینتر را روی **BIXOLON SLP-TX403** بگذار و اندازهٔ کاغذ/گپ را درست کن.
5. آبجکت‌های ثابت (لوگو، آدرس، متن ثابت) دست نخورند.
6. **Ctrl+S روی همان فایل.** *Save As* فقط برای ساخت پروفایل جدید.

نمایش و چاپ: Designer فقط **رکورد اول** را نشان می‌دهد. **Ctrl+P** ← *Records = All*، *Identical copies = 1*، *Serialized = 1*.

---

## ۶. گردش کار چاپ

1. اپراتور «چاپ لیبل ۱/۲» را از صفحهٔ تولید یا تاریخچه می‌زند (دسته یا سریال‌های انتخاب‌شده؛ چاپ مجدد همین مسیر بدون سریال جدید).
2. اگر هیچ پروفایلی برای آن نوع لیبل نیست ← **دیالوگ «تنظیم قالب»** (انتخاب `.btw` + نام برند؛ اپ فایل را در پوشهٔ قالب‌ها کپی می‌کند).
3. **دیالوگ چاپ:** انتخاب پروفایل (پیش‌انتخاب = آخرین استفادهٔ این مدل)، چک‌باکس «چاپ متن گارانتی روی لیبل»، خلاصه (تعداد، اولین و آخرین سریال)، دکمهٔ «پروفایل جدید».
4. بررسی‌ها: BarTender از قبل باز است؟ ← «پنجرهٔ قبلی را ببندید»؛ `current.csv` قفل؟ ← همان پیام؛ Job دیگری فعال؟ ← Mutex سراسری (`Global\GuaranteeApp.LabelPrint`).
5. بک‌آپ محلی قالب ← نوشتن اتمیک CSV ← باز کردن `.btw` (روش دقیق بعد از فاز ۰).
6. اپراتور یک لیبل را می‌بیند، در صورت نیاز ظاهر را اصلاح و Ctrl+S می‌زند، سپس Ctrl+P.
7. **ثبت بدون تأیید:** لحظهٔ باز شدن BarTender، `Label1PrintedAt`/`Label2PrintedAt` و ردیف‌های `PrintLogs` (به‌ازای هر سریال، با `ProfileName`) ثبت و محصولات `Synced=false` می‌شوند. دیالوگ می‌گوید: «اگر چاپ درست نبود از تاریخچه دوباره چاپ کنید».
8. آپلود پشتیبان قالب در پس‌زمینه (§۸).

### مدیریت پروسه و خطا
- اپ پروسهٔ BarTender را **kill نمی‌کند**؛ `current.csv.tmp` باقی‌مانده هنگام شروع اپ پاک می‌شود.
- لاگ هر Job: زمان، مدل، پروفایل، دسته، تعداد.
- پیام‌های فارسی: BarTender نصب نیست، قالب پیدا نشد، CSV قفل است، پروسهٔ قبلی باز است، پوشه قابل‌نوشتن نیست.
- فایل قالب گم‌شده (رکورد هست، فایل نیست) ← دیالوگ تنظیم قالب (انتخاب مجدد یا دریافت از پشتیبان سرور).

---

## ۷. گارانتی روی لیبل
مدت گارانتی روی مدل است و همیشه وجود دارد؛ چاپ آن به‌صورت متن، با چک‌باکس دیالوگ: تیک = ستون `Warranty` با `WarrantyLabelText`؛ بدون تیک = خالی. پیش‌فرض از `LabelProfiles.PrintWarranty` (برخی برندها گارانتی را آیکون یا متن دیگری دارند) و آخرین انتخاب ذخیره می‌شود. دیتابیس مدل هیچ‌وقت تغییر نمی‌کند.

---

## ۸. پشتیبان قالب‌ها

قالب‌های تبدیل‌شده تنها دادهٔ غیرقابل‌بازیابی‌اند.

**محلی (`TemplateBackupService`):** قبل از هر باز شدن، `Templates\_Backups\<فایل>\yyyy-MM-dd_HHmm.btw`، ۱۰ نسخهٔ آخر، **فقط اگر هش با آخرین بک‌آپ فرق کند**؛ دکمهٔ «بازگردانی نسخهٔ قبلی».

**سرور:** `POST api/sync/templates` (`02 §۵.۴`)، best-effort و بی‌صدا، فقط وقتی `ContentHash ≠ LastBackupHash`، در این زمان‌ها: شروع اپ، قبل از هر Job چاپ، دکمهٔ «پشتیبان‌گیری قالب‌ها». سقف ۴ مگابایت.

---

## ۹. اجزای کد

| جزء | وظیفه |
|---|---|
| `LabelProfileService` | CRUD پروفایل، پیش‌انتخاب، slug، هش |
| `LabelCsvWriter` | تولید CSV اتمیک + escape + اعتبارسنجی |
| `BarTenderLauncher` | یافتن BarTender (فقط نصب‌بودن، بدون بررسی لایسنس)، باز کردن فایل، تشخیص پنجرهٔ باز، Mutex |
| `LabelPrintCoordinator` | هماهنگی مراحل §۶ |
| `TemplateBackupService` | بک‌آپ محلی + آپلود |
| `LabelTemplateSetupDialog` / `LabelPrintDialog` | UI |

---

## ۱۰. فاز ۰ — آزمایش BarTender و پرینتر (پیش از ساخت چاپ در اپ)

با Enterprise 11.8، BIXOLON SLP-TX403 و یک قالب واقعی:
1. اتصال قالب به `current.csv` (Text File، UTF-8، کاما).
2. ۱۵ ردیف: Designer یک لیبل نشان می‌دهد و Ctrl+P با *Records = All* ۱۵ لیبل با ۱۵ سریال متفاوت چاپ می‌کند.
3. متن انگلیسی و (اگر هست) فارسی (نام مدل) درست دیده می‌شود.
4. QR و بارکد دقیقاً متن ستون را می‌گیرند؛ **۳ نمونهٔ چاپ‌شده روی کاغذ واقعی** با اسکنر/گوشی خوانده شود (کیفیت QR کوچک روی این پرینتر).
5. درایور مناسب BIXOLON (ترجیحاً Seagull/BarTender اگر برای مدل هست)؛ کاغذ، گپ، تیرگی و سرعت تنظیم شود.
6. بازنویسی CSV و باز کردن مجدد قالب، داده جدید را نشان می‌دهد.
7. اگر BarTender از قبل باز است: رفتار باز کردن مجدد (پنجرهٔ جدید یا قبلی؟ داده کهنه؟).
8. **با Designer باز، آیا اپ می‌تواند `current.csv` را بازنویسی کند؟** (قفل فایل)
9. **آیا Records = All در خود `.btw` می‌ماند؟** (اگر نه، در دستورالعمل اپراتور پررنگ شود.)
10. **روش باز کردن:** `bartend.exe "<file>.btw"` یا `ShellExecute` (سوییچ‌ها از مستندات 11.8 تأیید شود).
11. بستن بدون ذخیره: پیام BarTender و سلامت فایل.
12. Ctrl+S روی همان فایل، اتصال CSV و پرینتر را نگه می‌دارد؛ قالب کپی‌شده روی سیستم دیگر (با همان مسیر ثابت) بدون تنظیم مجدد کار می‌کند.
13. دستهٔ ۵۰۰ ردیفی.

نتیجه در `08` ثبت شود؛ هر مورد ناموفق قبل از ادامهٔ فاز چاپ گزارش و رفع شود.

---

## ۱۱. دستورالعمل اپراتور (خلاصهٔ یک‌صفحه‌ای؛ با تصویر در فاز ۷ تکمیل شود)

1. مدل و تعداد ← «تولید».
2. «چاپ لیبل ۱» ← برند را انتخاب ← «چاپ متن گارانتی» را طبق نیاز تیک بزن ← تأیید.
3. BarTender باز می‌شود و **یک لیبل** می‌بینی (طبیعی است). ظاهر را در صورت نیاز اصلاح و **Ctrl+S**.
4. **Ctrl+P** ← مطمئن شو *Records = All* ← Print. سریال‌ها همه متفاوت‌اند.
5. بعد از چاپ BarTender را ببند. اگر لیبل خراب بود: تاریخچه ← «چاپ مجدد».
6. اگر پیام «پنجرهٔ BarTender را ببندید» دیدی، BarTender را ببند و دوباره امتحان کن.
7. هرگز Save As روی قالب اصلی نزن (فقط برای برند جدید).
8. **بعد از بازیابی سیستم:** قبل از تولید جدید، شمارندهٔ همان روز را با آخرین لیبل فیزیکی تطبیق بده.

---

## ۱۲. پیش‌نیاز سیستم چاپ
ویندوز ۱۰/۱۱ ۶۴بیتی؛ BarTender Enterprise 11.8 (۶۴بیتی) فعال (SDK لازم نیست)؛ درایور و چاپ آزمایشی BIXOLON SLP-TX403؛ .NET Desktop Runtime ۱۰ (بدون .NET Framework 4.8)؛ پوشه‌های `C:\ProgramData\GuaranteeApp\{LabelData,Templates}` با دسترسی نوشتن کاربر (ACL توسط نصب/اولین اجرا)؛ اینترنت برای سینک (اپ بدون آن هم کار می‌کند).
