fix(wallet-service): 修复系统划转请求 DTO 验证错误
- 为 SystemWithdrawalRequestDTO 添加 class-validator 装饰器 - 添加 @ApiProperty 装饰器用于 Swagger 文档 - 使用 @Type(() => Number) 自动转换 amount 类型 - 简化验证逻辑,移除冗余的手动验证 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
02fa87f6c8
commit
db833fdf45
|
|
@ -19,18 +19,43 @@ import {
|
|||
ApiOperation,
|
||||
ApiResponse,
|
||||
ApiQuery,
|
||||
ApiBody,
|
||||
ApiProperty,
|
||||
} from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty, IsOptional, IsNumber } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
import { Public } from '@/shared/decorators';
|
||||
import { SystemWithdrawalApplicationService } from '@/application/services';
|
||||
|
||||
// DTO 定义
|
||||
class SystemWithdrawalRequestDTO {
|
||||
@ApiProperty({ description: '转出方系统账户序列号', example: 'S0000000003' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
fromAccountSequence: string;
|
||||
|
||||
@ApiProperty({ description: '接收方用户充值ID', example: 'D25122800032' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
toAccountSequence: string;
|
||||
amount: number | string; // 支持字符串或数字
|
||||
|
||||
@ApiProperty({ description: '转出金额(绿积分)', example: 1000 })
|
||||
@Type(() => Number)
|
||||
@IsNumber()
|
||||
amount: number;
|
||||
|
||||
@ApiProperty({ description: '备注', required: false, example: '补发奖励' })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
memo?: string;
|
||||
|
||||
@ApiProperty({ description: '操作管理员ID', example: 'admin_001' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
operatorId: string;
|
||||
|
||||
@ApiProperty({ description: '操作管理员姓名', required: false, example: '管理员张三' })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
operatorName?: string;
|
||||
}
|
||||
|
||||
|
|
@ -56,70 +81,20 @@ export class SystemWithdrawalController {
|
|||
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('接收账户不能为空');
|
||||
}
|
||||
|
||||
// 将 amount 转换为数字(前端可能传入字符串)
|
||||
const amount = typeof dto.amount === 'string' ? parseFloat(dto.amount) : dto.amount;
|
||||
if (!amount || isNaN(amount) || amount <= 0) {
|
||||
// class-validator 已处理基本验证,这里只做业务验证
|
||||
if (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: amount,
|
||||
amount: dto.amount,
|
||||
memo: dto.memo,
|
||||
operatorId: dto.operatorId,
|
||||
operatorName: dto.operatorName,
|
||||
|
|
|
|||
Loading…
Reference in New Issue