Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/docs/CHECK_MIGRATION_ANALYSIS.md
2026-04-14 19:34:55 +03:30

13 KiB
Executable file

تحلیل انتقال چک‌ها از hesabixOld به hesabixpy

بررسی جداول

دیتابیس قدیمی (hesabixOld)

جدول cheque (چک‌ها)

  • تعداد رکوردها: 1,872
  • ساختار:
    • id: int (PK)
    • bid_id: int (FK به business) - NOT NULL
    • submitter_id: int (FK به user) - NOT NULL
    • bank_id: int (FK به bank_account) - nullable
    • person_id: int (FK به person) - nullable
    • ref_id: int (FK - احتمالاً به document یا invoice) - nullable
    • date_submit: varchar(50) - تاریخ ثبت (timestamp)
    • type: varchar(20) - نوع چک ("input" یا "output")
    • sayad_num: varchar(50) - شماره صیاد - nullable
    • des: varchar(255) - توضیحات - nullable
    • date_stamp: varchar(50) - تاریخ چک (timestamp) - NOT NULL
    • pay_date: varchar(50) - تاریخ پرداخت (string) - nullable
    • number: varchar(255) - شماره چک - NOT NULL
    • bank_oncheque: varchar(255) - نام بانک روی چک - NOT NULL
    • amount: varchar(255) - مبلغ (string) - NOT NULL
    • status: varchar(255) - وضعیت (string) - nullable
    • locked: tinyint(1) - قفل شده - nullable
    • date: varchar(255) - تاریخ (string) - nullable
    • rejected: tinyint(1) - رد شده - nullable
    • money_id: int (FK به money) - nullable
    • transfered: tinyint(1) - منتقل شده - nullable
    • transfer_date: varchar(25) - تاریخ انتقال - nullable

دیتابیس جدید (hesabixpy)

جدول checks (چک‌ها)

  • id: int (PK)
  • business_id: int (FK) - NOT NULL
  • type: ENUM('RECEIVED', 'TRANSFERRED') - NOT NULL
  • person_id: int (FK به persons) - nullable
  • issue_date: datetime - NOT NULL (تاریخ چک)
  • due_date: datetime - NOT NULL (تاریخ سررسید)
  • check_number: varchar(50) - NOT NULL
  • sayad_code: varchar(16) - nullable
  • bank_name: varchar(255) - nullable
  • branch_name: varchar(255) - nullable
  • amount: numeric(18, 2) - NOT NULL
  • currency_id: int (FK) - NOT NULL
  • status: ENUM('RECEIVED_ON_HAND', 'TRANSFERRED_ISSUED', 'DEPOSITED', 'CLEARED', 'ENDORSED', 'RETURNED', 'BOUNCED', 'CANCELLED') - nullable
  • status_at: datetime - nullable
  • current_holder_type: ENUM('BUSINESS', 'BANK', 'PERSON') - nullable
  • current_holder_id: int - nullable
  • last_action_document_id: int (FK به documents) - nullable
  • developer_data: JSON - nullable
  • created_at: datetime - NOT NULL
  • updated_at: datetime - NOT NULL

آمار و توزیع داده‌ها

نوع چک (type)

  • input: 1,319 مورد (70.5%) → RECEIVED
  • output: 553 مورد (29.5%) → TRANSFERRED

وضعیت چک (status)

  • وصول نشده: 1,227 مورد (65.6%)
  • واگذار شده: 299 مورد (16.0%)
  • وصول: 298 مورد (15.9%)
  • پاس نشده: 38 مورد (2.0%)
  • پاس شده: 9 مورد (0.5%)
  • برگشت خورده: 1 مورد (0.1%)

ارز (money_id)

  • money_id = 1 (IRR): 1,812 مورد (96.8%)
  • NULL: 60 مورد (3.2%)

سایر فیلدها

  • چک‌های دارای person_id: 1,843 مورد (98.5%)
  • چک‌های بدون person_id: 29 مورد (1.5%)
  • چک‌های دارای bank_id: 307 مورد (16.4%)
  • چک‌های دارای sayad_num: 1,869 مورد (99.8%)
  • حداکثر طول sayad_num: 48 کاراکتر (باید truncate شود به 16)
  • حداکثر طول number: 34 کاراکتر (مشکلی ندارد)
  • حداکثر amount: 4,500,000,000,000 (در محدوده numeric(18,2) است)

فیلدهای boolean

  • locked = 1: 606 مورد (32.4%)
  • locked = 0: 1,266 مورد (67.6%)
  • transfered = 1: 299 مورد (16.0%)
  • transfered = NULL: 1,573 مورد (84.0%)
  • rejected = 1: 1 مورد (0.1%)
  • rejected = 0: 59 مورد (3.2%)
  • rejected = NULL: 1,812 مورد (96.8%)

