feat: internationalize API error responses by locale
Add shared error codes with zh/en/ms messages, coded app exceptions, and locale-aware global filter. Frontends send X-Locale so error text matches the active UI language. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Injectable, BadRequestException } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { appBadRequest } from '../../shared/common/app-error';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../../shared/prisma/prisma.service';
|
||||
import { Decimal } from '@prisma/client/runtime/library';
|
||||
@@ -12,7 +13,7 @@ export class WalletService {
|
||||
|
||||
async getWallet(userId: bigint) {
|
||||
const wallet = await this.prisma.wallet.findUnique({ where: { userId } });
|
||||
if (!wallet) throw new BadRequestException('Wallet not found');
|
||||
if (!wallet) throw appBadRequest('WALLET_NOT_FOUND');
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@@ -26,7 +27,7 @@ export class WalletService {
|
||||
const wallets = await tx.$queryRaw<Array<{ id: bigint; available_balance: Decimal; frozen_balance: Decimal; version: number }>>`
|
||||
SELECT id, available_balance, frozen_balance, version FROM wallets WHERE user_id = ${userId} FOR UPDATE
|
||||
`;
|
||||
if (!wallets.length) throw new BadRequestException('Wallet not found');
|
||||
if (!wallets.length) throw appBadRequest('WALLET_NOT_FOUND');
|
||||
return wallets[0];
|
||||
}
|
||||
|
||||
@@ -39,7 +40,7 @@ export class WalletService {
|
||||
transactionType = 'MANUAL_DEPOSIT',
|
||||
) {
|
||||
const amt = new Decimal(amount);
|
||||
if (amt.lte(0)) throw new BadRequestException('Amount must be positive');
|
||||
if (amt.lte(0)) throw appBadRequest('AMOUNT_MUST_BE_POSITIVE');
|
||||
|
||||
return this.prisma.$transaction(async (tx) => {
|
||||
const w = await this.lockWallet(tx, userId);
|
||||
@@ -84,12 +85,12 @@ export class WalletService {
|
||||
referenceId?: string,
|
||||
) {
|
||||
const amt = new Decimal(amount);
|
||||
if (amt.lte(0)) throw new BadRequestException('Amount must be positive');
|
||||
if (amt.lte(0)) throw appBadRequest('AMOUNT_MUST_BE_POSITIVE');
|
||||
|
||||
return this.prisma.$transaction(async (tx) => {
|
||||
const w = await this.lockWallet(tx, userId);
|
||||
const balanceBefore = new Decimal(w.available_balance);
|
||||
if (balanceBefore.lt(amt)) throw new BadRequestException('Insufficient balance');
|
||||
if (balanceBefore.lt(amt)) throw appBadRequest('INSUFFICIENT_BALANCE');
|
||||
const balanceAfter = balanceBefore.sub(amt);
|
||||
|
||||
await tx.wallet.update({
|
||||
@@ -128,7 +129,7 @@ export class WalletService {
|
||||
return this.prisma.$transaction(async (tx) => {
|
||||
const w = await this.lockWallet(tx, userId);
|
||||
const avail = new Decimal(w.available_balance);
|
||||
if (avail.lt(amt)) throw new BadRequestException('Insufficient balance');
|
||||
if (avail.lt(amt)) throw appBadRequest('INSUFFICIENT_BALANCE');
|
||||
|
||||
const balanceAfter = avail.sub(amt);
|
||||
const frozenAfter = new Decimal(w.frozen_balance).add(amt);
|
||||
|
||||
Reference in New Issue
Block a user