Files
clinicpro/.claude/prompt/currency-toman-display-admin.md
T

8.1 KiB

واحد پول = تومان در پنل ادمین (نمایش ÷۱۰ / ورودی ×۱۰) — ذخیره و درگاه ریال می‌ماند

پروژه

clinicpro (admin frontend — React). cross-repo: پرامپت همتا برای سایت عمومی: nobat724_front/.claude/prompt/currency-toman-display-front.md.

زمینه

واحد پول در نمایشِ کل محصول باید تومان باشد، ولی طبق تصمیم:

  • ذخیره‌سازی DB و API و ارسال به درگاه پرداخت همچنان ریال می‌ماند (بدون migration، نام ستون/فیلدهای *_rials ثابت). درگاه ملت ریال می‌خواهد و مقدارِ ذخیره‌شده درست است.
  • فقط لایهٔ نمایش مقدار ریال را ÷۱۰ کرده و با برچسب «تومان» نشان دهد، و فرم‌های ورودیِ پول مقدارِ تومانِ واردشده را ×۱۰ کرده و به‌صورت ریال ذخیره کنند.

الان ناهماهنگ است: formatRial عددِ ریال را می‌گیرد ولی برچسب «تومان» می‌چسباند (پس ۱۰ برابر نشان می‌دهد)، و فرم‌های قیمت با برچسب «(ریال)» مقدار را مستقیم ریال ذخیره می‌کنند.

مشکل / هدف

در پنل ادمین، همهٔ مبالغ به تومان نمایش داده و دریافت شوند؛ تبدیل تومان↔ریال فقط در لایهٔ UI (نمایش/فرم) انجام شود. DB/API/درگاه تغییری نکنند.

فایل‌های مرتبط

فایل نقش
clinicpro/assets/admin/lib/utils.ts helper مرکزی تبدیل + formatRial (نمایش تومان)
clinicpro/assets/admin/lib/utils.test.ts به‌روزرسانی انتظار تست
clinicpro/assets/admin/pages/SettingsPage.tsx ۳ ورودی قیمت (appointment_fee/sms_panel_fee/sms_price) تومان
clinicpro/assets/admin/components/FreeVisitPrice.tsx ورودی قیمت تومان
clinicpro/assets/admin/components/ServiceTariffModal.tsx ورودی تعرفه تومان
clinicpro/assets/admin/components/TenantInsuranceContracts.tsx ورودی فرانشیز/سقف تعهد تومان
clinicpro/assets/admin/pages/SmsWalletPage.tsx مبلغ شارژ (ورودی) + نمایش قیمت هر پیامک
(در صورت وجود) صفحهٔ تسویه/برداشت که amount_rials ورودی می‌گیرد ورودی مبلغ تومان

نمایش‌های دیگر (Payments، Subscription، RepresentationFinance، Dashboard و…) از formatRial استفاده می‌کنند؛ با اصلاح مرکزی خودکار تومان می‌شوند (۲۲ مصرف formatRial).

وضعیت فعلی

lib/utils.ts

export function formatRial(amount: number): string {
  return new Intl.NumberFormat('fa-IR').format(amount) + ' تومان';
}

عدد ریال را بدون تبدیل، با برچسب «تومان» نشان می‌دهد → ۱۰ برابر.

SettingsPage.tsx (ورودی‌ها ریال ذخیره می‌شوند)

appointment_fee_rials: s.appointment_fee_rials ?? '150000',
sms_panel_fee_rials:   s.sms_panel_fee_rials ?? '1500000',
sms_price_rials:       s.sms_price_rials ?? '500',
// ...
<input {...register('appointment_fee_rials')} ... placeholder="150000" />

مقدار مستقیم به‌صورت ریال در site_config PATCH می‌شود.

نمونهٔ نمایش (Subscription)

{formatRial(period.price_rials)}   // price_rials ریال است

وظایف

۱. helperهای تبدیل + اصلاح formatRial (utils.ts)

export const RIAL_PER_TOMAN = 10;
export const rialToToman = (rial: number): number => Math.round((Number(rial) || 0) / RIAL_PER_TOMAN);
export const tomanToRial = (toman: number): number => Math.round((Number(toman) || 0) * RIAL_PER_TOMAN);

