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 bb7bb1af..9b6ae264 100644 --- a/backend/services/trading-service/src/application/services/c2c.service.ts +++ b/backend/services/trading-service/src/application/services/c2c.service.ts @@ -747,8 +747,64 @@ export class C2cService { }); this.logger.log(`C2C订单已过期: ${freshOrder.orderNo}, 原状态: ${freshOrder.status}`); + + // MATCHED/PAID 订单过期后,将数量退还为新的 PENDING 订单(恢复到市场) + if (freshOrder.status === C2C_ORDER_STATUS.MATCHED || freshOrder.status === C2C_ORDER_STATUS.PAID) { + await this.restoreExpiredOrder(freshOrder, quantityDecimal); + } } finally { await this.redis.releaseLock(lockKey, lockValue); } } + + /** + * 过期订单恢复:为 maker 重新创建一个 PENDING 订单 + * 将过期的成交数量退还到市场,让其他用户可以继续接单 + */ + private async restoreExpiredOrder(expiredOrder: C2cOrderEntity, quantityDecimal: Decimal): Promise { + try { + const priceDecimal = new Decimal(expiredOrder.price); + const totalAmountDecimal = priceDecimal.mul(quantityDecimal); + + // SELL 订单需要重新冻结 maker 的积分值 + if (expiredOrder.type === C2C_ORDER_TYPE.SELL) { + const makerAccount = await this.tradingAccountRepository.findByAccountSequence(expiredOrder.makerAccountSequence); + if (!makerAccount) { + this.logger.warn(`过期恢复: maker ${expiredOrder.makerAccountSequence} 账户不存在,跳过恢复`); + return; + } + const quantityMoney = new Money(quantityDecimal); + if (makerAccount.availableCash.isLessThan(quantityMoney)) { + this.logger.warn(`过期恢复: maker ${expiredOrder.makerAccountSequence} 可用余额不足 (需要 ${quantityDecimal}, 可用 ${makerAccount.availableCash}),跳过恢复`); + return; + } + await this.tradingAccountRepository.freezeCash(expiredOrder.makerAccountSequence, quantityDecimal); + } + + // 创建新的 PENDING 订单 + const restoreOrderNo = this.generateOrderNo(); + await this.c2cOrderRepository.create({ + orderNo: restoreOrderNo, + type: expiredOrder.type as any, + makerAccountSequence: expiredOrder.makerAccountSequence, + makerUserId: expiredOrder.makerUserId ?? undefined, + makerPhone: expiredOrder.makerPhone ?? undefined, + makerNickname: expiredOrder.makerNickname ?? undefined, + price: expiredOrder.price, + quantity: quantityDecimal.toString(), + totalAmount: totalAmountDecimal.toString(), + paymentMethod: expiredOrder.type === C2C_ORDER_TYPE.SELL ? (expiredOrder.paymentMethod ?? undefined) : undefined, + paymentAccount: expiredOrder.type === C2C_ORDER_TYPE.SELL ? (expiredOrder.paymentAccount ?? undefined) : undefined, + paymentQrCode: expiredOrder.type === C2C_ORDER_TYPE.SELL ? (expiredOrder.paymentQrCode ?? undefined) : undefined, + paymentRealName: expiredOrder.type === C2C_ORDER_TYPE.SELL ? (expiredOrder.paymentRealName ?? undefined) : undefined, + sellerKavaAddress: expiredOrder.sellerKavaAddress, + remark: expiredOrder.remark ?? undefined, + }); + + this.logger.log(`过期恢复: 订单 ${expiredOrder.orderNo} 已恢复为新 PENDING 订单 ${restoreOrderNo}, 数量: ${quantityDecimal}`); + } catch (error) { + this.logger.error(`过期恢复失败: ${expiredOrder.orderNo}`, error); + // 恢复失败不影响过期流程,只记录日志 + } + } }