112 lines
4.0 KiB
TypeScript
112 lines
4.0 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<{ accountId: bigint; storeId: bigint }> {
|
|
const sid = this.parseStoreId(storeId);
|
|
const binding = await this.prisma.storeAccountStore.findFirst({
|
|
where: {
|
|
storeId: sid,
|
|
storeAccount: { status: 'ACTIVE', isPrimary: 1 },
|
|
},
|
|
orderBy: { id: 'asc' },
|
|
select: { storeAccountId: true, storeId: true },
|
|
});
|
|
if (!binding) {
|
|
throw new NotFoundException('该门店无可用账户,请先创建门店账户');
|
|
}
|
|
return { accountId: binding.storeAccountId, storeId: binding.storeId };
|
|
}
|
|
|
|
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 { accountId, storeId } = await this.resolveStoreAccountId(dto.storeId);
|
|
return this.redeemService.previewRedeem(accountId, storeId, dto.token);
|
|
}
|
|
|
|
async confirm(dto: AdminRedeemDebugStoreTokenDto) {
|
|
const { accountId, storeId } = await this.resolveStoreAccountId(dto.storeId);
|
|
return this.redeemService.confirmRedeem(accountId, storeId, { token: dto.token });
|
|
}
|
|
|
|
async sendPhoneLookupSms(dto: AdminRedeemDebugPhoneStoreDto) {
|
|
const { accountId, storeId } = await this.resolveStoreAccountId(dto.storeId);
|
|
return this.redeemService.sendPhoneLookupSms(accountId, storeId, dto.phone);
|
|
}
|
|
|
|
async phoneBalance(dto: AdminRedeemDebugPhoneBalanceDto) {
|
|
const { accountId, storeId } = await this.resolveStoreAccountId(dto.storeId);
|
|
return this.redeemService.verifyPhoneAndGetBalance(accountId, storeId, dto.phone, dto.code);
|
|
}
|
|
|
|
async phonePrepare(dto: AdminRedeemDebugPhonePrepareDto) {
|
|
const { accountId, storeId } = await this.resolveStoreAccountId(dto.storeId);
|
|
return this.redeemService.preparePhoneRedeem(accountId, storeId, dto.sessionId, dto.amount);
|
|
}
|
|
|
|
async phoneConfirm(dto: AdminRedeemDebugPhoneConfirmDto) {
|
|
const { accountId, storeId } = await this.resolveStoreAccountId(dto.storeId);
|
|
return this.redeemService.confirmPhoneRedeem(accountId, storeId, dto.sessionId, dto.code);
|
|
}
|
|
}
|