/** * System Withdrawal Controller * * 系统账户转出管理 API * 仅供内部管理后台调用 */ import { Controller, Get, Post, Body, Query, Logger, BadRequestException, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse, ApiQuery, ApiBody, } from '@nestjs/swagger'; import { Public } from '@/shared/decorators'; import { SystemWithdrawalApplicationService } from '@/application/services'; // DTO 定义 class SystemWithdrawalRequestDTO { fromAccountSequence: string; toAccountSequence: string; amount: number; memo?: string; operatorId: string; operatorName?: string; } /** * 系统账户转出控制器 * 供管理后台调用,用于从系统账户转出资金到用户账户 */ @ApiTags('System Withdrawal (Internal)') @Controller('system-withdrawal') export class SystemWithdrawalController { private readonly logger = new Logger(SystemWithdrawalController.name); constructor( private readonly systemWithdrawalService: SystemWithdrawalApplicationService, ) {} /** * 发起系统账户转出 */ @Post('request') @Public() @ApiOperation({ summary: '发起系统账户转出(内部API)', description: '从系统账户(总部、运营、区域等)转出资金到用户账户', }) @ApiBody({ schema: { type: 'object', required: ['fromAccountSequence', 'toAccountSequence', 'amount', 'operatorId'], properties: { fromAccountSequence: { type: 'string', description: '转出方系统账户序列号', example: 'S0000000003', }, toAccountSequence: { type: 'string', description: '接收方用户充值ID', example: 'D25122800032', }, amount: { type: 'number', description: '转出金额(绿积分)', example: 1000, }, memo: { type: 'string', description: '备注', example: '补发奖励', }, operatorId: { type: 'string', description: '操作管理员ID', example: 'admin_001', }, operatorName: { type: 'string', description: '操作管理员姓名', example: '管理员张三', }, }, }, }) @ApiResponse({ status: 200, description: '转出订单创建成功' }) @ApiResponse({ status: 400, description: '参数错误或余额不足' }) async requestSystemWithdrawal(@Body() dto: SystemWithdrawalRequestDTO) { this.logger.log(`[REQUEST] 系统账户转出请求: ${JSON.stringify(dto)}`); // 验证必填参数 if (!dto.fromAccountSequence) { throw new BadRequestException('转出账户不能为空'); } if (!dto.toAccountSequence) { throw new BadRequestException('接收账户不能为空'); } if (!dto.amount || dto.amount <= 0) { throw new BadRequestException('转出金额必须大于0'); } if (!dto.operatorId) { throw new BadRequestException('操作员ID不能为空'); } const result = await this.systemWithdrawalService.requestSystemWithdrawal({ fromAccountSequence: dto.fromAccountSequence, toAccountSequence: dto.toAccountSequence, amount: dto.amount, memo: dto.memo, operatorId: dto.operatorId, operatorName: dto.operatorName, }); this.logger.log(`[REQUEST] 转出订单创建成功: ${result.orderNo}`); return { success: true, data: result, }; } /** * 获取可转出的系统账户列表 */ @Get('accounts') @Public() @ApiOperation({ summary: '获取可转出的系统账户列表(内部API)', description: '获取所有允许转出的系统账户及其余额', }) @ApiResponse({ status: 200, description: '系统账户列表' }) async getWithdrawableAccounts() { this.logger.log('[ACCOUNTS] 查询可转出系统账户'); const accounts = await this.systemWithdrawalService.getWithdrawableSystemAccounts(); return { success: true, data: accounts, }; } /** * 查询转出订单列表 */ @Get('orders') @Public() @ApiOperation({ summary: '查询系统账户转出订单列表(内部API)', description: '分页查询系统账户转出订单', }) @ApiQuery({ name: 'fromAccountSequence', required: false, description: '转出账户筛选' }) @ApiQuery({ name: 'toAccountSequence', required: false, description: '接收账户筛选' }) @ApiQuery({ name: 'status', required: false, description: '状态筛选 (PENDING/FROZEN/CONFIRMED/FAILED)' }) @ApiQuery({ name: 'page', required: false, description: '页码,默认1' }) @ApiQuery({ name: 'pageSize', required: false, description: '每页数量,默认20' }) @ApiResponse({ status: 200, description: '订单列表' }) async getOrders( @Query('fromAccountSequence') fromAccountSequence?: string, @Query('toAccountSequence') toAccountSequence?: string, @Query('status') status?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ) { this.logger.log(`[ORDERS] 查询转出订单: from=${fromAccountSequence}, to=${toAccountSequence}, status=${status}`); const result = await this.systemWithdrawalService.getSystemWithdrawalOrders({ fromAccountSequence, toAccountSequence, status, page: page ? parseInt(page, 10) : 1, pageSize: pageSize ? parseInt(pageSize, 10) : 20, }); return { success: true, data: result, }; } /** * 获取系统账户名称 */ @Get('account-name') @Public() @ApiOperation({ summary: '获取系统账户名称(内部API)', description: '根据账户序列号获取系统账户的显示名称', }) @ApiQuery({ name: 'accountSequence', required: true, description: '账户序列号' }) @ApiResponse({ status: 200, description: '账户名称' }) async getAccountName(@Query('accountSequence') accountSequence: string) { if (!accountSequence) { throw new BadRequestException('账户序列号不能为空'); } const name = this.systemWithdrawalService.getSystemAccountName(accountSequence); const isAllowed = this.systemWithdrawalService.isWithdrawalAllowed(accountSequence); return { success: true, data: { accountSequence, name, isWithdrawalAllowed: isAllowed, }, }; } }