update calculate user balance

This commit is contained in:
NW
2025-01-09 20:07:44 +00:00
parent f9356c6bbe
commit dd18e74529
5 changed files with 140 additions and 61 deletions

View File

@@ -2,6 +2,8 @@
import db from "../config/database.js";
import CryptoJS from "crypto-js"; // Импортируем библиотеку crypto-js
import UserService from "../services/userService.js";
class PurchaseService {
static async getPurchasesByUserId(userId, limit, offset) {
try {
@@ -42,16 +44,62 @@ class PurchaseService {
static async createPurchase(userId, productId, walletType, quantity, totalPrice) {
try {
const user = await UserService.getUserByUserId(userId);
if (!user) {
throw new Error('User not found');
}
// Обновляем крипто-баланс пользователя перед началом покупки
await UserService.recalculateUserBalanceByTelegramId(user.telegram_id);
let remainingAmount = totalPrice;
let usedBonus = 0;
let usedCrypto = 0;
let sourceWalletType = '';
// Сначала списываем с бонусного баланса
if (user.bonus_balance > 0) {
usedBonus = Math.min(user.bonus_balance, remainingAmount);
remainingAmount -= usedBonus;
// Обновляем бонусный баланс пользователя
await db.runAsync(
'UPDATE users SET bonus_balance = bonus_balance - ? WHERE id = ?',
[usedBonus, userId]
);
// Добавляем информацию о списании с бонусного баланса
sourceWalletType += `bonus_${usedBonus}`;
}
// Если осталась сумма, списываем с крипто-баланса
if (remainingAmount > 0) {
usedCrypto = remainingAmount;
// Обновляем крипто-баланс пользователя
await db.runAsync(
'UPDATE users SET total_balance = total_balance - ? WHERE id = ?',
[usedCrypto, userId]
);
// Добавляем информацию о списании с крипто-баланса
if (sourceWalletType) {
sourceWalletType += `, crypto_${usedCrypto}`;
} else {
sourceWalletType = `crypto_${usedCrypto}`;
}
}
// Генерируем MD5-хеш для tx_hash
const txHash = CryptoJS.MD5(Date.now().toString()).toString();
// Вставка новой покупки в базу данных
// Вставляем новую покупку в базу данных
const result = await db.runAsync(
`INSERT INTO purchases (user_id, product_id, wallet_type, quantity, total_price, purchase_date, tx_hash)
VALUES (?, ?, ?, ?, ?, ?, ?)`,
[userId, productId, walletType, quantity, totalPrice, new Date().toISOString(), txHash]
[userId, productId, sourceWalletType, quantity, totalPrice, new Date().toISOString(), txHash]
);
// Возвращаем ID новой покупки
return result.lastID;
} catch (error) {
@@ -62,6 +110,29 @@ class PurchaseService {
static async updatePurchaseStatus(purchaseId, status) {
try {
const purchase = await this.getPurchaseById(purchaseId);
if (!purchase) {
throw new Error('Purchase not found');
}
if (status === 'canceled') {
const user = await UserService.getUserByUserId(purchase.user_id);
// Возвращаем средства на бонусный или крипто-баланс
if (purchase.wallet_type === 'bonus') {
await db.runAsync(
'UPDATE users SET bonus_balance = bonus_balance + ? WHERE id = ?',
[purchase.total_price, user.id]
);
} else {
await db.runAsync(
'UPDATE users SET total_balance = total_balance + ? WHERE id = ?',
[purchase.total_price, user.id]
);
}
}
// Обновляем статус покупки
await db.runAsync(
'UPDATE purchases SET status = ? WHERE id = ?',
[status, purchaseId]

View File

@@ -1,5 +1,9 @@
// userService.js
import db from "../config/database.js";
import Wallet from "../models/Wallet.js";
import WalletUtils from "../utils/walletUtils.js";
class UserService {
// Функция для нормализации telegram_id
@@ -119,22 +123,50 @@ class UserService {
static async recalculateUserBalanceByTelegramId(telegramId) {
const normalizedTelegramId = this.normalizeTelegramId(telegramId);
const user = await this.getUserByTelegramId(normalizedTelegramId);
if (!user) {
return;
}
const archivedBalance = await Wallet.getArchivedWalletsBalance(user.id);
const activeBalance = await Wallet.getActiveWalletsBalance(user.id);
const purchases = await db.getAsync(
`SELECT SUM(total_price) as total_sum FROM purchases WHERE user_id = ?`,
[user.id]
);
const userTotalBalance = (activeBalance + archivedBalance) - (purchases?.total_sum || 0);
await db.runAsync(`UPDATE users SET total_balance = ? WHERE id = ?`, [userTotalBalance, user.id]);
try {
// Получаем все крипто-балансы пользователя
const cryptoBalances = await db.allAsync(
`SELECT wallet_type, balance FROM crypto_wallets WHERE user_id = ?`,
[user.id]
);
// Получаем актуальные курсы криптовалют
const prices = await WalletUtils.getCryptoPrices();
// Пересчитываем балансы в доллары
let totalCryptoBalance = 0;
for (const wallet of cryptoBalances) {
const baseType = WalletUtils.getBaseWalletType(wallet.wallet_type); // Убираем суффиксы
const rate = prices[baseType.toLowerCase()] || 0; // Получаем курс для базового типа
totalCryptoBalance += wallet.balance * rate;
}
// Получаем сумму всех покупок в крипте
const cryptoPurchases = await db.getAsync(
`SELECT SUM(total_price) as total_sum FROM purchases
WHERE user_id = ? AND wallet_type LIKE 'crypto%'`,
[user.id]
);
// Вычитаем сумму покупок из общего крипто-баланса
const remainingBalance = totalCryptoBalance - (cryptoPurchases?.total_sum || 0);
// Обновляем поле total_balance в таблице users
await db.runAsync(
`UPDATE users SET total_balance = ? WHERE id = ?`,
[remainingBalance, user.id]
);
console.log(`[DEBUG] Updated total_balance for user ${user.id}: ${remainingBalance}`);
} catch (error) {
console.error('Error recalculating user balance:', error);
throw error;
}
}
static async updateUserLocation(telegramId, country, city, district) {
@@ -164,28 +196,13 @@ class UserService {
static async getUserBalance(userId) {
try {
// Пересчитываем баланс перед получением
const user = await this.getUserByUserId(userId);
if (!user) {
throw new Error('User not found');
}
await this.recalculateUserBalanceByTelegramId(user.telegram_id);
// Получаем обновленный баланс
const updatedUser = await db.getAsync(
`SELECT total_balance, bonus_balance
FROM users
WHERE id = ?`,
[userId]
);
if (!updatedUser) {
throw new Error('User not found');
}
// Возвращаем сумму основного и бонусного баланса
return updatedUser.total_balance + updatedUser.bonus_balance;
// Возвращаем сумму доступного крипто-баланса и бонусного баланса
return user.total_balance + user.bonus_balance;
} catch (error) {
console.error('Error getting user balance:', error);
throw error;