تکراری بودن

  • چک‌های با number تکراری در یک کسب و کار: وجود دارد (باید مدیریت شود)
  • چک‌های با sayad_num تکراری در یک کسب و کار: وجود دارد (باید مدیریت شود)

نگاشت فیلدها

نگاشت اصلی

فیلد قدیمی فیلد جدید تبدیل
bid_id business_id نگاشت از business_id قدیمی به جدید
type type "input" → "RECEIVED", "output" → "TRANSFERRED"
person_id person_id نگاشت از person_id قدیمی به جدید
date_stamp issue_date تبدیل timestamp به datetime
pay_date due_date تبدیل string به datetime (یا از date_stamp استفاده)
number check_number مستقیم (محدود به 50 کاراکتر)
sayad_num sayad_code مستقیم (محدود به 16 کاراکتر - باید truncate شود)
bank_oncheque bank_name مستقیم
amount amount تبدیل string به numeric(18,2)
money_id currency_id نگاشت از money_id قدیمی به currency_id جدید
status status تبدیل status فارسی به ENUM انگلیسی
- branch_name NULL (اطلاعاتی در دیتابیس قدیمی نیست)
- status_at از date_submit یا date_stamp استفاده می‌شود
- current_holder_type از status و transfered محاسبه می‌شود
- current_holder_id از bank_id یا person_id استفاده می‌شود
- last_action_document_id از ref_id استفاده می‌شود (اگر document باشد)

فیلدهای حذف شده

  • submitter_id: در دیتابیس جدید وجود ندارد
  • bank_id: به current_holder_id تبدیل می‌شود (اگر current_holder_type = 'BANK')
  • ref_id: ممکن است به last_action_document_id تبدیل شود
  • des: در دیتابیس جدید وجود ندارد (می‌توان در developer_data ذخیره کرد)
  • locked: در دیتابیس جدید وجود ندارد
  • rejected: در status لحاظ می‌شود
  • transfered: در status و current_holder_type لحاظ می‌شود
  • transfer_date: در دیتابیس جدید وجود ندارد
  • date: در دیتابیس جدید وجود ندارد
  • date_submit: ممکن است به status_at تبدیل شود

تبدیل‌های پیچیده

1. تبدیل type

def convert_type(old_type: str) -> str:
    if old_type == "input":
        return "RECEIVED"
    elif old_type == "output":
        return "TRANSFERRED"
    else:
        raise ValueError(f"Unknown type: {old_type}")

2. تبدیل status

وضعیت قدیمی وضعیت جدید توضیحات
وصول نشده RECEIVED_ON_HAND چک دریافتی در دست (برای input)
وصول نشده TRANSFERRED_ISSUED چک پرداختنی صادر شده (برای output)
واگذار شده ENDORSED واگذار شده به شخص ثالث
وصول CLEARED پاس/وصول شده
پاس نشده DEPOSITED سپرده به بانک (در جریان وصول)
پاس شده CLEARED پاس/وصول شده
برگشت خورده BOUNCED برگشت خورده

نکته: تبدیل status به type چک بستگی دارد:

  • برای input (RECEIVED):
    • وصول نشده → RECEIVED_ON_HAND
    • واگذار شده → ENDORSED
    • وصول → CLEARED
    • پاس نشده → DEPOSITED
    • پاس شده → CLEARED
    • برگشت خورده → BOUNCED
  • برای output (TRANSFERRED):
    • وصول نشده → TRANSFERRED_ISSUED
    • واگذار شده → ENDORSED
    • وصول → CLEARED
    • پاس نشده → DEPOSITED
    • پاس شده → CLEARED
    • برگشت خورده → BOUNCED

3. تبدیل تاریخ‌ها

  • date_stamp: timestamp (varchar) → issue_date (datetime)
  • pay_date: string (مثل "1403/10/05") → due_date (datetime)
    • اگر pay_date معتبر نباشد، از date_stamp استفاده می‌شود
  • date_submit: timestamp (varchar) → status_at (datetime)

4. تبدیل amount

  • amount: varchar(255) → numeric(18,2)
  • باید string را به عدد تبدیل کنیم
  • حداکثر مقدار: 4,500,000,000,000 (در محدوده است)

5. تبدیل sayad_code

  • sayad_num: varchar(50) → sayad_code: varchar(16)
  • باید truncate شود به 16 کاراکتر
  • حداکثر طول در دیتابیس قدیمی: 48 کاراکتر

6. نگاشت bank_id

  • bank_id در دیتابیس قدیمی به bank_account اشاره می‌کند
  • در دیتابیس جدید، باید به bank_accounts نگاشت شود
  • اگر bank_id وجود داشت و transfered = 1، current_holder_type = 'BANK' و current_holder_id = new_bank_account_id

