First commit of the Hedena Gold product (separate from gold-bank): branding, package names, and deploy defaults aligned to the new brand; legacy Henza trees stay local-only via .gitignore.
12 KiB
ماژول محصول (Product) — ادمین پنل
مستند تعریف محصول، تنوع (Variant) و ثبت اطلاعات در ادمین پنل، منطبق بر پیادهسازی فعلی.
مسیرهای مرتبط:
- فرم ثبت/ویرایش: AddProduct.vue (هم برای ایجاد هم ویرایش استفاده میشود؛ EditProduct.vue صرفاً یک wrapper است)
- لیست محصولات: ProductList.vue و مدل جدول productListModel.ts
- بکاند: admin-products.controller.ts و admin-products.service.ts
- اسکیمای دیتابیس: schema.prisma (مدلهای
Product,ProductVariant,ProductImage)
۱. تعریف محصول (Product)
هر محصول یک رکورد پایه دارد که در کارت «اطلاعات پایه» و «تصاویر محصول» فرم پر میشود.
۱.۱ اطلاعات پایه
| فیلد فرم (فارسی) | نام در فرم/پیلود | ستون در دیتابیس | نوع | الزامی | توضیح |
|---|---|---|---|---|---|
| کد محصول | 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 |
تعداد | فیلد پیلود |
|---|---|---|---|
| تصویر شاخص | FEATURED |
تک | indicator_id |
| تصویر شاخص موبایل | FEATURED_MOBILE |
تک | mobile_pic |
| گالری تصاویر سایت | GALLERY (پیشفرض) |
چندتایی | images |
| گالری تصاویر موبایل | GALLERY_MOBILE |
چندتایی | images_mobile |
آپلود از طریق کامپوننت ImageUploadInput و اندپوینت عمومی file/create انجام میشود (همان اندپوینتی که برای آپلود دستهبندی/اسلایدر/آواتار هم استفاده میشود). فیلد imageBody (کپشن هر تصویر گالری در نسخه قدیمی) معادلی در دیتابیس ندارد و حذف شده.
۲. کارکرد واریانت (تنوع محصول)
هر محصول میتواند چند «تنوع» (ProductVariant) داشته باشد — مثلاً وزنهای مختلف یک مدل طلا. مدیریت واریانتها درون همان فرم محصول و بهصورت یک جدول اینلاین با مودال افزودن/ویرایش انجام میشود؛ واریانتها تا زمان «ثبت اطلاعات» فقط در حافظه (state) نگه داشته میشوند و همراه با کل محصول به سرور ارسال میگردند.
۲.۱ فیلدهای واریانت
| عنوان در مودال | نام فیلد | ستون دیتابیس | نوع | توضیح |
|---|---|---|---|---|
| عنوان | title |
ProductVariant.title |
string، الزامی | تنها فیلد با اعتبارسنجی (عنوان تنوع الزامی است) |
| وزن | grams |
ProductVariant.rashWeightGrams |
Decimal(14,4) | وزن پایه/خام پیش از احتساب اجرت («rash weight») |
| اجرت درصدی | percentage_pay |
ProductVariant.defaultWagePercent |
Decimal(6,3) | درصد اجرت پیشفرض روی وزن پایه |
| تعداد | qty |
ProductVariant.qty |
int، پیشفرض 0 |
موجودی انبار |
| فعال | is_active |
ProductVariant.isActive |
boolean، پیشفرض true |
|
| پیش سفارش | is_pre_order |
ProductVariant.isPreOrder |
boolean، پیشفرض false |
اگر true باشد، حتی با موجودی صفر قابل سفارش است |
فیلدهای دیگر مدل ProductVariant که در فرم نیستند: sku (یکتا)، id. فیلد رنگ و اجرت ریالی نسخه قدیمی حذف شدهاند (بدون ستون معادل).
قاعدهی سبد خرید: اگر
qty = 0وisPreOrder = falseباشد، واریانت قابل افزودن به سبد نیست (منطق درapps/admin-panel/src/stores/cart.ts).
۲.۲ رفتار UI جدول تنوعها
- ستونها: عنوان، وزن، اجرت درصدی، تعداد، فعال (تگ سبز/قرمز)، پیش سفارش (تگ آبی/خالی)، عملیات.
- افزودن تنوع: دکمه بالای جدول → باز کردن مودال خالی با کلید موقت
__key(برای ردیابی ردیف پیش از ذخیره در سرور). - ویرایش تنوع: آیکون ویرایش هر ردیف → پر کردن مودال با مقادیر همان ردیف.
- حذف تنوع: آیکون حذف → صرفاً از آرایهی حافظه حذف میشود؛ حذف واقعی از دیتابیس زمانی رخ میدهد که فرم اصلی «ثبت اطلاعات» شود.
- کل بخش تنوعها پشت پرمیشن است (زیر بخش «ثبت اطلاعات» دقیقتر شرح داده شده).
۳. ثبت اطلاعات
۳.۱ فرم ایجاد/ویرایش
- یک فرم واحد (
AddProduct.vue) هم برای ایجاد و هم ویرایش به کار میرود؛ تشخیص حالت از روی وجودroute.params.id. - اعتبارسنجی سمت کلاینت: فقط «نام محصول» (
title) الزامی است؛ در سطح واریانت فقط «عنوان» الزامی است. سایر فیلدها اختیاریاند. - دکمه ارسال: «ثبت اطلاعات» →
handleSubmit.
۳.۲ اندپوینتها
| حالت | متد | مسیر |
|---|---|---|
| ایجاد محصول جدید | POST |
product/create |
| ویرایش محصول موجود | PUT |
product/update/:id |
| نمایش یک محصول (پر کردن فرم ویرایش) | GET |
product/show/:id |
| لیست برندها | GET |
brand |
| لیست دستهبندیها | POST |
category |
| لیست سینیها/کالکشنها | GET |
admin/products/collections |
۳.۳ ساختار پیلود ارسالی
{
"title": "...",
"product_code": "...",
"show_type": 3,
"category_id": "...",
"brand_id": "...",
"ciny_ids": ["..."],
"body_html": "...",
"is_active": true,
"indicator_id": "url|null",
"mobile_pic": "url|null",
"cats": ["category_id"],
"images": ["url", "..."],
"images_mobile": ["url", "..."],
"variants": [
{
"id": "فقط در ویرایش واریانت موجود",
"title": "...",
"grams": 0,
"percentage_pay": 0,
"qty": 0,
"is_active": true,
"is_pre_order": false
}
]
}
نکات مهم:
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.