67 lines
3.9 KiB
JavaScript
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 }
|