fix(pre-planting): 合并逻辑改为按份数累计,支持多份订单合并

问题:用户一笔订单可购买多份(portionCount>1),但 performMerge
按订单条数校验是否够 10 条,导致 6 笔订单共 10 份却报错
"不足 10 笔已支付订单进行合并"。

修复:
- performMerge: 遍历 PAID 订单累加 portionCount 直到凑满 10 份
- findPaidOrdersByUserId: 去掉 limit 参数,获取所有 PAID 订单
- PrePlantingMerge.create: 去掉 sourceOrderNos.length === 10 校验
  改为 length > 0(份数校验已在 performMerge 完成)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-03-03 02:44:35 -08:00
parent d7f7d7082d
commit a8e06e2eda
3 changed files with 17 additions and 13 deletions

View File

@ -574,18 +574,24 @@ export class PrePlantingApplicationService {
accountSequence: string, accountSequence: string,
position: import('../../domain/aggregates/pre-planting-position.aggregate').PrePlantingPosition, position: import('../../domain/aggregates/pre-planting-position.aggregate').PrePlantingPosition,
) { ) {
// 获取待合并的已支付订单(数量由 PRE_PLANTING_PORTIONS_PER_TREE 决定) // 获取所有已支付订单,按份数累加取够 PRE_PLANTING_PORTIONS_PER_TREE 份
const paidOrders = await this.orderRepo.findPaidOrdersByUserId( // 注意一笔订单可能包含多份portionCount > 1所以不能按订单条数判断
tx, const allPaidOrders = await this.orderRepo.findPaidOrdersByUserId(tx, userId);
userId,
PRE_PLANTING_PORTIONS_PER_TREE,
);
if (paidOrders.length < PRE_PLANTING_PORTIONS_PER_TREE) { let accumulatedPortions = 0;
throw new Error(`不足 ${PRE_PLANTING_PORTIONS_PER_TREE} 笔已支付订单进行合并`); const sourceOrders: typeof allPaidOrders = [];
for (const order of allPaidOrders) {
sourceOrders.push(order);
accumulatedPortions += order.portionCount;
if (accumulatedPortions >= PRE_PLANTING_PORTIONS_PER_TREE) break;
}
if (accumulatedPortions < PRE_PLANTING_PORTIONS_PER_TREE) {
throw new Error(
`不足 ${PRE_PLANTING_PORTIONS_PER_TREE} 份进行合并(当前 ${accumulatedPortions} 份,来自 ${sourceOrders.length} 笔订单)`,
);
} }
const sourceOrders = paidOrders.slice(0, PRE_PLANTING_PORTIONS_PER_TREE);
const sourceOrderNos = sourceOrders.map((o) => o.orderNo); const sourceOrderNos = sourceOrders.map((o) => o.orderNo);
const mergeNo = this.generateMergeNo(); const mergeNo = this.generateMergeNo();

View File

@ -70,8 +70,8 @@ export class PrePlantingMerge {
cityCode: string, cityCode: string,
totalTreesMergedAfter: number, totalTreesMergedAfter: number,
): PrePlantingMerge { ): PrePlantingMerge {
if (sourceOrderNos.length !== PRE_PLANTING_PORTIONS_PER_TREE) { if (sourceOrderNos.length === 0) {
throw new Error(`合并需要 ${PRE_PLANTING_PORTIONS_PER_TREE} 个订单,收到 ${sourceOrderNos.length}`); throw new Error('合并至少需要 1 笔源订单');
} }
const merge = new PrePlantingMerge( const merge = new PrePlantingMerge(

View File

@ -61,12 +61,10 @@ export class PrePlantingOrderRepository {
async findPaidOrdersByUserId( async findPaidOrdersByUserId(
tx: Prisma.TransactionClient, tx: Prisma.TransactionClient,
userId: bigint, userId: bigint,
limit: number,
): Promise<PrePlantingOrder[]> { ): Promise<PrePlantingOrder[]> {
const records = await tx.prePlantingOrder.findMany({ const records = await tx.prePlantingOrder.findMany({
where: { userId, status: PrePlantingOrderStatus.PAID }, where: { userId, status: PrePlantingOrderStatus.PAID },
orderBy: { createdAt: 'asc' }, orderBy: { createdAt: 'asc' },
take: limit,
}); });
return records.map((r) => this.toDomain(r)); return records.map((r) => this.toDomain(r));
} }