20 KiB
Executable file
سناریو: تولید کالا از طریق فاکتور تولید با استفاده از فرمول تولید (BOM)
اصل طراحی
فرمول تولید (BOM) که منجر به تولید کالای جدید میشود، صرفاً از طریق فاکتور تولید انجام میشود.
این یعنی:
- ✅ اجباری: هر فاکتور تولید باید از یک فرمول تولید استفاده کند
- ✅ یکپارچه: تمام فرآیند تولید از تعریف فرمول تا صدور فاکتور در یک جریان یکپارچه انجام میشود
- ✅ قابل ردیابی: هر فاکتور تولید به یک فرمول مشخص لینک میشود
وضعیت فعلی
1. مدیریت فرمول تولید (BOM) در بخش کالا
- مکان: تب "فرمول تولید" در فرم ویرایش/ایجاد کالا (
product_form_dialog.dart) - عملکرد فعلی:
- کاربر میتواند فرمولهای تولید را برای هر کالا تعریف کند
- فرمولها در جدول
product_bomsذخیره میشوند و به کالا لینک میشوند (product_id) - هر فرمول میتواند چندین نسخه داشته باشد (
version) - یک فرمول میتواند به عنوان پیشفرض تنظیم شود (
is_default) - حذف شده: دکمه "انفجار فرمول" از این بخش حذف شده است
2. صدور فاکتور تولید
- مکان: صفحه
new_invoice_page.dart - نوع فاکتور:
InvoiceType.production(مقدار API:invoice_production) - عملکرد فعلی:
- کاربر میتواند فاکتور از نوع "تولید" را ایجاد کند
- ویجت
BomExplosionWidgetبرای استفاده از فرمولهای تولید موجود است - اما استفاده از BOM اجباری نیست (مشکل)
مشکل فعلی
- ❌ استفاده از BOM اجباری نیست: کاربر میتواند فاکتور تولید بدون استفاده از فرمول تولید ایجاد کند
- ❌ movement تنظیم نمیشود: در BOM Explosion، مقدار
movementدرextra_infoردیفها ذخیره نمیشود - ❌ عدم ردیابی: فاکتور تولید به فرمول استفاده شده لینک نمیشود
- ❌ امکان خطا: کاربر میتواند به صورت دستی ردیفهای نادرست اضافه کند
سناریو بازطراحی شده
اصول طراحی
- ✅ اجبار استفاده از BOM: هر فاکتور تولید باید حداقل از یک فرمول تولید استفاده کند
- ✅ مدیریت فرمول در بخش کالا: فرمولها همچنان در تب "فرمول تولید" کالا تعریف و مدیریت میشوند
- ✅ انفجار در فاکتور: انفجار فرمول فقط در صفحه صدور فاکتور تولید انجام میشود
- ✅ ردیابی کامل: هر فاکتور تولید به فرمول(های) استفاده شده لینک میشود
- ✅ حرکت خودکار: مقدار
movementدرextra_infoبه صورت خودکار تنظیم میشود
تغییرات پیشنهادی
1. بخش کالا (Frontend - product_bom_section.dart)
تغییرات:
- ✅ حفظ: مدیریت فرمولها (ایجاد، ویرایش، حذف) همچنان در این بخش باقی میماند
- ❌ حذف: دکمه "انفجار فرمول" از این بخش حذف میشود
- ❌ حذف: دیالوگ نمایش نتایج انفجار و ایجاد پیشنویس سند حذف میشود
- ✅ افزودن: یک پیام راهنما یا لینک به کاربر که "برای استفاده از این فرمول، در فاکتور تولید از آن استفاده کنید"
2. صفحه صدور فاکتور تولید (Frontend - new_invoice_page.dart)
تغییرات:
- ✅ اجبار استفاده از BOM:
- اگر نوع فاکتور "تولید" است، کاربر نمیتواند فاکتور را ذخیره کند مگر اینکه حداقل یک بار انفجار فرمول انجام داده باشد
- یک پیام هشدار نمایش داده میشود: "برای فاکتور تولید، باید حداقل یک فرمول تولید را منفجر کنید"
- ✅ ویجت انفجار فرمول (بهبود یافته):
- انتخاب کالای تولیدی (از لیست کالاها)
- نمایش فرمولهای موجود برای آن کالا (اگر فرمول پیشفرض وجود دارد، به صورت پیشفرض انتخاب شود)
- امکان انتخاب فرمول خاص (اگر چند فرمول وجود دارد)
- ورود مقدار تولید
- دکمه "انفجار و افزودن به فاکتور"
- جدید: پس از انفجار، ID فرمول در
extra_infoفاکتور ذخیره میشود
- ✅ پس از انفجار (بهبود یافته):
- نتایج انفجار به صورت ردیفهای فاکتور به
_lineItemsاضافه میشوند - اجباری: مواد اولیه (inputs) با
movement: "out"درextra_infoتنظیم میشوند - اجباری: خروجیها (outputs) با
movement: "in"درextra_infoتنظیم میشوند - جدید: ID فرمول استفاده شده در
extra_infoهر ردیف ذخیره میشود (برای ردیابی) - کاربر میتواند قبل از ذخیره، ردیفها را ویرایش کند (مقدار، قیمت، انبار)
- جدید: امکان انفجار چند فرمول در یک فاکتور (برای محصولات مختلف)
- نتایج انفجار به صورت ردیفهای فاکتور به
- ✅ اعتبارسنجی قبل از ذخیره:
- بررسی میشود که حداقل یک ردیف با
movement: "out"وجود دارد (مواد اولیه) - بررسی میشود که حداقل یک ردیف با
movement: "in"وجود دارد (محصول نهایی) - بررسی میشود که تمام ردیفهای فاکتور
movementمشخص داشته باشند
- بررسی میشود که حداقل یک ردیف با
3. Backend (تغییرات اعتبارسنجی)
- ✅ API
explode_bomهمچنان موجود است و استفاده میشود - ✅ جدید: اعتبارسنجی در
create_invoice:- اگر نوع فاکتور
invoice_productionاست:- بررسی میشود که حداقل یک ردیف با
movement: "out"وجود دارد - بررسی میشود که حداقل یک ردیف با
movement: "in"وجود دارد - بررسی میشود که تمام ردیفها
movementمشخص داشته باشند - در صورت عدم وجود، خطا: "فاکتور تولید باید از فرمول تولید استفاده کند"
- بررسی میشود که حداقل یک ردیف با
- اگر نوع فاکتور
- ✅ جدید: ذخیره اطلاعات فرمول:
- در
extra_infoفاکتور، لیست ID فرمولهای استفاده شده ذخیره میشود:{"bom_ids": [1, 2]} - در
extra_infoهر ردیف، ID فرمول استفاده شده ذخیره میشود:{"bom_id": 1}
- در
- ✅ ساختار دیتابیس بدون تغییر باقی میماند
جریان کار طراحی شده
1. کاربر در بخش کالا (تعریف فرمول):
└─> کالای تولیدی را ایجاد/ویرایش میکند
└─> در تب "فرمول تولید"، فرمولهای تولید را تعریف میکند:
├─ مواد اولیه (component products)
├─ خروجیها (output products)
└─ عملیات (operations)
└─> فرمول را ذخیره میکند
└─> (اختیاری) فرمولی را به عنوان پیشفرض تنظیم میکند
2. کاربر برای صدور فاکتور تولید:
└─> به صفحه "صدور فاکتور جدید" میرود
└─> نوع فاکتور را "تولید" انتخاب میکند
└─> به تب "کالاها و خدمات" میرود
└─> ⚠️ سیستم بررسی میکند که آیا فرمولی منفجر شده است؟
├─ خیر: نمایش پیام هشدار "برای فاکتور تولید، باید حداقل یک فرمول تولید را منفجر کنید"
└─ بله: ادامه روند
└─> دکمه "انفجار فرمول" را میزند
└─> کالای تولیدی را انتخاب میکند
└─> سیستم فرمولهای موجود را نمایش میدهد:
├─ اگر فرمول پیشفرض وجود دارد، به صورت پیشفرض انتخاب میشود
└─ در غیر این صورت، کاربر فرمول را انتخاب میکند
└─> مقدار تولید را وارد میکند
└─> دکمه "انفجار و افزودن" را میزند
└─> ✅ ردیفهای فاکتور به صورت خودکار پر میشوند:
├─ مواد اولیه (movement: "out" در extra_info)
│ └─ extra_info.bom_id = [ID فرمول]
└─ محصولات تولید شده (movement: "in" در extra_info)
└─ extra_info.bom_id = [ID فرمول]
└─> (اختیاری) امکان انفجار فرمول دیگر برای کالای دیگر
└─> کاربر میتواند ردیفها را ویرایش کند:
├─ مقدار (quantity)
├─ قیمت (unit_price)
├─ انبار (warehouse_id)
└─ ⚠️ نمیتواند movement را تغییر دهد
└─> هنگام ذخیره، اعتبارسنجی انجام میشود:
├─ ✅ حداقل یک ردیف با movement: "out" وجود دارد؟
├─ ✅ حداقل یک ردیف با movement: "in" وجود دارد؟
└─ ✅ تمام ردیفها movement مشخص دارند؟
└─> ✅ فاکتور ذخیره میشود
└─> ✅ حوالههای انبار به صورت خودکار ایجاد میشوند:
├─ حواله issue (برای مواد اولیه - movement: "out")
└─ حواله receipt (برای محصولات نهایی - movement: "in")
└─> ✅ اسناد حسابداری در پست حوالهها ایجاد میشوند
جزئیات پیادهسازی
Frontend - ویجت انفجار فرمول در فاکتور (بهبود یافته)
فایل: hesabixUI/hesabix_ui/lib/widgets/invoice/bom_explosion_widget.dart
تغییرات لازم:
class BomExplosionWidget extends StatefulWidget {
final int businessId;
final Function(List<InvoiceLineItem>, int bomId) onExploded; // bomId اضافه شد
// ...
}
// در _explodeAndAdd():
// پس از انفجار موفق:
final bomId = _selectedBom?.id;
if (bomId != null) {
// اضافه کردن bom_id به extra_info هر ردیف
for (var item in lineItems) {
// باید InvoiceLineItem را گسترش دهیم یا از Map استفاده کنیم
}
widget.onExploded(lineItems, bomId);
}
عملکرد بهبود یافته:
- ✅ نمایش یک کارت برجسته در تب "کالاها و خدمات" (فقط برای
InvoiceType.production) - ✅ دیالوگ انتخاب کالا و فرمول
- ✅ ورود مقدار تولید با اعتبارسنجی
- ✅ فراخوانی API
explode_bom - ✅ تبدیل نتایج به
InvoiceLineItemبا تنظیم خودکار:- مواد اولیه:
extra_info.movement = "out" - خروجیها:
extra_info.movement = "in" - همه:
extra_info.bom_id = [bomId]
- مواد اولیه:
- ✅ افزودن به لیست و نمایش موفقیت
- ✅ جدید: ذخیره لیست
bom_idsدرextra_infoفاکتور
تغییرات در new_invoice_page.dart:
- ✅ در متد
_buildProductsTab():- ویجت
BomExplosionWidgetرا نمایش بده (همیشه در بالای جدول) - پس از انفجار، ردیفها را به
_lineItemsاضافه کن bom_idرا درextra_infoفاکتور ذخیره کن
- ویجت
- ✅ جدید: در متد
_serializeLineItem():- بررسی کن که اگر نوع فاکتور
productionاست:- اگر ردیف
movementندارد، خطا بده
- اگر ردیف
- بررسی کن که اگر نوع فاکتور
- ✅ جدید: در متد
_validateAndBuildPayload():- اگر نوع فاکتور
productionاست:- بررسی کن که حداقل یک ردیف با
movement: "out"وجود دارد - بررسی کن که حداقل یک ردیف با
movement: "in"وجود دارد - بررسی کن که تمام ردیفها
movementمشخص دارند - در صورت عدم وجود، خطا: "برای فاکتور تولید، باید حداقل یک فرمول تولید را منفجر کنید"
- بررسی کن که حداقل یک ردیف با
- اگر نوع فاکتور
Frontend - حذف انفجار از بخش کالا
تغییرات در product_bom_section.dart:
- حذف متد
_explode() - حذف دکمه "انفجار فرمول" از
ListTile - (اختیاری) افزودن یک
InfoCardکه راهنمایی میدهد: "برای استفاده از این فرمول، در فاکتور تولید از آن استفاده کنید"
مزایای این رویکرد
-
✅ یکپارچگی و کنترل:
- تمام فرآیند تولید از یک مسیر انجام میشود
- کاهش خطاهای انسانی (عدم وارد کردن دستی مواد اولیه)
- تضمین صحت دادهها
-
✅ جداسازی مسئولیتها:
- مدیریت فرمول = بخش کالا (تعریف و نگهداری)
- استفاده از فرمول = فاکتور تولید (اجرای عملیات)
-
✅ ردیابی کامل:
- هر فاکتور تولید به فرمول(های) استفاده شده لینک میشود
- امکان گزارشگیری دقیق از تولیدات بر اساس فرمول
- امکان بازگشت و بررسی فرمول استفاده شده
-
✅ تجربه کاربری بهتر:
- کاربر مستقیماً در فاکتور میتواند از فرمول استفاده کند
- راهنماییهای واضح برای کاربر
- جلوگیری از خطا با اعتبارسنجیهای مناسب
-
✅ انعطافپذیری کنترل شده:
- کاربر میتواند پس از انفجار، ردیفها را ویرایش کند (مقدار، قیمت، انبار)
- کاربر نمیتواند
movementرا تغییر دهد (برای جلوگیری از خطا) - امکان انفجار چند فرمول در یک فاکتور (برای تولید چند محصول)
-
✅ سازگاری با Backend:
- از APIهای موجود استفاده میکند
- اعتبارسنجیهای اضافی در Backend برای اطمینان از صحت دادهها
تصمیمات طراحی
-
✅ امکان ویرایش ردیفهای انفجار شده: بله
- کاربر میتواند مقدار، قیمت و انبار را تغییر دهد
- کاربر نمیتواند
movementرا تغییر دهد (برای جلوگیری از خطا)
-
✅ امکان انفجار چندباره: بله
- کاربر میتواند چند فرمول مختلف را در یک فاکتور منفجر کند
- هر فرمول میتواند برای کالای متفاوتی باشد
-
✅ اجبار استفاده از BOM: بله
- کاربر نمیتواند فاکتور تولید را بدون انفجار حداقل یک فرمول ذخیره کند
- اعتبارسنجی در Frontend و Backend انجام میشود
-
✅ ذخیره اطلاعات فرمول: بله
bom_idدرextra_infoهر ردیف ذخیره میشود- لیست
bom_idsدرextra_infoفاکتور ذخیره میشود
-
✅ حذف گروهی ردیفهای انفجار شده: بله (در نسخههای بعدی)
- امکان حذف تمام ردیفهای مربوط به یک فرمول خاص
-
✅ حرکت خودکار: بله
movement: "out"برای مواد اولیه به صورت خودکار تنظیم میشودmovement: "in"برای محصولات نهایی به صورت خودکار تنظیم میشود
خلاصه تغییرات فایلها
فایلهای جدید
- ✅
hesabixUI/hesabix_ui/lib/widgets/invoice/bom_explosion_widget.dart- ویجت انفجار فرمول در فاکتور (موجود)
فایلهای تغییر یافته (نیاز به اصلاح)
Frontend:
-
hesabixUI/hesabix_ui/lib/widgets/invoice/bom_explosion_widget.dart:- ✅ افزودن
movementبهextra_infoهر ردیف - ✅ افزودن
bom_idبهextra_infoهر ردیف - ✅ برگرداندن
bom_idبه callback
- ✅ افزودن
-
hesabixUI/hesabix_ui/lib/pages/business/new_invoice_page.dart:- ✅ ذخیره
bom_idsدرextra_infoفاکتور - ✅ اعتبارسنجی قبل از ذخیره: بررسی وجود حداقل یک انفجار فرمول
- ✅ اعتبارسنجی
movementبرای تمام ردیفها
- ✅ ذخیره
-
hesabixUI/hesabix_ui/lib/models/invoice_line_item.dart(اختیاری):- بررسی نیاز به اضافه کردن فیلد
bomIdیا استفاده ازextra_info
- بررسی نیاز به اضافه کردن فیلد
Backend:
hesabixAPI/app/services/invoice_service.py:- ✅ اعتبارسنجی در
create_invoiceبرای فاکتور تولید:- بررسی وجود حداقل یک ردیف با
movement: "out" - بررسی وجود حداقل یک ردیف با
movement: "in" - بررسی وجود
movementدر تمام ردیفها
- بررسی وجود حداقل یک ردیف با
- ✅ اعتبارسنجی در
فایلهای بدون تغییر
- ✅ مدلهای دیتابیس (نیاز به تغییر ندارند)
- ✅ API endpoints موجود (نیاز به تغییر ندارند)
- ✅ ساختار
product_bomsو جداول مرتبط
چکلیست پیادهسازی
مرحله 1: Frontend - ویجت انفجار
- تنظیم
movement: "out"برای مواد اولیه درBomExplosionWidget - تنظیم
movement: "in"برای خروجیها درBomExplosionWidget - اضافه کردن
bom_idبهextra_infoهر ردیف - برگرداندن
bom_idبه callback
مرحله 2: Frontend - صفحه فاکتور
- ذخیره لیست
bom_idsدرextra_infoفاکتور - اعتبارسنجی قبل از ذخیره: بررسی انفجار حداقل یک فرمول
- نمایش پیام هشدار در صورت عدم وجود انفجار فرمول
- اعتبارسنجی
movementبرای تمام ردیفها
مرحله 3: Backend - اعتبارسنجی
- اعتبارسنجی در
create_invoiceبرای فاکتور تولید - بررسی وجود
movementدر تمام ردیفها - بررسی وجود حداقل یک ردیف با
movement: "out" - بررسی وجود حداقل یک ردیف با
movement: "in"
مرحله 4: تست
- تست ایجاد فاکتور تولید با استفاده از BOM
- تست عدم امکان ذخیره فاکتور تولید بدون BOM
- تست انفجار چند فرمول در یک فاکتور
- تست ویرایش ردیفهای انفجار شده
- تست ایجاد حوالههای انبار
آماده برای پیادهسازی