feat(theme-2): sync inbox/announcements/presence/deposit from main

This commit is contained in:
2026-06-18 09:38:33 +08:00
parent ec51b675e3
commit e56029225e
86 changed files with 6828 additions and 928 deletions

View File

@@ -2,9 +2,11 @@ import { Module } from '@nestjs/common';
import { DepositService } from './deposit.service';
import { WalletModule } from '../ledger/wallet.module';
import { AgentsModule } from '../agent/agents.module';
import { PlayerMessagesModule } from '../player-messages/player-messages.module';
import { SystemConfigModule } from '../../shared/config/system-config.module';
@Module({
imports: [WalletModule, AgentsModule],
imports: [WalletModule, AgentsModule, PlayerMessagesModule, SystemConfigModule],
providers: [DepositService],
exports: [DepositService],
})

View File

@@ -19,6 +19,7 @@ describe('DepositService', () => {
},
user: {
findFirst: jest.fn(),
findUnique: jest.fn(),
},
agentProfile: {
findUnique: jest.fn(),
@@ -38,12 +39,28 @@ describe('DepositService', () => {
const credit = {
recalculateUsedCredit: jest.fn(),
};
const playerMessages = {
createDepositApprovedMessage: jest.fn(),
createDepositRejectedMessage: jest.fn(),
};
const systemConfig = {
getInboxNotifySettings: jest.fn().mockResolvedValue({
inboxEnabled: true,
deposit: true,
}),
};
let service: DepositService;
beforeEach(() => {
jest.clearAllMocks();
service = new DepositService(prisma as never, funds as never, credit as never);
service = new DepositService(
prisma as never,
funds as never,
credit as never,
playerMessages as never,
systemConfig as never,
);
tx.$queryRaw.mockResolvedValue([{ id: 1n }]);
tx.depositOrder.findUnique.mockResolvedValue({
id: 1n,
@@ -57,8 +74,11 @@ describe('DepositService', () => {
});
tx.bet.findMany.mockResolvedValue([]);
tx.user.findFirst.mockResolvedValue(null);
tx.user.findUnique.mockResolvedValue({ locale: 'en-US' });
tx.agentProfile.findUnique.mockResolvedValue(null);
credit.recalculateUsedCredit.mockResolvedValue(undefined);
playerMessages.createDepositApprovedMessage.mockResolvedValue({});
playerMessages.createDepositRejectedMessage.mockResolvedValue({});
});
it('posts approved deposits as player wallet transactions and refreshes parent credit', async () => {
@@ -131,7 +151,7 @@ describe('DepositService', () => {
});
it('uses approval cycle key when revoking a funded deposit for re-review', async () => {
const reviewedAt = new Date('2026-06-15T14:08:48.000Z');
const reviewedAt = new Date();
tx.depositOrder.findUnique.mockResolvedValue({
id: 1n,
orderNo: 'DEP-1',

View File

@@ -7,6 +7,8 @@ import { FundsPostingService } from '../ledger/funds-posting.service';
import { AgentCreditService } from '../agent/agent-credit.service';
import { appBadRequest } from '../../shared/common/app-error';
import { deleteUploadFileByUrl } from '../../shared/uploads/delete-upload-file';
import { PlayerMessagesService } from '../player-messages/player-messages.service';
import { SystemConfigService } from '../../shared/config/system-config.service';
function generateOrderNo(): string {
const ts = Date.now().toString(36).toUpperCase();
@@ -49,6 +51,8 @@ export class DepositService {
private prisma: PrismaService,
private funds: FundsPostingService,
private credit: AgentCreditService,
private playerMessages: PlayerMessagesService,
private systemConfig: SystemConfigService,
) {}
// ============ Payment Methods (Admin CRUD) ============
@@ -254,6 +258,14 @@ export class DepositService {
// ============ Deposit Orders ============
private async getPlayerLocale(playerId: bigint, tx: Prisma.TransactionClient | PrismaService = this.prisma) {
const user = await tx.user.findUnique({
where: { id: playerId },
select: { locale: true },
});
return user?.locale ?? 'en-US';
}
private async recordDepositAudit(
client: AuditLogWriter,
data: {
@@ -670,6 +682,10 @@ export class DepositService {
};
}
async countPendingDepositOrders(): Promise<number> {
return this.prisma.depositOrder.count({ where: { status: 'PENDING' } });
}
async approveDepositOrder(
orderId: bigint,
operatorId: bigint,
@@ -722,6 +738,22 @@ export class DepositService {
await this.credit.recalculateUsedCredit(parentAgentId, tx);
}
const playerLocale = await this.getPlayerLocale(order.playerId, tx);
const inboxNotify = await this.systemConfig.getInboxNotifySettings();
if (inboxNotify.inboxEnabled && inboxNotify.deposit) {
await this.playerMessages.createDepositApprovedMessage(
order.playerId,
{
depositOrderId: orderId,
orderNo: order.orderNo,
amount: order.amount.toString(),
approvedAmount: creditAmount.toString(),
locale: playerLocale,
},
tx,
);
}
return { success: true };
});
}
@@ -753,6 +785,18 @@ export class DepositService {
remark: reason,
});
const playerLocale = await this.getPlayerLocale(order.playerId);
const inboxNotify = await this.systemConfig.getInboxNotifySettings();
if (inboxNotify.inboxEnabled && inboxNotify.deposit) {
await this.playerMessages.createDepositRejectedMessage(order.playerId, {
depositOrderId: orderId,
orderNo: order.orderNo,
amount: order.amount.toString(),
rejectReason: reason,
locale: playerLocale,
});
}
return { success: true };
}