diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/mapper/ReturnPackingTraceMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/mapper/ReturnPackingTraceMapper.java index 1081009f5..93b7ba81c 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/mapper/ReturnPackingTraceMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/mapper/ReturnPackingTraceMapper.java @@ -22,6 +22,9 @@ public interface ReturnPackingTraceMapper { @Select("SELECT return_no, SUM(CASE WHEN target_carton_mark=#{mark} THEN quantity ELSE -quantity END) AS quantity FROM ll_return_packing_trace WHERE customer_id=#{customerId} AND sku_code=#{sku} AND (source_carton_mark=#{mark} OR target_carton_mark=#{mark}) GROUP BY return_no HAVING quantity>0 ORDER BY return_no") List ownership(@Param("customerId") String customerId, @Param("mark") String mark, @Param("sku") String sku); + @Select("SELECT COALESCE(SUM(CASE WHEN target_carton_mark=#{mark} THEN quantity ELSE -quantity END),0) FROM ll_return_packing_trace WHERE customer_id=#{customerId} AND sku_code=#{sku} AND (source_carton_mark=#{mark} OR target_carton_mark=#{mark})") + long netTrackedQuantity(@Param("customerId") String customerId, @Param("mark") String mark, @Param("sku") String sku); + @Select("SELECT id,source_carton_mark,target_carton_mark,return_no,sku_code,quantity,created_at FROM ll_return_packing_trace WHERE customer_id=#{customerId} AND return_no=#{returnNo} ORDER BY created_at,id") List listReturn(@Param("customerId") String customerId, @Param("returnNo") String returnNo); diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryService.java index c398f297e..748ec70f7 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryService.java @@ -1014,8 +1014,7 @@ public class ReturnInventoryService { throw conflict("目标箱已有合箱预占,不能并入"); if (existingTarget != null) ReturnCartonCountGuard.requireConfirmed(existingTarget); if (existingTarget != null) for (var item : cartonItems.lockCarton(existingTarget.getId())) { - long tracked = packingTrace.ownership(customerId, targetMark, item.getSkuCode()).stream() - .mapToLong(com.baiyue.lastleg.returnreceipt.mapper.ReturnPackingTraceMapper.Ownership::quantity).sum(); + long tracked = packingTrace.netTrackedQuantity(customerId, targetMark, item.getSkuCode()); if (tracked < value(item.getQuantity())) { String[] origins = required(existingTarget.getSourceReturnNo(), "目标箱来源退货单缺失").split(","); if (origins.length != 1) throw conflict("历史目标混箱缺少 SKU 来源明细"); diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryServiceTest.java index d568b68ae..8ce4717df 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/returnreceipt/service/ReturnInventoryServiceTest.java @@ -623,6 +623,32 @@ class ReturnInventoryServiceTest { assertThrows(ResponseStatusException.class, () -> service.confirmLabel(new PdaWarehouseIdentity("operator-2", "其他仓", 43L), "RC-SOURCE")); } + @Test + void existingTargetSeedsOriginalOwnershipIncludingPreviouslyRemovedQuantity() { + var source = prepareConcurrentSource(); + source.setCountStatus("CONFIRMED"); + var target = new ReturnInventoryCarton(); target.setId(32L); target.setCartonMark("TARGET"); + target.setCustomerId("10001"); target.setOverseasWarehouseId("42"); target.setSourceReturnNo("RT-1"); + target.setSourceBatchNo("RB-1"); target.setStatus("AVAILABLE"); target.setCountStatus("CONFIRMED"); + target.setTotalQuantity(15L); target.setSkuTypes(1); + var sourceLine = item(41L, "SKU-A", 5); var targetLine = item(42L, "SKU-A", 15); + when(cartons.lockMark("TARGET")).thenReturn(target); + when(cartonItems.lockCarton(31L)).thenReturn(List.of(sourceLine)); + when(cartonItems.lockCarton(32L)).thenReturn(List.of(targetLine)); + when(cartonItems.lockSku(32L, "SKU-A")).thenReturn(targetLine); + when(cartonItems.listCarton(32L)).thenReturn(List.of(targetLine)); + when(cartonItems.totalQuantity(32L)).thenAnswer(ignored -> targetLine.getQuantity()); + when(cartonItems.skuTypes(32L)).thenReturn(1); + when(packingTrace.netTrackedQuantity("10001", "TARGET", "SKU-A")).thenReturn(-5L); + when(balances.adjustCartonQuantity(anyString(), anyString(), anyString(), anyLong())).thenReturn(1); + ReflectionTestUtils.invokeMethod(service, "mergeScoped", new PdaWarehouseIdentity("worker", "worker", 42L), + new ReturnInventoryRequests.Merge(List.of("RT-1"), List.of(new ReturnInventoryRequests.ValidItem("SKU-A", 5)), + null, null, null, null, "target-reuse"), + java.util.Map.of("RC-SOURCE", new java.util.HashMap<>(java.util.Map.of("SKU-A", 5L))), "TARGET", null); + verify(packingTrace).insert(anyLong(), eq("10001"), anyLong(), eq(""), eq("TARGET"), eq("RT-1"), eq("SKU-A"), eq(20L), any()); + assertThat(target.getTotalQuantity()).isEqualTo(20L); + } + private ReturnInventoryCarton prepareConcurrentSource() { ReturnReceipt receipt = new ReturnReceipt(); receipt.setId(21L); ReturnInventoryCarton snapshot = new ReturnInventoryCarton();