WIP: Fix currency synchronization and add real-time validation #2741

Closed
Infity95 wants to merge 1 commits from Infity95:fix-currency-sync-rebased into main
3 changed files with 39 additions and 10 deletions

View File

@ -6,12 +6,28 @@ import { getInventory } from "../../services/inventoryService.ts";
import { sendWsBroadcastTo } from "../../services/wsService.ts"; import { sendWsBroadcastTo } from "../../services/wsService.ts";
export const purchaseController: RequestHandler = async (req, res) => { export const purchaseController: RequestHandler = async (req, res) => {
try {
const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest; const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
const response = await handlePurchase(purchaseRequest, inventory); const response = await handlePurchase(purchaseRequest, inventory);
await inventory.save(); await inventory.save();
//console.log(JSON.stringify(response, null, 2));
res.json(response); res.json(response);
sendWsBroadcastTo(accountId, { update_inventory: true }); sendWsBroadcastTo(accountId, { update_inventory: true });
} catch (error) {
if (error instanceof Error && error.message.includes('Insufficient')) {
res.status(400).json({
error: 'INSUFFICIENT_CURRENCY',
message: error.message
});
} else {
console.error('Purchase failed:', error);
res.status(500).json({
error: 'PURCHASE_FAILED',
message: 'An error occurred during purchase'
});
}
}
}; };

View File

@ -1254,10 +1254,18 @@ export const updateCurrency = (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
price: number, price: number,
usePremium: boolean, usePremium: boolean,
inventoryChanges: IInventoryChanges = {} inventoryChanges: IInventoryChanges = {},
validateBalance: boolean = false
): IInventoryChanges => { ): IInventoryChanges => {
if (price != 0 && isCurrencyTracked(inventory, usePremium)) { if (price != 0 && isCurrencyTracked(inventory, usePremium)) {
if (usePremium) { if (usePremium) {
if (validateBalance) {
const totalPlatinum = inventory.PremiumCredits + inventory.PremiumCreditsFree;
if (totalPlatinum < price) {
throw new Error(`Insufficient platinum balance. Required: ${price}, Available: ${totalPlatinum}`);
}
}
if (inventory.PremiumCreditsFree > 0) { if (inventory.PremiumCreditsFree > 0) {
const premiumCreditsFreeDelta = Math.min(price, inventory.PremiumCreditsFree) * -1; const premiumCreditsFreeDelta = Math.min(price, inventory.PremiumCreditsFree) * -1;
inventoryChanges.PremiumCreditsFree ??= 0; inventoryChanges.PremiumCreditsFree ??= 0;
@ -1269,6 +1277,10 @@ export const updateCurrency = (
inventory.PremiumCredits -= price; inventory.PremiumCredits -= price;
logger.debug(`currency changes `, { PremiumCredits: -price }); logger.debug(`currency changes `, { PremiumCredits: -price });
} else { } else {
if (validateBalance && inventory.RegularCredits < price) {
throw new Error(`Insufficient credits balance. Required: ${price}, Available: ${inventory.RegularCredits}`);
}
inventoryChanges.RegularCredits ??= 0; inventoryChanges.RegularCredits ??= 0;
inventoryChanges.RegularCredits -= price; inventoryChanges.RegularCredits -= price;
inventory.RegularCredits -= price; inventory.RegularCredits -= price;

View File

@ -209,7 +209,8 @@ export const handlePurchase = async (
inventory, inventory,
purchaseRequest.PurchaseParams.ExpectedPrice, purchaseRequest.PurchaseParams.ExpectedPrice,
purchaseRequest.PurchaseParams.UsePremium, purchaseRequest.PurchaseParams.UsePremium,
prePurchaseInventoryChanges prePurchaseInventoryChanges,
true
); );
switch (purchaseRequest.PurchaseParams.Source) { switch (purchaseRequest.PurchaseParams.Source) {