// ورودی همچنان «مقدار ریال» است (سازگاری با ۲۲ فراخوانی)، ولی خروجی به تومان نمایش داده می‌شود.
export function formatRial(rial: number): string {
  return new Intl.NumberFormat('fa-IR').format(rialToToman(rial)) + ' تومان';
}

نام formatRial را برای سازگاری با تمام مصرف‌کننده‌ها نگه دار (فقط رفتارش تومان‌نمایش می‌شود). اگر خواستی برای خوانایی formatToman را هم به‌عنوان alias صادر کن.

۲. فرم‌های ورودی پول — تومان بگیر، ریال ذخیره کن

الگوی کلی: مقدار ذخیره‌شده (ریال) را با rialToToman در فرم نشان بده؛ هنگام submit با tomanToRial به ریال تبدیل کن؛ برچسب واحد را «تومان» کن.

SettingsPage.tsx:

  • defaultValues: appointment_fee_rials: String(rialToToman(Number(s.appointment_fee_rials ?? 1500000))) و مشابه برای sms_panel_fee_rials، sms_price_rials (پیش‌فرض‌ها را هم به تومان تبدیل کن: مثلاً 150000 ریال → نمایش 15000).
  • هنگام ذخیره (onSubmit/PATCH): این سه فیلد را tomanToRial(...) کن و سپس بفرست، تا site_config همچنان ریال بگیرد.
  • placeholder/برچسب‌ها را از ریال به تومان به‌روز کن (مثلاً placeholder «15000»).

FreeVisitPrice.tsx / ServiceTariffModal.tsx / TenantInsuranceContracts.tsx:

  • برچسب‌های «قیمت (ریال)»، «تعرفه (ریال)»، «فرانشیز (ریال)»، «سقف تعهد (ریال)» → «(تومان)».
  • مقدار پیش‌فرضِ فرم = rialToToman(storedRial)؛ هنگام ذخیره = tomanToRial(inputToman) قبل از ارسال به API.

SmsWalletPage.tsx:

  • مبلغ شارژ که کاربر وارد می‌کند = تومان → قبل از ارسال tomanToRial.
  • نمایش «قیمت هر پیامک» و موجودی کیف‌پول از formatRial استفاده کند (خودکار تومان).

صفحهٔ تسویه/برداشت (اگر amount_rials را از ورودی می‌گیرد): مقدار تومانِ واردشده را tomanToRial کن و بفرست؛ نمایش موجودی/سقف با formatRial.

۳. برچسب‌های ثابت «ریال» در JSX

هر جای UI که رشتهٔ «ریال» به‌صورت ثابت کنار عدد آمده (نه از طریق formatRial) به «تومان» تغییر کند و عددش اگر خام ریال است با rialToToman تبدیل شود. (با grep -rn "ریال" assets/admin پیدا کن.)

۴. تست

lib/utils.test.ts: انتظار formatRial را به تومان به‌روز کن (مثلاً ورودی 150000 ریال → خروجی شامل 15,000 و «تومان»).

نکات مهم

  • DB/API/درگاه دست نخورد: هیچ کلید *_rials، هیچ endpoint، و MellatGateway/PaymentManager تغییر نمی‌کند. مقدارِ رفته به درگاه همان ریالِ ذخیره‌شده است (درست).
  • تبدیل فقط در مرز UI: نمایش rialToToman، ورودی tomanToRial. هیچ مقدارِ تبدیل‌شده‌ای نباید در API/DB ذخیره شود مگر بعد از tomanToRial (که دوباره ریال است).
  • گرد کردن: قیمت‌ها مضرب ۱۰ ریال‌اند؛ Math.round امن است. اگر مقداری مضرب ۱۰ نبود، تومانِ گردشده نمایش داده می‌شود (پذیرفتنی).
  • دوباره‌تبدیل نشود: مراقب باش جایی که قبلاً formatRial اعمال شده دوباره ÷۱۰ نکنی (double convert).
  • تست‌ها: ddev exec npx tsc --noEmit، ddev exec yarn dev بدون خطا؛ سپس چشمی: Settings (قیمت‌ها تومان و ذخیره درست)، Payments/Subscription/Dashboard (اعداد ۱۰ برابر کوچک‌تر از قبل و برچسب تومان).
  • backend docs تغییری ندارد (واحد API ریال می‌ماند).