مستند تعریف محصول، تنوع (Variant) و ثبت اطلاعات در ادمین پنل، منطبق بر پیادهسازی فعلی.
مسیرهای مرتبط:
- فرم ثبت/ویرایش: [AddProduct.vue](../apps/admin-panel/src/views/apps/product/AddProduct.vue) (هم برای ایجاد هم ویرایش استفاده میشود؛ [EditProduct.vue](../apps/admin-panel/src/views/apps/product/EditProduct.vue) صرفاً یک wrapper است)
- لیست محصولات: [ProductList.vue](../apps/admin-panel/src/views/apps/product/ProductList.vue) و مدل جدول [productListModel.ts](../apps/admin-panel/src/views/apps/product/productListModel.ts)
- بکاند: [admin-products.controller.ts](../apps/api/src/modules/admin-products/admin-products.controller.ts) و [admin-products.service.ts](../apps/api/src/modules/admin-products/admin-products.service.ts)
هر محصول یک رکورد پایه دارد که در کارت «اطلاعات پایه» و «تصاویر محصول» فرم پر میشود.
### ۱.۱ اطلاعات پایه
| فیلد فرم (فارسی) | نام در فرم/پیلود | ستون در دیتابیس | نوع | الزامی | توضیح |
|---|---|---|---|---|---|
| کد محصول | `product_code` | `Product.productCode` | string، یکتا (`@unique`) | خیر | SKU نمایشی؛ در فرم اعتبارسنجی نمیشود ولی در دیتابیس یکتا است |
| نام محصول | `title` | `Product.title` | string | بله | تنها فیلد با اعتبارسنجی سمت فرم (`err.title`) |
| نوع نمایش | `show_type` | `Product.showType` | int، پیشفرض `3` | خیر | مقادیر: `1` سایت، `2` گوشی، `3` سایت و گوشی |
| دستهبندی | `category_id` | `Product.categoryId` (FK به `Category`) | string، اختیاری | خیر | از `GET category` پر میشود؛ عنوانها با نوع فروشگاه (`type_str`) پسوند میخورند |
| برند | `brand_id` | `Product.brandId` (FK به `Brand`) | string، اختیاری | خیر | از `GET brand` |
| سینیها (گروهبندی) | `ciny_ids` | جدول واسط `CollectionProduct` → مدل `Collection` | آرایه از id | خیر | چندانتخابی؛ معادل مدرن فیچر قدیمی «Ciny»، صرفاً یک تگگذاری/گروهبندی محصول است، نه چیزی مرتبط با قیمت لحظهای طلا |
| شرح محصول (سایت) | `body_html` | `Product.description` | text | خیر | |
| نمایش محصول | `is_active` | `Product.isActive` | boolean، پیشفرض `true` | خیر | فعال/غیرفعال بودن محصول در فروشگاه |
فیلدهای سیستمی که در فرم دیده نمیشوند: `id` (cuid)، `createdAt`.
> فیلدهای نسخه قدیمی که عمداً حذف شدهاند (چون ستون معادل در اسکیمای جدید ندارند): `delivery_type`, `message_long_delivery`, `offer_day`, `has_warranty`, `is_exist`, `tags`، و فیلدهای رنگ/اجرت ریالی در تنوع. طبق کامنت بالای فایل فرم، این تصمیم آگاهانه بوده — داده جمعآوری و بیصدا دور ریخته نمیشود.
### ۱.۲ تصاویر محصول
محصول به ازای هر تصویر یک رکورد `ProductImage` دارد که با فیلد `role` مشخص میشود کدام یک از ۴ اسلات قدیمی است:
| بخش فرم (فارسی) | `ProductImageRole` | تعداد | فیلد پیلود |
آپلود از طریق کامپوننت `ImageUploadInput` و اندپوینت عمومی `file/create` انجام میشود (همان اندپوینتی که برای آپلود دستهبندی/اسلایدر/آواتار هم استفاده میشود). فیلد `imageBody` (کپشن هر تصویر گالری در نسخه قدیمی) معادلی در دیتابیس ندارد و حذف شده.
---
## ۲. کارکرد واریانت (تنوع محصول)
هر محصول میتواند چند «تنوع» (`ProductVariant`) داشته باشد — مثلاً وزنهای مختلف یک مدل طلا. مدیریت واریانتها **درون همان فرم محصول** و بهصورت یک جدول اینلاین با مودال افزودن/ویرایش انجام میشود؛ واریانتها تا زمان «ثبت اطلاعات» فقط در حافظه (state) نگه داشته میشوند و همراه با کل محصول به سرور ارسال میگردند.
### ۲.۱ فیلدهای واریانت
| عنوان در مودال | نام فیلد | ستون دیتابیس | نوع | توضیح |
|---|---|---|---|---|
| عنوان | `title` | `ProductVariant.title` | string، الزامی | تنها فیلد با اعتبارسنجی (`عنوان تنوع الزامی است`) |
| وزن | `grams` | `ProductVariant.rashWeightGrams` | Decimal(14,4) | وزن پایه/خام پیش از احتساب اجرت («rash weight») |
فیلدهای دیگر مدل `ProductVariant` که در فرم نیستند: `sku` (یکتا)، `id`. تمام فیلدهای مرجع henza_admin شامل رنگ، اجرت ریالی و توضیحات تنوع با موفقیت پورت شدند.
-`cats` مشتق از `category_id` است (آرایهای تکعضوی یا خالی) — یک artifact از انتقال ساختار قدیمی چند-دستهای.
-`images` معادل گالری سایت و `images_mobile` معادل گالری موبایل است؛ تصاویر شاخص جدا (`indicator_id`, `mobile_pic`) ارسال میشوند.
- کل آرایه `variants` هر بار با کل درخواست ارسال میشود (نه اندپوینت جداگانه)؛ بکاند مسئول تطبیق/ایجاد/بهروزرسانی ردیفها بر اساس وجود یا نبود `id` است.
### ۳.۴ بازخورد به کاربر
- موفق: پیام `اطلاعات با موفقیت به ثبت رسید.` و ریدایرکت به `/apps/product/list`.
- خطا: پیام خطای برگشتی از سرور (`e.response.data.message`) یا پیام پیشفرض `خطا در ثبت اطلاعات.`
- در حین ارسال، کل فرم پشت `a-spin` (لودینگ) قفل میشود.
### ۳.۵ پرمیشنهای مرتبط با ثبت/مدیریت واریانت
| کلید پرمیشن | کنترل میکند |
|---|---|
| `product.list.variants` | نمایش کل بخش «تنوعها» در فرم محصول |
| `product.list.variants.view` | مشاهده (تعریفشده در `permissionConst.ts`؛ در UI فعلی فرم جداگانه چک نشده) |
| `product.list.variants.add` | نمایش دکمه «افزودن تنوع» |
| `product.list.variants.edit` | نمایش آیکون ویرایش هر ردیف تنوع |
| `product.list.variants.remove` | نمایش آیکون حذف هر ردیف تنوع |
ثبت خودِ محصول (فرم اصلی) پرمیشن جداگانهای در این فایل چک نمیکند — دسترسی به صفحه از طریق روتینگ/منو کنترل میشود.
---
## ۴. لیست محصولات (خلاصه، برای زمینه)
جدول لیست (`admin/products/list`) این ستونها را نشان میدهد: کد، تصویر محصول، نام محصول، برند، دستهبندی، کد محصول، نوع نمایش (با فیلتر انتخابی روی مقادیر ۱/۲/۳)، عملیات. تعریف کامل در [productListModel.ts](../apps/admin-panel/src/views/apps/product/productListModel.ts).