feat: multi-module iteration
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsNotEmpty, IsNumber, IsString, Min } from 'class-validator';
|
||||
import type { RedeemPhoneDirectPrepareRequest } from '@dukang/shared-types';
|
||||
|
||||
export class RedeemPhoneSendLookupSmsDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
phone: string;
|
||||
}
|
||||
|
||||
export class RedeemPhoneBalanceDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
phone: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
code: string;
|
||||
}
|
||||
|
||||
export class RedeemPhonePrepareDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
sessionId: string;
|
||||
|
||||
@Type(() => Number)
|
||||
@IsNumber()
|
||||
@Min(0.01)
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export class RedeemPhoneDirectPrepareDto implements RedeemPhoneDirectPrepareRequest {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
phone: string;
|
||||
|
||||
@Type(() => Number)
|
||||
@IsNumber()
|
||||
@Min(0.01)
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export class RedeemPhoneConfirmDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
sessionId: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
code: string;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsIn, IsInt, IsNotEmpty, IsOptional, IsString, MaxLength, Min } from 'class-validator';
|
||||
|
||||
export class RedeemFailureReportDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
token: string;
|
||||
|
||||
@IsIn(['NETWORK', 'BUSINESS'])
|
||||
errorClass: 'NETWORK' | 'BUSINESS';
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(256)
|
||||
message?: string;
|
||||
|
||||
@IsIn(['preview', 'confirm'])
|
||||
step: 'preview' | 'confirm';
|
||||
}
|
||||
|
||||
export class RedeemPendingSubmitDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
token: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
photoResourceId: string;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
failCount?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(256)
|
||||
remark?: string;
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import { Body, Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
|
||||
import { RedeemService } from './redeem.service';
|
||||
import { JwtAuthGuard, AuthUser } from '../../common/guards/jwt-auth.guard';
|
||||
import { ShopStoreGuard } from '../../common/guards/shop-store.guard';
|
||||
import { CurrentUser } from '../../common/decorators/current-user.decorator';
|
||||
import {
|
||||
RedeemPhoneBalanceDto,
|
||||
RedeemPhoneConfirmDto,
|
||||
RedeemPhoneDirectPrepareDto,
|
||||
RedeemPhonePrepareDto,
|
||||
RedeemPhoneSendLookupSmsDto,
|
||||
} from './dto/phone-redeem.dto';
|
||||
import { RedeemFailureReportDto, RedeemPendingSubmitDto } from './dto/weaknet-redeem.dto';
|
||||
|
||||
@Controller('redeem')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
export class UserRedeemController {
|
||||
constructor(private readonly redeemService: RedeemService) {}
|
||||
|
||||
@Post('tokens')
|
||||
createToken(@CurrentUser() user: AuthUser, @Body() body: Record<string, unknown>) {
|
||||
return this.redeemService.createToken(user.actorId, body as never);
|
||||
}
|
||||
|
||||
@Get('tokens/:token')
|
||||
getToken(@Param('token') token: string) {
|
||||
return this.redeemService.getToken(token);
|
||||
}
|
||||
|
||||
@Get('tokens/:token/status')
|
||||
getTokenStatus(@CurrentUser() user: AuthUser, @Param('token') token: string) {
|
||||
return this.redeemService.getTokenStatus(token, user.actorId);
|
||||
}
|
||||
|
||||
@Post('ratings')
|
||||
rating(@CurrentUser() user: AuthUser, @Body() body: Record<string, unknown>) {
|
||||
return this.redeemService.submitRating(user.actorId, body as never);
|
||||
}
|
||||
|
||||
@Get('records')
|
||||
records(
|
||||
@CurrentUser() user: AuthUser,
|
||||
@Query('page') page = '1',
|
||||
@Query('pageSize') pageSize = '20',
|
||||
) {
|
||||
return this.redeemService.listUserRecords(
|
||||
user.actorId,
|
||||
Number(page),
|
||||
Number(pageSize),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Controller('shop/redeem')
|
||||
@UseGuards(JwtAuthGuard, ShopStoreGuard)
|
||||
export class ShopRedeemController {
|
||||
constructor(private readonly redeemService: RedeemService) {}
|
||||
|
||||
@Post('preview')
|
||||
preview(@CurrentUser() user: AuthUser, @Body() body: { token: string }) {
|
||||
return this.redeemService.previewRedeem(user.actorId, user.storeId!, body.token);
|
||||
}
|
||||
|
||||
@Post('confirm')
|
||||
confirm(@CurrentUser() user: AuthUser, @Body() body: { token: string }) {
|
||||
return this.redeemService.confirmRedeem(user.actorId, user.storeId!, body);
|
||||
}
|
||||
|
||||
@Post('failures')
|
||||
reportFailure(
|
||||
@CurrentUser() user: AuthUser,
|
||||
@Body() body: RedeemFailureReportDto,
|
||||
) {
|
||||
return this.redeemService.reportNetworkFailure(user.actorId, user.storeId!, body);
|
||||
}
|
||||
|
||||
@Post('pending')
|
||||
submitPending(
|
||||
@CurrentUser() user: AuthUser,
|
||||
@Body() body: RedeemPendingSubmitDto,
|
||||
) {
|
||||
return this.redeemService.submitPendingRedeem(user.actorId, user.storeId!, body);
|
||||
}
|
||||
|
||||
@Get('records')
|
||||
records(
|
||||
@CurrentUser() user: AuthUser,
|
||||
@Query('page') page = '1',
|
||||
@Query('pageSize') pageSize = '20',
|
||||
) {
|
||||
return this.redeemService.listShopRecords(
|
||||
user.actorId,
|
||||
user.storeId!,
|
||||
Number(page),
|
||||
Number(pageSize),
|
||||
);
|
||||
}
|
||||
|
||||
@Get('stats')
|
||||
stats(
|
||||
@CurrentUser() user: AuthUser,
|
||||
@Query('range') range?: string,
|
||||
) {
|
||||
const normalized =
|
||||
range === '7d' || range === '30d' || range === 'today' ? range : 'today';
|
||||
return this.redeemService.getShopRedeemStats(user.actorId, user.storeId!, normalized);
|
||||
}
|
||||
|
||||
@Post('phone/send-lookup-sms')
|
||||
sendPhoneLookupSms(@CurrentUser() user: AuthUser, @Body() body: RedeemPhoneSendLookupSmsDto) {
|
||||
return this.redeemService.sendPhoneLookupSms(user.actorId, user.storeId!, body.phone);
|
||||
}
|
||||
|
||||
@Post('phone/balance')
|
||||
phoneBalance(@CurrentUser() user: AuthUser, @Body() body: RedeemPhoneBalanceDto) {
|
||||
return this.redeemService.verifyPhoneAndGetBalance(
|
||||
user.actorId,
|
||||
user.storeId!,
|
||||
body.phone,
|
||||
body.code,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('phone/prepare')
|
||||
phonePrepare(@CurrentUser() user: AuthUser, @Body() body: RedeemPhonePrepareDto) {
|
||||
return this.redeemService.preparePhoneRedeem(
|
||||
user.actorId,
|
||||
user.storeId!,
|
||||
body.sessionId,
|
||||
body.amount,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('phone/prepare-direct')
|
||||
phonePrepareDirect(@CurrentUser() user: AuthUser, @Body() body: RedeemPhoneDirectPrepareDto) {
|
||||
return this.redeemService.preparePhoneRedeemDirect(
|
||||
user.actorId,
|
||||
user.storeId!,
|
||||
body.phone,
|
||||
body.amount,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('phone/confirm')
|
||||
phoneConfirm(@CurrentUser() user: AuthUser, @Body() body: RedeemPhoneConfirmDto) {
|
||||
return this.redeemService.confirmPhoneRedeem(
|
||||
user.actorId,
|
||||
user.storeId!,
|
||||
body.sessionId,
|
||||
body.code,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Module, forwardRef } from '@nestjs/common';
|
||||
import { AnalyticsModule } from '../analytics/analytics.module';
|
||||
import { IamModule } from '../iam/iam.module';
|
||||
import { BenefitModule } from '../benefit/benefit.module';
|
||||
import { SettlementModule } from '../settlement/settlement.module';
|
||||
import { RedeemService } from './redeem.service';
|
||||
import { ShopRedeemController, UserRedeemController } from './redeem.controller';
|
||||
|
||||
@Module({
|
||||
imports: [IamModule, AnalyticsModule, BenefitModule, forwardRef(() => SettlementModule)],
|
||||
controllers: [UserRedeemController, ShopRedeemController],
|
||||
providers: [RedeemService],
|
||||
exports: [RedeemService],
|
||||
})
|
||||
export class RedeemModule {}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user