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,
|
ApiOperation,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiQuery,
|
ApiQuery,
|
||||||
ApiBody,
|
ApiProperty,
|
||||||
} from '@nestjs/swagger';
|
} from '@nestjs/swagger';
|
||||||
|
import { IsString, IsNotEmpty, IsOptional, IsNumber } from 'class-validator';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
import { Public } from '@/shared/decorators';
|
import { Public } from '@/shared/decorators';
|
||||||
import { SystemWithdrawalApplicationService } from '@/application/services';
|
import { SystemWithdrawalApplicationService } from '@/application/services';
|
||||||
|
|
||||||
// DTO 定义
|
// DTO 定义
|
||||||
class SystemWithdrawalRequestDTO {
|
class SystemWithdrawalRequestDTO {
|
||||||
|
@ApiProperty({ description: '转出方系统账户序列号', example: 'S0000000003' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
fromAccountSequence: string;
|
fromAccountSequence: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '接收方用户充值ID', example: 'D25122800032' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
toAccountSequence: string;
|
toAccountSequence: string;
|
||||||
amount: number | string; // 支持字符串或数字
|
|
||||||
|
@ApiProperty({ description: '转出金额(绿积分)', example: 1000 })
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
amount: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '备注', required: false, example: '补发奖励' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
memo?: string;
|
memo?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '操作管理员ID', example: 'admin_001' })
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
operatorId: string;
|
operatorId: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: '操作管理员姓名', required: false, example: '管理员张三' })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
operatorName?: string;
|
operatorName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,70 +81,20 @@ export class SystemWithdrawalController {
|
||||||
summary: '发起系统账户转出(内部API)',
|
summary: '发起系统账户转出(内部API)',
|
||||||
description: '从系统账户(总部、运营、区域等)转出资金到用户账户',
|
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: 200, description: '转出订单创建成功' })
|
||||||
@ApiResponse({ status: 400, description: '参数错误或余额不足' })
|
@ApiResponse({ status: 400, description: '参数错误或余额不足' })
|
||||||
async requestSystemWithdrawal(@Body() dto: SystemWithdrawalRequestDTO) {
|
async requestSystemWithdrawal(@Body() dto: SystemWithdrawalRequestDTO) {
|
||||||
this.logger.log(`[REQUEST] 系统账户转出请求: ${JSON.stringify(dto)}`);
|
this.logger.log(`[REQUEST] 系统账户转出请求: ${JSON.stringify(dto)}`);
|
||||||
|
|
||||||
// 验证必填参数
|
// class-validator 已处理基本验证,这里只做业务验证
|
||||||
if (!dto.fromAccountSequence) {
|
if (dto.amount <= 0) {
|
||||||
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) {
|
|
||||||
throw new BadRequestException('转出金额必须大于0');
|
throw new BadRequestException('转出金额必须大于0');
|
||||||
}
|
}
|
||||||
if (!dto.operatorId) {
|
|
||||||
throw new BadRequestException('操作员ID不能为空');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await this.systemWithdrawalService.requestSystemWithdrawal({
|
const result = await this.systemWithdrawalService.requestSystemWithdrawal({
|
||||||
fromAccountSequence: dto.fromAccountSequence,
|
fromAccountSequence: dto.fromAccountSequence,
|
||||||
toAccountSequence: dto.toAccountSequence,
|
toAccountSequence: dto.toAccountSequence,
|
||||||
amount: amount,
|
amount: dto.amount,
|
||||||
memo: dto.memo,
|
memo: dto.memo,
|
||||||
operatorId: dto.operatorId,
|
operatorId: dto.operatorId,
|
||||||
operatorName: dto.operatorName,
|
operatorName: dto.operatorName,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue