From 60d99add2c0dc1c0fe38d0a61d29e28afdb962f6 Mon Sep 17 00:00:00 2001 From: hailin Date: Sun, 1 Feb 2026 03:25:57 -0800 Subject: [PATCH] =?UTF-8?q?fix(c2c):=20=E8=BF=87=E6=9C=9F=E6=81=A2?= =?UTF-8?q?=E5=A4=8D=E6=97=B6=E5=90=88=E5=B9=B6=E5=88=B0=E5=B7=B2=E6=9C=89?= =?UTF-8?q?PENDING=E8=AE=A2=E5=8D=95=EF=BC=8C=E9=81=BF=E5=85=8D=E5=90=8Cma?= =?UTF-8?q?ker=E4=BA=A7=E7=94=9F=E9=87=8D=E5=A4=8D=E6=8C=82=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原来每个过期的MATCHED子订单都创建独立PENDING,导致一个卖单被多人 部分接单后过期会产生多个重复挂单。现在恢复时先查找同maker/type/price 的PENDING订单,有则合并数量,无则创建新订单。 Co-Authored-By: Claude Opus 4.5 --- .../src/application/services/c2c.service.ts | 85 +++++++++++++------ 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/backend/services/trading-service/src/application/services/c2c.service.ts b/backend/services/trading-service/src/application/services/c2c.service.ts index 5840e160..69852dc2 100644 --- a/backend/services/trading-service/src/application/services/c2c.service.ts +++ b/backend/services/trading-service/src/application/services/c2c.service.ts @@ -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 订单无需恢复`); }