11 KiB
Executable file
تحلیل انتقال default_currency_id از hesabixOld به hesabixpy
خلاصه اجرایی
این سند تحلیل نحوه انتقال default_currency_id از دیتابیس قدیمی (hesabixOld) به دیتابیس جدید (hesabixpy) را ارائه میدهد.
وضعیت فعلی
دیتابیس قدیمی (hesabixOld)
جدول money
- تعداد ارزها: 4 ارز
- ساختار:
id: شناسه یکتاname: نام کد ارز (مثل IRR, USD, AFN, IQD)label: نام کامل فارسیsymbol: نماد ارزshort_name: نام کوتاه
دادههای موجود:
id | name | label | symbol | short_name
1 | IRR | ریال ایران | ریال | ریال
2 | USD | دلار آمریکا | $ | دلار
3 | AFN | افغانی افغانستان | ؋ | افغانی
4 | IQD | دینار عراق | ع.د | دینار
جدول business
- فیلد:
money_id(ارجاع بهmoney.id) - توزیع استفاده:
money_id = 1(IRR): 4,420 کسب و کار (99.1%)money_id = 2(USD): 40 کسب و کار (0.9%)money_id = 3(AFN): 10 کسب و کار (0.2%)money_id = 4(IQD): 3 کسب و کار (0.07%)
- کسب و کارهای بدون money_id: 0 (همه کسب و کارها money_id دارند)
دیتابیس جدید (hesabixpy)
جدول currencies
- تعداد ارزها: 82 ارز
- ساختار:
id: شناسه یکتاname: نام کامل انگلیسیtitle: نام فارسیsymbol: نماد ارزcode: کد ارز (unique) - معادلnameدر جدول قدیمی
ارزهای مربوط به دیتابیس قدیمی:
id | name | title | symbol | code
1 | Iranian Rial | ریال ایران | ﷼ | IRR
2 | United States Dollar| US Dollar | $ | USD
20 | Afghan Afghani | Afghani | ؋ | AFN
19 | Iraqi Dinar | Iraqi Dinar | ع.د | IQD
جدول businesses
- فیلد:
default_currency_id(ارجاع بهcurrencies.id) - نوع:
Integer, ForeignKey, nullable=True
استراتژی انتقال
روش 1: Mapping بر اساس Code (پیشنهادی)
الگوریتم:
- ایجاد جدول mapping بین
money.id(قدیمی) وcurrencies.id(جدید) - Mapping بر اساس
money.name(قدیمی) =currencies.code(جدید) - استفاده از mapping برای تبدیل
business.money_id→businesses.default_currency_id
مزایا:
- دقیق و قابل اعتماد
- بر اساس استاندارد ISO currency codes
- ساده و قابل پیادهسازی
معایب:
- نیاز به ایجاد mapping table
روش 2: جستجوی مستقیم در هر انتقال
الگوریتم:
- برای هر کسب و کار،
money_idرا از دیتابیس قدیمی بخوان money.nameرا از جدولmoneyبخوان- در جدول
currenciesجستجو کن:WHERE code = money.name - اگر پیدا شد: استفاده از
currencies.id - اگر پیدا نشد: استفاده از پیشفرض (IRR)
مزایا:
- نیاز به mapping table ندارد
- ساده برای پیادهسازی
معایب:
- کندتر (query برای هر کسب و کار)
- نیاز به cache کردن نتایج
روش 3: استفاده از پیشفرض برای همه
الگوریتم:
- همه کسب و کارها را با
default_currency_id = 1(IRR) ایجاد کن
مزایا:
- بسیار ساده
- سریع
معایب:
- از دست رفتن اطلاعات (40 کسب و کار USD، 10 کسب و کار AFN، 3 کسب و کار IQD)
- نادرست برای کسب و کارهای غیر-IRR
راهحل پیشنهادی: روش 1 (Mapping Table)
پیادهسازی
1. ایجاد Currency Mapping Table
-- ایجاد جدول موقت برای mapping
CREATE TEMPORARY TABLE currency_id_mapping AS
SELECT
old_money.id as old_money_id,
new_currency.id as new_currency_id,
old_money.name as code
FROM hesabixOld.money old_money
INNER JOIN hesabixpy.currencies new_currency
ON old_money.name = new_currency.code;
نتیجه:
old_money_id | new_currency_id | code
1 | 1 | IRR
2 | 2 | USD
3 | 20 | AFN
4 | 19 | IQD
2. استفاده در انتقال کسب و کار
def get_default_currency_id(old_money_id: int, currency_mapping: Dict[int, int]) -> int | None:
"""
تبدیل money_id قدیمی به default_currency_id جدید
Args:
old_money_id: شناسه money در دیتابیس قدیمی
currency_mapping: دیکشنری mapping {old_money_id: new_currency_id}
Returns:
شناسه currency در دیتابیس جدید یا None
"""
if not old_money_id:
return None
new_currency_id = currency_mapping.get(old_money_id)
if new_currency_id:
return new_currency_id
# اگر پیدا نشد، از پیشفرض IRR استفاده کن
# جستجو برای IRR در دیتابیس جدید
return get_irr_currency_id() # معمولاً 1
3. مدیریت موارد خاص
سناریو 1: money_id پیدا نشد در mapping
- عمل: استفاده از پیشفرض IRR (currency_id = 1)
- لاگ: ثبت در لاگ برای بررسی
سناریو 2: currency در دیتابیس جدید وجود ندارد
- عمل: استفاده از پیشفرض IRR
- لاگ: ثبت در لاگ با هشدار
سناریو 3: money_id = NULL
- عمل:
default_currency_id = NULLیا پیشفرض IRR - توجه: در دیتابیس قدیمی همه کسب و کارها money_id دارند، پس این حالت نادر است
کد نمونه
def create_currency_mapping(db_old, db_new) -> Dict[int, int]:
"""
ایجاد mapping بین money قدیمی و currencies جدید
"""
# Query برای ایجاد mapping
query = """
SELECT
old_money.id as old_money_id,
new_currency.id as new_currency_id
FROM hesabixOld.money old_money
INNER JOIN hesabixpy.currencies new_currency
ON old_money.name = new_currency.code
"""
results = db_old.execute(text(query)).fetchall()
mapping = {}
for row in results:
mapping[row.old_money_id] = row.new_currency_id
return mapping
def get_default_currency_id_for_business(
old_money_id: int | None,
currency_mapping: Dict[int, int],
default_irr_id: int = 1
) -> int | None:
"""
تبدیل money_id قدیمی به default_currency_id جدید
"""
if not old_money_id:
return default_irr_id # یا None بسته به نیاز
return currency_mapping.get(old_money_id, default_irr_id)
آمار و ارقام
توزیع استفاده از ارزها
| ارز | تعداد کسب و کار | درصد |
|---|---|---|
| IRR | 4,420 | 99.1% |
| USD | 40 | 0.9% |
| AFN | 10 | 0.2% |
| IQD | 3 | 0.07% |
| کل | 4,473 | 100% |
Mapping Table
| old_money_id | old_code | new_currency_id | new_code | تطابق |
|---|---|---|---|---|
| 1 | IRR | 1 | IRR | ✅ |
| 2 | USD | 2 | USD | ✅ |
| 3 | AFN | 20 | AFN | ✅ |
| 4 | IQD | 19 | IQD | ✅ |
نتیجه: همه 4 ارز قدیمی در دیتابیس جدید وجود دارند و میتوانند به درستی mapping شوند.
نکته مهم: به دلیل تفاوت collation بین دو دیتابیس، باید از BINARY یا COLLATE در query استفاده کرد:
-- روش صحیح برای mapping
SELECT old_money.id, new_currency.id
FROM hesabixOld.money old_money
INNER JOIN hesabixpy.currencies new_currency
ON BINARY old_money.name = BINARY new_currency.code;
مراحل اجرا
مرحله 1: ایجاد Currency Mapping
# در اسکریپت انتقال کسب و کارها
currency_mapping = create_currency_mapping(old_db, new_db)
# نتیجه: {1: 1, 2: 2, 3: 20, 4: 19}
مرحله 2: استفاده در انتقال
# برای هر کسب و کار
old_money_id = old_business.get('money_id')
default_currency_id = get_default_currency_id_for_business(
old_money_id,
currency_mapping,
default_irr_id=1
)
# درج در دیتابیس جدید
business_data = {
# ... سایر فیلدها ...
'default_currency_id': default_currency_id
}
مرحله 3: اعتبارسنجی
-- بررسی تعداد کسب و کارها با هر ارز
SELECT
c.code,
c.name,
COUNT(b.id) as business_count
FROM hesabixpy.businesses b
INNER JOIN hesabixpy.currencies c ON b.default_currency_id = c.id
GROUP BY c.id, c.code, c.name
ORDER BY business_count DESC;
انتظار:
- IRR: ~4,420 کسب و کار
- USD: ~40 کسب و کار
- AFN: ~10 کسب و کار
- IQD: ~3 کسب و کار
نکات مهم
- همه کسب و کارها money_id دارند: هیچ کسب و کاری بدون money_id نیست
- همه ارزهای قدیمی در جدید وجود دارند: همه 4 ارز میتوانند mapping شوند
- IRR پیشفرض است: در صورت عدم تطابق، از IRR استفاده میشود
- Mapping بر اساس Code: استفاده از
money.name=currencies.codeبرای mapping
ریسکها و راهحلها
ریسک 1: Currency در دیتابیس جدید وجود ندارد
احتمال: بسیار کم (همه 4 ارز موجود هستند) راهحل: استفاده از پیشفرض IRR و ثبت در لاگ
ریسک 2: Mapping نادرست
احتمال: بسیار کم (بر اساس ISO code) راهحل: اعتبارسنجی بعد از انتقال
ریسک 3: Performance
احتمال: کم (فقط 4 ارز) راهحل: استفاده از mapping table در memory
نتیجهگیری
روش پیشنهادی: استفاده از Mapping Table بر اساس Code
دلایل:
- ✅ دقیق و قابل اعتماد
- ✅ همه ارزهای قدیمی در جدید وجود دارند
- ✅ ساده برای پیادهسازی
- ✅ قابل اعتبارسنجی
پیادهسازی:
- ایجاد
currency_id_mappingدر ابتدای اسکریپت انتقال - استفاده از mapping در انتقال هر کسب و کار
- استفاده از IRR به عنوان پیشفرض در صورت عدم تطابق
انتظار:
- 4,420 کسب و کار با IRR
- 40 کسب و کار با USD
- 10 کسب و کار با AFN
- 3 کسب و کار با IQD