Files
dukang/server/dukang-api/src/modules/ops/admin-redeem-debug.service.ts
T
2026-07-12 10:34:58 +08:00

108 lines
3.8 KiB
TypeScript

import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../../common/prisma/prisma.module';
import { RedeemService } from '../redeem/redeem.service';
import type {
AdminRedeemDebugCreateTokenDto,
AdminRedeemDebugPhoneBalanceDto,
AdminRedeemDebugPhoneConfirmDto,
AdminRedeemDebugPhonePrepareDto,
AdminRedeemDebugPhoneStoreDto,
AdminRedeemDebugStoreTokenDto,
} from './dto/admin-mutate.dto';
@Injectable()
export class AdminRedeemDebugService {
constructor(
private readonly prisma: PrismaService,
private readonly redeemService: RedeemService,
) {}
private parseStoreId(value: string): bigint {
const normalized = String(value ?? '').trim();
if (!normalized || !/^\d+$/.test(normalized)) {
throw new BadRequestException('门店 ID 格式无效');
}
return BigInt(normalized);
}
private async resolveUserId(identifier: string): Promise<bigint> {
const normalized = String(identifier ?? '').trim();
if (!normalized) {
throw new BadRequestException('请填写用户 ID、用户编号或手机号');
}
if (/^\d+$/.test(normalized)) {
const byId = await this.prisma.user.findUnique({
where: { id: BigInt(normalized) },
select: { id: true },
});
if (byId) return byId.id;
const byPhone = await this.prisma.user.findFirst({
where: { phone: normalized },
select: { id: true },
});
if (byPhone) return byPhone.id;
} else {
const byNo = await this.prisma.user.findFirst({
where: { userNo: normalized },
select: { id: true },
});
if (byNo) return byNo.id;
}
throw new NotFoundException('用户不存在,请检查 ID、用户编号或手机号');
}
private async resolveStoreAccountId(storeId: string): Promise<bigint> {
const account = await this.prisma.storeAccount.findFirst({
where: { storeId: this.parseStoreId(storeId), status: 'ACTIVE' },
orderBy: { id: 'asc' },
select: { id: true, store: { select: { name: true } } },
});
if (!account) {
throw new NotFoundException('该门店无可用账户,请先创建门店账户');
}
return account.id;
}
async createToken(dto: AdminRedeemDebugCreateTokenDto) {
const userId = await this.resolveUserId(dto.userId);
return this.redeemService.createToken(userId, {
amount: dto.amount,
couponId: dto.couponId?.trim() || undefined,
storeId: dto.storeId?.trim() || undefined,
});
}
async preview(dto: AdminRedeemDebugStoreTokenDto) {
const storeAccountId = await this.resolveStoreAccountId(dto.storeId);
return this.redeemService.previewRedeem(storeAccountId, dto.token);
}
async confirm(dto: AdminRedeemDebugStoreTokenDto) {
const storeAccountId = await this.resolveStoreAccountId(dto.storeId);
return this.redeemService.confirmRedeem(storeAccountId, { token: dto.token });
}
async sendPhoneLookupSms(dto: AdminRedeemDebugPhoneStoreDto) {
const storeAccountId = await this.resolveStoreAccountId(dto.storeId);
return this.redeemService.sendPhoneLookupSms(storeAccountId, dto.phone);
}
async phoneBalance(dto: AdminRedeemDebugPhoneBalanceDto) {
const storeAccountId = await this.resolveStoreAccountId(dto.storeId);
return this.redeemService.verifyPhoneAndGetBalance(storeAccountId, dto.phone, dto.code);
}
async phonePrepare(dto: AdminRedeemDebugPhonePrepareDto) {
const storeAccountId = await this.resolveStoreAccountId(dto.storeId);
return this.redeemService.preparePhoneRedeem(storeAccountId, dto.sessionId, dto.amount);
}
async phoneConfirm(dto: AdminRedeemDebugPhoneConfirmDto) {
const storeAccountId = await this.resolveStoreAccountId(dto.storeId);
return this.redeemService.confirmPhoneRedeem(storeAccountId, dto.sessionId, dto.code);
}
}