Files
modstagram-back/utils/walletSplit.js
payacom fade8543e2 e2ee
2026-10-02 18:13:34 +03:30

67 lines
3.9 KiB
JavaScript

const WalletTransactionModel = require('../models/WalletTransactionModel')
const { getBucketBalance } = require('../controllers/application/wallet/walletController')
/**
* وقتی کاربر موقع خرید تیکِ «استفاده از موجودی کیف پول» رو می‌زنه (useWallet=true)،
* تا هر مقدار که سبدِ «charged» (شارژِ دستیِ کیف پول، همون چیزی که کاربر خودش واریز
* کرده — نه سبدهای درآمدیِ shop/academy/project/booking) پوشش بده از همونجا کسر
* می‌شه و فقط باقی‌مونده (اگه چیزی مونده باشه) از درگاه زرین‌پال گرفته می‌شه. اگه
* useWallet نباشه یا موجودی صفر باشه، دقیقاً مثلِ قبل کاملش از درگاه پرداخت می‌شه.
*
* عمداً همینجا چیزی کسر نمی‌کنه (فقط محاسبه) — کسرِ واقعی رو خودِ فراخوان، فقط لحظه‌ای
* که پرداخت قطعاً موفق شده (یا کلاً از درگاه رد نشده، یعنی fullyCovered) صدا می‌زنه؛
* این‌طوری اگه کاربر پرداختِ درگاه رو نصفه ول کنه، هیچ مبلغی از کیف پول کم نشده که
* لازم باشه برگردونده بشه
*/
// زرین‌پال حداقل مبلغِ درگاه رو ۱۵٬۰۰۰ ریال (۱٬۵۰۰ تومان) می‌خواد — اگه بعدِ کسرِ
// کیف‌پول فقط یه باقی‌مونده‌ی مثبتِ کوچیک‌تر از این بمونه، کلِ درخواستِ initiate به
// زرین‌پال با خطای 422 رد می‌شه (نه فقط همون بخشِ کوچیک) — این دقیقاً همون چیزی بود
// که باعث می‌شد «ثبت درخواست» (و هر مسیرِ دیگه‌ای که از این تابع استفاده می‌کنه) با
// بعضی ترکیب‌های قیمت/موجودیِ کیف‌پول روی سرور ارور بده
const ZARINPAL_MIN_GATEWAY_TOMAN = 1500
async function resolveWalletSplit (userId, amount, useWallet) {
if (!useWallet) {
return { walletAmount: 0, gatewayAmount: amount, fullyCovered: false }
}
const balance = await getBucketBalance(userId, 'charged')
if (!balance || balance <= 0) {
return { walletAmount: 0, gatewayAmount: amount, fullyCovered: false }
}
let walletAmount = Math.min(balance, amount)
let gatewayAmount = amount - walletAmount
if (gatewayAmount > 0 && gatewayAmount < ZARINPAL_MIN_GATEWAY_TOMAN) {
const neededWalletAmount = amount - ZARINPAL_MIN_GATEWAY_TOMAN
if (neededWalletAmount >= 0 && balance >= neededWalletAmount) {
// از کیف‌پول کمتر استفاده کن تا باقی‌مونده دقیقاً به حداقلِ مجازِ درگاه برسه
walletAmount = neededWalletAmount
gatewayAmount = ZARINPAL_MIN_GATEWAY_TOMAN
} else {
// یا کلِ مبلغ از حداقلِ درگاه کمتره، یا کیف‌پول برای رسوندنِ باقی‌مونده به اون
// حداقل کافی نیست — اصلاً از کیف‌پول استفاده نکن، همه چیز از درگاه. این‌طوری
// حداقل یه خطای واضحِ «حداقل مبلغ» از خودِ زرین‌پال می‌گیریم، نه یه 422ِ گنگ
walletAmount = 0
gatewayAmount = amount
}
}
return { walletAmount, gatewayAmount, fullyCovered: gatewayAmount <= 0 }
}
async function debitWalletForPurchase (userId, walletAmount, { referenceType, referenceId, description }) {
if (!walletAmount || walletAmount <= 0) return
await WalletTransactionModel.create({
user: userId,
bucket: 'charged',
type: 'debit',
amount: walletAmount,
referenceType,
referenceId,
description
})
}
module.exports = { resolveWalletSplit, debitWalletForPurchase }