v3.5.3版本更新1
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-08-20 18:54:15 +08:00
parent ee493823bf
commit fc2e5b65de
65 changed files with 2297 additions and 875 deletions
@@ -9,6 +9,7 @@ import {
generateRedeemNo,
generateRedeemPendingNo,
REDEEM_WEAKNET_FAIL_THRESHOLD,
resolveSettlementRate,
validateRedeemAmount,
allocateBenefitCoupons,
} from '@dukang/domain';
@@ -176,8 +177,15 @@ export class RedeemService {
normalizedAllocations: Array<{ couponId: string; amount: number }>,
analyticsExtra?: { channel: 'token' | 'phone'; sessionId?: string; tokenSuffix?: string },
) {
const settlementRate = Number(account.store.settlementRate);
const settleAmount = calcRedeemSettleAmount(amount, settlementRate);
const amountNum = Number(amount);
if (!Number.isFinite(amountNum) || amountNum <= 0) {
throw new BadRequestException('核销金额必须大于 0');
}
const settlementRate = resolveSettlementRate(account.store.settlementRate);
const settleAmount = calcRedeemSettleAmount(amountNum, settlementRate);
if (!Number.isFinite(settleAmount) || settleAmount < 0) {
throw new BadRequestException('结算金额计算异常');
}
const redeemChannel = analyticsExtra?.channel === 'phone' ? 'PHONE' : 'SCAN';
const [userRow, storeRow] = await Promise.all([
@@ -200,7 +208,7 @@ export class RedeemService {
userId,
couponId: BigInt(normalizedAllocations[0].couponId),
storeId: account.storeId,
amount,
amount: amountNum,
settleAmount,
channel: redeemChannel,
isTest,
@@ -214,16 +222,14 @@ export class RedeemService {
},
});
if (!isTest) {
await this.settlementService.createStorePayout(
redeemRecord.id,
account.storeId,
amount,
settleAmount,
settlementRate,
tx,
);
}
await this.settlementService.createStorePayout(
redeemRecord.id,
account.storeId,
amountNum,
settleAmount,
settlementRate,
tx,
);
return redeemRecord;
});
@@ -240,7 +246,7 @@ export class RedeemService {
const redeemExtra = {
redeemRecordId: record.id.toString(),
storeId: account.storeId.toString(),
amount,
amount: amountNum,
channel: analyticsExtra?.channel ?? 'token',
...(analyticsExtra?.sessionId ? { sessionId: analyticsExtra.sessionId } : {}),
...(analyticsExtra?.tokenSuffix ? { tokenSuffix: analyticsExtra.tokenSuffix } : {}),
@@ -252,7 +258,7 @@ export class RedeemService {
refId: record.id,
extraJson: {
redeemNo: record.redeemNo,
amount,
amount: amountNum,
userId: userId.toString(),
channel: analyticsExtra?.channel ?? 'token',
},
@@ -270,7 +276,11 @@ export class RedeemService {
extraJson: redeemExtra,
});
return record;
return {
...record,
amount: amountNum,
settleAmount,
};
}
async sendPhoneLookupSms(storeAccountId: bigint, storeId: bigint, phone: string) {
@@ -484,6 +494,12 @@ export class RedeemService {
}
async createToken(userId: bigint, body: { couponId?: string; amount: number; storeId?: string }) {
const amount = Number(body.amount);
if (!Number.isFinite(amount) || amount <= 0) {
throw new BadRequestException('核销金额必须大于 0');
}
body = { ...body, amount };
let allocations: Array<{ couponId: string; amount: number }>;
if (body.couponId) {
@@ -993,6 +1009,9 @@ export class RedeemService {
await this.validateAllocations(normalizedAllocations);
const amount = Number(pending.amount);
if (!Number.isFinite(amount) || amount <= 0) {
throw new BadRequestException('待处理单核销金额无效');
}
const record = await this.executeRedeem(
account,
pending.userId,
@@ -1101,7 +1120,26 @@ export class RedeemService {
}),
this.prisma.redeemRecord.count({ where: { storeId } }),
]);
return { list: serializeBigInt(list), total, page, pageSize };
return {
list: serializeBigInt(
list.map((r) => ({
...r,
amount: Number(r.amount),
settleAmount: Number(r.settleAmount),
payout: r.payout
? {
...r.payout,
redeemAmount: Number(r.payout.redeemAmount),
payoutAmount: Number(r.payout.payoutAmount),
settlementRate: Number(r.payout.settlementRate),
}
: r.payout,
})),
),
total,
page,
pageSize,
};
}
async getShopRedeemStats(
@@ -1174,7 +1212,11 @@ export class RedeemService {
todayAmount,
todayScanCount,
todayPhoneCount,
recentRecords: recent,
recentRecords: recent.map((r) => ({
...r,
amount: Number(r.amount),
settleAmount: Number(r.settleAmount),
})),
});
}