fix(c2c): 过期恢复时合并到已有PENDING订单,避免同maker产生重复挂单

原来每个过期的MATCHED子订单都创建独立PENDING,导致一个卖单被多人
部分接单后过期会产生多个重复挂单。现在恢复时先查找同maker/type/price
的PENDING订单,有则合并数量,无则创建新订单。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-01 03:25:57 -08:00
parent 49ba2fcb19
commit 60d99add2c
1 changed files with 60 additions and 25 deletions

View File

@ -780,38 +780,73 @@ export class C2cService {
},
});
// 3. MATCHED/PAID 订单恢复为新的 PENDING 订单
// 3. MATCHED/PAID 订单恢复:优先合并到已有的同 maker/type/price 的 PENDING 订单
if (shouldRestore) {
const priceDecimal = new Decimal(freshOrder.price);
restoreOrderNo = this.generateOrderNo();
const totalAmount = priceDecimal.mul(quantityDecimal).toString();
this.logger.log(
`[EXPIRY][TX] 步骤3: 恢复为新 PENDING 订单 ${restoreOrderNo}, ` +
`类型=${freshOrder.type}, maker=${freshOrder.makerAccountSequence}, ` +
`数量=${quantityDecimal}, 总金额=${totalAmount}`,
);
await tx.c2cOrder.create({
data: {
orderNo: restoreOrderNo,
// 查找是否已有可合并的 PENDING 订单(同 maker + 同类型 + 同价格)
const existingPending = await tx.c2cOrder.findFirst({
where: {
makerAccountSequence: freshOrder.makerAccountSequence,
type: freshOrder.type as any,
status: C2C_ORDER_STATUS.PENDING as any,
makerAccountSequence: freshOrder.makerAccountSequence,
makerUserId: freshOrder.makerUserId,
makerPhone: freshOrder.makerPhone,
makerNickname: freshOrder.makerNickname,
price: freshOrder.price,
quantity: quantityDecimal.toString(),
totalAmount,
minAmount: '0',
maxAmount: '0',
paymentMethod: isSell ? freshOrder.paymentMethod : null,
paymentAccount: isSell ? freshOrder.paymentAccount : null,
paymentQrCode: isSell ? freshOrder.paymentQrCode : null,
paymentRealName: isSell ? freshOrder.paymentRealName : null,
sellerKavaAddress: isSell ? freshOrder.sellerKavaAddress : null,
remark: freshOrder.remark,
},
});
if (existingPending) {
// 合并到已有 PENDING 订单:增加数量和总金额
const existingQty = new Decimal(existingPending.quantity.toString());
const mergedQty = existingQty.plus(quantityDecimal);
const mergedTotal = priceDecimal.mul(mergedQty).toString();
restoreOrderNo = existingPending.orderNo;
this.logger.log(
`[EXPIRY][TX] 步骤3: 合并到已有 PENDING 订单 ${existingPending.orderNo}, ` +
`原数量=${existingQty} + 恢复=${quantityDecimal} = ${mergedQty}`,
);
await tx.c2cOrder.update({
where: { orderNo: existingPending.orderNo },
data: {
quantity: mergedQty.toString(),
totalAmount: mergedTotal,
},
});
} else {
// 无可合并订单,创建新的 PENDING 订单
restoreOrderNo = this.generateOrderNo();
const totalAmount = priceDecimal.mul(quantityDecimal).toString();
this.logger.log(
`[EXPIRY][TX] 步骤3: 创建新 PENDING 订单 ${restoreOrderNo}, ` +
`类型=${freshOrder.type}, maker=${freshOrder.makerAccountSequence}, ` +
`数量=${quantityDecimal}, 总金额=${totalAmount}`,
);
await tx.c2cOrder.create({
data: {
orderNo: restoreOrderNo,
type: freshOrder.type as any,
status: C2C_ORDER_STATUS.PENDING as any,
makerAccountSequence: freshOrder.makerAccountSequence,
makerUserId: freshOrder.makerUserId,
makerPhone: freshOrder.makerPhone,
makerNickname: freshOrder.makerNickname,
price: freshOrder.price,
quantity: quantityDecimal.toString(),
totalAmount,
minAmount: '0',
maxAmount: '0',
paymentMethod: isSell ? freshOrder.paymentMethod : null,
paymentAccount: isSell ? freshOrder.paymentAccount : null,
paymentQrCode: isSell ? freshOrder.paymentQrCode : null,
paymentRealName: isSell ? freshOrder.paymentRealName : null,
sellerKavaAddress: isSell ? freshOrder.sellerKavaAddress : null,
remark: freshOrder.remark,
},
});
}
} else {
this.logger.debug(`[EXPIRY][TX] 步骤3: PENDING 订单无需恢复`);
}