rwadurian/backend/services/wallet-service/src/api/controllers/system-withdrawal.controlle...

221 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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,
},
};
}
}