7. نگاشت person_id

  • person_id در دیتابیس قدیمی به person اشاره می‌کند
  • در دیتابیس جدید، باید به persons نگاشت شود
  • اگر person_id وجود داشت و transfered = 1، current_holder_type = 'PERSON' و current_holder_id = new_person_id

8. محاسبه current_holder_type و current_holder_id

def calculate_holder(old_cheque: Dict) -> Tuple[str | None, int | None]:
    if old_cheque.get('transfered') == 1:
        if old_cheque.get('bank_id'):
            return ('BANK', new_bank_account_id)
        elif old_cheque.get('person_id'):
            return ('PERSON', new_person_id)
        else:
            return ('BUSINESS', new_business_id)
    else:
        # اگر transfered نباشد، در دست کسب و کار است
        return ('BUSINESS', new_business_id)

نگاشت ارز (money_id → currency_id)

از تحلیل قبلی می‌دانیم:

  • money_id = 1 → currency_id = 1 (IRR)
  • money_id = 2 → currency_id = 2 (USD)
  • money_id = 3 → currency_id = 20 (AFN)
  • money_id = 4 → currency_id = 19 (IQD)

نکته: برای مواردی که money_id NULL است، باید از ارز پیش‌فرض کسب و کار استفاده کنیم.

چالش‌ها و راه‌حل‌ها

1. تکراری بودن check_number

  • در دیتابیس قدیمی، check_number ممکن است در یک کسب و کار تکراری باشد
  • در دیتابیس جدید، (business_id, check_number) باید unique باشد
  • راه‌حل: اگر تکراری بود، باید skip شود یا یک suffix اضافه شود

2. تکراری بودن sayad_code

  • در دیتابیس قدیمی، sayad_num ممکن است در یک کسب و کار تکراری باشد
  • در دیتابیس جدید، (business_id, sayad_code) باید unique باشد (چند NULL مجاز است)
  • راه‌حل: اگر تکراری بود، باید skip شود یا NULL شود

3. تبدیل pay_date

  • pay_date در دیتابیس قدیمی string است (مثل "1403/10/05")
  • باید به datetime تبدیل شود
  • راه‌حل: استفاده از کتابخانه تاریخ شمسی برای تبدیل

4. محدودیت sayad_code

  • sayad_num در دیتابیس قدیمی varchar(50) است
  • در دیتابیس جدید varchar(16) است
  • راه‌حل: truncate به 16 کاراکتر

5. نگاشت bank_id

  • bank_id در دیتابیس قدیمی به bank_account اشاره می‌کند
  • باید به bank_accounts جدید نگاشت شود
  • راه‌حل: ایجاد mapping بین bank_account قدیمی و جدید

6. نگاشت person_id

  • person_id در دیتابیس قدیمی به person اشاره می‌کند
  • باید به persons جدید نگاشت شود
  • راه‌حل: ایجاد mapping بین person قدیمی و جدید

7. فیلدهای حذف شده

  • submitter_id, des, locked, rejected, transfer_date, date در دیتابیس جدید وجود ندارند
  • راه‌حل:
    • des می‌تواند در developer_data ذخیره شود
    • سایر فیلدها نادیده گرفته می‌شوند

8. ref_id

  • ref_id ممکن است به document یا invoice اشاره کند
  • در دیتابیس جدید، last_action_document_id به documents اشاره می‌کند
  • راه‌حل: اگر ref_id به document اشاره می‌کند، نگاشت می‌شود، در غیر این صورت NULL می‌شود

مراحل اجرا

  1. ایجاد mapping بین business_id قدیمی و جدید
  2. ایجاد mapping بین money_id قدیمی و currency_id جدید
  3. ایجاد mapping بین person_id قدیمی و جدید
  4. ایجاد mapping بین bank_id قدیمی (bank_account) و جدید (bank_accounts)
  5. تبدیل type از "input"/"output" به "RECEIVED"/"TRANSFERRED"
  6. تبدیل status از فارسی به ENUM انگلیسی
  7. تبدیل تاریخ‌ها از timestamp/string به datetime
  8. تبدیل amount از string به numeric
  9. محاسبه current_holder_type و current_holder_id
  10. مدیریت موارد تکراری (check_number و sayad_code)
  11. انتقال چک‌ها

آمار کلی

  • چک‌ها: 1,872 رکورد
    • چک‌های دریافتی (input): 1,319 مورد (70.5%)
    • چک‌های پرداختنی (output): 553 مورد (29.5%)
  • وضعیت‌ها: 6 وضعیت مختلف
  • ارز: اکثراً IRR (96.8%)