后端增加发放好客权益券的接口

This commit is contained in:
2026-07-12 20:28:43 +08:00
parent b267e885be
commit b5235dedef
8 changed files with 303 additions and 34 deletions
@@ -1,9 +1,10 @@
import { Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { HqOperation } from '../../common/hq-operation/hq-operation.decorator';
import { HqOperationAction } from '../../common/hq-operation/hq-operation.constants';
import { AdminBenefitService } from './admin-benefit.service';
import { AdminBenefitCouponsQueryDto, AdminBenefitLedgersQueryDto } from './dto/admin-query.dto';
import { AdminBenefitGrantDto } from './dto/admin-mutate.dto';
@Controller('admin/benefit/coupons')
@UseGuards(HqAuthGuard)
@@ -15,6 +16,17 @@ export class AdminBenefitCouponsController {
return this.service.listCoupons(query);
}
@Post('grant')
@HqOperation({
action: HqOperationAction.BENEFIT_COUPON_GRANT,
refType: 'BENEFIT_COUPON',
refIdField: 'id',
includeBody: true,
})
grant(@Body() dto: AdminBenefitGrantDto) {
return this.service.grantCoupon(dto);
}
@Get(':id')
detail(@Param('id') id: string) {
return this.service.detailCoupon(BigInt(id));
@@ -4,11 +4,16 @@ import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import { buildBenefitLedgerEvent, benefitLedgerWhere } from '../../common/event/event.helpers';
import { mapBenefitLedgerCompat } from '../../common/compat/v31-compat';
import { BenefitService } from '../benefit/benefit.service';
import type { AdminBenefitCouponsQueryDto, AdminBenefitLedgersQueryDto } from './dto/admin-query.dto';
import type { AdminBenefitGrantDto } from './dto/admin-mutate.dto';
@Injectable()
export class AdminBenefitService {
constructor(private readonly prisma: PrismaService) {}
constructor(
private readonly prisma: PrismaService,
private readonly benefitService: BenefitService,
) {}
async listCoupons(query: AdminBenefitCouponsQueryDto) {
const page = query.page ?? 1;
@@ -80,6 +85,32 @@ export class AdminBenefitService {
return serializeBigInt(updated);
}
async grantCoupon(dto: AdminBenefitGrantDto) {
const phone = dto.phone.trim();
if (!/^1[3-9]\d{9}$/.test(phone)) {
throw new BadRequestException('请输入正确的用户手机号');
}
const user = await this.prisma.user.findFirst({
where: { phone, status: 1, mergedIntoUserId: null },
select: { id: true, userNo: true, phone: true, nickname: true },
});
if (!user) {
throw new NotFoundException('未找到该手机号对应的用户');
}
const coupon = await this.benefitService.grantManual({
userId: user.id,
amount: dto.amount,
remark: dto.remark,
});
return serializeBigInt({
...coupon,
user,
});
}
async listLedgers(query: AdminBenefitLedgersQueryDto) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
@@ -993,3 +993,19 @@ export class UpdatePromoCodeStatusDto {
@IsIn(['ACTIVE', 'DISABLED'])
status: 'ACTIVE' | 'DISABLED';
}
export class AdminBenefitGrantDto {
@IsString()
@IsNotEmpty()
phone: string;
@Type(() => Number)
@IsNumber()
@Min(0.01)
@Max(999999.99)
amount: number;
@IsOptional()
@IsString()
remark?: string;
}