14 KiB
Executable file
14 KiB
Executable file
تحلیل انتقال بخش انبارها
1. بررسی ساختار جداول
1.1. دیتابیس قدیمی (hesabixOld)
جدول storeroom (انبارها)
- id: شناسه انبار
- bid_id: شناسه کسب و کار
- name: نام انبار
- manager: نام انباردار
- adr: آدرس
- tel: تلفن
- active: فعال/غیرفعال
آمار:
- تعداد کل انبارها: 1,185
- تعداد کسب و کارهای دارای انبار: 924
جدول storeroom_ticket (اسناد انبار)
- id: شناسه سند
- bid_id: شناسه کسب و کار
- submitter_id: شناسه کاربر ایجادکننده
- person_id: شناسه شخص (مشتری/تامینکننده)
- doc_id: شناسه فاکتور مرتبط
- year_id: شناسه سال مالی
- storeroom_id: شناسه انبار
- transfer_type_id: شناسه نوع انتقال (ارجاع به
storeroom_transfer_type) - date: تاریخ سند (فرمت: 1402/08/27)
- date_submit: تاریخ ثبت (timestamp)
- transfer: نام انتقالدهنده
- receiver: نام دریافتکننده
- code: کد سند
- type: نوع سند (
inputیاoutput) - referral: ارجاع
- type_string: نوع سند به فارسی (مثل "حواله ورود"، "حواله خروج")
- des: توضیحات
- sender_tel: تلفن فرستنده
- can_share: قابل اشتراکگذاری
- import_workflow_code: کد workflow واردات
- activation_code: کد فعالسازی
- is_preview: پیشنمایش
- is_approved: تایید شده
- completed: تکمیل شده
- completed_at: تاریخ تکمیل
- approved_by_id: شناسه تاییدکننده
- completed_by_id: شناسه تکمیلکننده
آمار:
- تعداد کل اسناد: 4,564
input: 1,511output: 3,053
جدول storeroom_item (آیتمهای سند انبار)
- id: شناسه آیتم
- ticket_id: شناسه سند انبار
- commodity_id: شناسه کالا
- bid_id: شناسه کسب و کار
- storeroom_id: شناسه انبار
- type: نوع (
inputیاoutput) - count: تعداد (varchar)
- des: توضیحات
- referal: ارجاع
آمار:
- تعداد کل آیتمها: 12,645
input: 5,359output: 7,286
جدول storeroom_transfer_type (نوع انتقال)
- id: شناسه
- name: نام (مثل "تحویل درب انبار"، "پست عادی"، "پست پیشتاز"، "باربری"، "اتوبوس"، "تیپاکس"، "پیک")
1.2. دیتابیس جدید (hesabixpy)
جدول warehouses (انبارها)
- id: شناسه انبار
- business_id: شناسه کسب و کار
- code: کد یکتا در هر کسب و کار (varchar(64))
- name: نام انبار (varchar(255))
- description: توضیحات (text)
- warehouse_keeper: نام انباردار (varchar(255))
- phone: تلفن (varchar(32))
- address: آدرس (text)
- postal_code: کد پستی (varchar(16))
- is_default: انبار پیشفرض (boolean)
- created_at: تاریخ ایجاد
- updated_at: تاریخ بهروزرسانی
محدودیتها:
UNIQUE(business_id, code): کد باید در هر کسب و کار یکتا باشد
جدول warehouse_documents (اسناد انبار)
- id: شناسه سند
- business_id: شناسه کسب و کار
- fiscal_year_id: شناسه سال مالی
- code: کد سند (varchar(64), UNIQUE)
- document_date: تاریخ سند (date)
- status: وضعیت (
draft|posted|cancelled) - doc_type: نوع سند (
receipt|issue|transfer|production_in|production_out|adjustment) - warehouse_id_from: شناسه انبار مبدا (برای transfer)
- warehouse_id_to: شناسه انبار مقصد (برای transfer)
- source_type: نوع منبع (
invoice|manual|api) - source_document_id: شناسه سند منبع
- extra_info: اطلاعات اضافی (JSON)
- created_by_user_id: شناسه کاربر ایجادکننده
- created_at: تاریخ ایجاد
- updated_at: تاریخ بهروزرسانی
جدول warehouse_document_lines (خطوط سند انبار)
- id: شناسه خط
- warehouse_document_id: شناسه سند انبار
- product_id: شناسه کالا
- warehouse_id: شناسه انبار
- movement: نوع حرکت (
in|out) - quantity: تعداد (decimal(18,6))
- cost_price: قیمت تمام شده (decimal(18,6))
- cogs_amount: مبلغ COGS (decimal(18,6))
- extra_info: اطلاعات اضافی (JSON)
- instance_ids: لیست ID کالاهای یونیک (JSON)
2. نگاشت فیلدها
2.1. انبارها (storeroom → warehouses)
| فیلد قدیمی | فیلد جدید | توضیحات |
|---|---|---|
id |
- | استفاده نمیشود (ایجاد جدید) |
bid_id |
business_id |
نیاز به mapping |
name |
name |
مستقیم |
manager |
warehouse_keeper |
مستقیم |
adr |
address |
مستقیم |
tel |
phone |
مستقیم |
active |
- | فقط انبارهای active منتقل میشوند |
| - | code |
باید تولید شود (مثلاً از name یا id) |
| - | description |
میتواند از name یا address استفاده کند |
| - | postal_code |
NULL |
| - | is_default |
اولین انبار هر کسب و کار = true |
2.2. اسناد انبار (storeroom_ticket → warehouse_documents)
| فیلد قدیمی | فیلد جدید | توضیحات |
|---|---|---|
id |
- | استفاده نمیشود |
bid_id |
business_id |
نیاز به mapping |
submitter_id |
created_by_user_id |
نیاز به mapping |
person_id |
- | در extra_info ذخیره میشود |
doc_id |
source_document_id |
نیاز به mapping (اگر فاکتور مرتبط باشد) |
year_id |
fiscal_year_id |
نیاز به mapping |
storeroom_id |
warehouse_id_from یا warehouse_id_to |
بستگی به type دارد |
transfer_type_id |
- | در extra_info ذخیره میشود |
date |
document_date |
تبدیل از شمسی به میلادی |
date_submit |
created_at |
تبدیل از timestamp به datetime |
code |
code |
مستقیم (با بررسی یکتایی) |
type |
doc_type |
تبدیل: input → receipt, output → issue |
type_string |
- | در extra_info ذخیره میشود |
des |
- | در extra_info ذخیره میشود |
transfer |
- | در extra_info ذخیره میشود |
receiver |
- | در extra_info ذخیره میشود |
sender_tel |
- | در extra_info ذخیره میشود |
referral |
- | در extra_info ذخیره میشود |
| - | status |
بر اساس completed و is_approved: completed=1 → posted, در غیر این صورت draft |
| - | warehouse_id_from |
برای transfer (اگر type_string شامل "انتقال" باشد) |
| - | warehouse_id_to |
برای transfer |
| - | source_type |
اگر doc_id وجود داشته باشد → invoice, در غیر این صورت manual |
2.3. آیتمهای سند (storeroom_item → warehouse_document_lines)
| فیلد قدیمی | فیلد جدید | توضیحات |
|---|---|---|
id |
- | استفاده نمیشود |
ticket_id |
warehouse_document_id |
نیاز به mapping |
commodity_id |
product_id |
نیاز به mapping |
storeroom_id |
warehouse_id |
نیاز به mapping |
type |
movement |
تبدیل: input → in, output → out |
count |
quantity |
تبدیل از varchar به decimal |
des |
- | در extra_info ذخیره میشود |
referal |
- | در extra_info ذخیره میشود |
| - | cost_price |
NULL (میتواند از قیمت کالا محاسبه شود) |
| - | cogs_amount |
NULL |
| - | instance_ids |
NULL |
3. تبدیلهای مورد نیاز
3.1. تبدیل نوع سند (type → doc_type)
def convert_doc_type(old_type: str, type_string: str | None) -> str:
"""
تبدیل type قدیمی به doc_type جدید
Args:
old_type: 'input' یا 'output'
type_string: نوع سند به فارسی (مثل "حواله ورود")
Returns:
doc_type جدید: 'receipt'|'issue'|'transfer'|'production_in'|'production_out'|'adjustment'
"""
if old_type == "input":
# بررسی type_string برای تشخیص نوع دقیق
if type_string and "انتقال" in type_string:
return "transfer"
elif type_string and "تولید" in type_string:
return "production_in"
else:
return "receipt"
elif old_type == "output":
if type_string and "انتقال" in type_string:
return "transfer"
elif type_string and "تولید" in type_string:
return "production_out"
else:
return "issue"
else:
return "adjustment" # پیشفرض
3.2. تبدیل وضعیت (completed/is_approved → status)
def convert_status(completed: int | None, is_approved: int | None) -> str:
"""
تبدیل وضعیت قدیمی به status جدید
Returns:
'draft'|'posted'|'cancelled'
"""
if completed == 1:
return "posted"
elif is_approved == 0:
return "cancelled"
else:
return "draft"
3.3. تبدیل تاریخ
- date: از فرمت شمسی (1402/08/27) به
date - date_submit: از timestamp به
datetime
3.4. تبدیل تعداد (count → quantity)
def convert_quantity(count_str: str | None) -> Decimal | None:
"""
تبدیل count از varchar به decimal
"""
if not count_str or not count_str.strip():
return None
try:
cleaned = count_str.strip().replace(',', '').replace(' ', '').replace('،', '')
if not cleaned or cleaned == '0':
return None
return Decimal(cleaned)
except (ValueError, InvalidOperation, TypeError):
return None
3.5. تولید کد انبار (code)
def generate_warehouse_code(name: str, existing_codes: set) -> str:
"""
تولید کد یکتا برای انبار
"""
# استفاده از name (با محدودیت 64 کاراکتر)
base_code = name[:64].strip()
# اگر تکراری است، اضافه کردن شماره
code = base_code
counter = 1
while code in existing_codes:
suffix = f"_{counter}"
code = (base_code[:64-len(suffix)] + suffix)
counter += 1
return code
4. روابط و وابستگیها
4.1. وابستگیهای انبارها
- business_id: نیاز به mapping از
bid_idقدیمی بهbusiness_idجدید - code: باید یکتا در هر کسب و کار باشد
4.2. وابستگیهای اسناد انبار
- business_id: نیاز به mapping
- fiscal_year_id: نیاز به mapping از
year_id - warehouse_id_from/warehouse_id_to: نیاز به mapping از
storeroom_id - created_by_user_id: نیاز به mapping از
submitter_id - source_document_id: نیاز به mapping از
doc_id(اگر فاکتور مرتبط باشد) - code: باید یکتا باشد (UNIQUE)
4.3. وابستگیهای خطوط سند
- warehouse_document_id: نیاز به mapping از
ticket_id - product_id: نیاز به mapping از
commodity_id - warehouse_id: نیاز به mapping از
storeroom_id
5. چالشها و راهحلها
5.1. یکتایی کد سند (code)
- مشکل:
codeدرwarehouse_documentsباید یکتا باشد - راهحل: اگر تکراری است، اضافه کردن suffix (مثلاً
_1,_2)
5.2. تشخیص نوع سند (transfer vs receipt/issue)
- مشکل:
typeفقطinput/outputاست، اما بایدtransferرا تشخیص دهیم - راهحل: استفاده از
type_stringبرای تشخیص
5.3. mapping فاکتورها (doc_id → source_document_id)
- مشکل:
doc_idدر دیتابیس قدیمی به فاکتورها اشاره میکند که هنوز منتقل نشدهاند - راهحل: اگر فاکتورها منتقل نشدهاند،
source_document_idرا NULL بگذاریم وsource_typeراmanualکنیم
5.4. انبار پیشفرض (is_default)
- راهحل: اولین انبار هر کسب و کار را
is_default = trueکنیم
5.5. تبدیل تاریخ شمسی
- راهحل: استفاده از کتابخانه
jdatetimeبرای تبدیل تاریخ شمسی به میلادی
6. مراحل انتقال
-
انتقال انبارها (warehouses)
- ایجاد mapping بین
storeroom_idقدیمی وwarehouse_idجدید - فقط انبارهای
active = 1را منتقل کنیم
- ایجاد mapping بین
-
انتقال اسناد انبار (warehouse_documents)
- ایجاد mapping بین
ticket_idقدیمی وwarehouse_document_idجدید - تبدیل
typeبهdoc_type - تبدیل تاریخها
- تبدیل وضعیت
- ایجاد mapping بین
-
انتقال خطوط سند (warehouse_document_lines)
- استفاده از mapping های ایجاد شده
- تبدیل
countبهquantity - تبدیل
typeبهmovement
7. آمار کلی
- انبارها: 1,185
- اسناد انبار: 4,564
- ورود: 1,511
- خروج: 3,053
- آیتمهای سند: 12,645
- ورود: 5,359
- خروج: 7,286
- کسب و کارهای دارای انبار: 924