fix(firstleg): continue same-plan loading allocations
This commit is contained in:
@@ -79,12 +79,19 @@ import com.baiyue.firstleg.dto.SmartLoadingDtos.Candidate; import org.apache.iba
|
||||
WHERE inbound_detail_id IS NOT NULL AND package_count>0
|
||||
GROUP BY tenant_id,measurement_id,inbound_detail_id
|
||||
) i ON i.tenant_id=o.tenant_id AND i.measurement_id=m.id
|
||||
WHERE o.warehouse_id=#{warehouseId} AND o.id=#{inboundId} AND o.process_status='WAIT_SPLIT'
|
||||
WHERE o.warehouse_id=#{warehouseId} AND o.id=#{inboundId}
|
||||
AND (o.process_status='WAIT_SPLIT' OR (o.process_status='LOADING' AND EXISTS (
|
||||
SELECT 1 FROM fl_loading_plan_item same_plan_item
|
||||
WHERE same_plan_item.loading_plan_id=#{planId}
|
||||
AND same_plan_item.account_id=o.tenant_id
|
||||
AND same_plan_item.inbound_id=o.id
|
||||
AND same_plan_item.deleted=0
|
||||
)))
|
||||
AND o.actual_gross_weight_kg IS NOT NULL AND o.actual_net_weight_kg IS NOT NULL
|
||||
AND (o.inbound_role='MASTER' OR (o.split_purpose='REMAINDER' AND o.split_status='NOT_SPLIT'))
|
||||
AND i.inbound_detail_id=#{detailId}
|
||||
ORDER BY m.id DESC LIMIT 1 FOR UPDATE
|
||||
""")
|
||||
Candidate candidate(@Param("warehouseId") long warehouseId,@Param("inboundId") long inboundId,
|
||||
@Param("detailId") long detailId);
|
||||
Candidate candidate(@Param("planId") long planId,@Param("warehouseId") long warehouseId,
|
||||
@Param("inboundId") long inboundId,@Param("detailId") long detailId);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ public class SmartLoadingRepository {
|
||||
@Resource private InboundOrderMapper inbounds;
|
||||
|
||||
public List<Candidate> candidates(long warehouseId) { return candidates.candidates(warehouseId); }
|
||||
public Candidate candidate(long warehouseId, long inboundId, long detailId) {
|
||||
return candidates.candidate(warehouseId, inboundId, detailId);
|
||||
public Candidate candidate(long planId, long warehouseId, long inboundId, long detailId) {
|
||||
return candidates.candidate(planId, warehouseId, inboundId, detailId);
|
||||
}
|
||||
public InboundOrderEntity inbound(long accountId, long inboundId) {
|
||||
return inbounds.selectOne(new LambdaQueryWrapper<InboundOrderEntity>()
|
||||
|
||||
@@ -132,7 +132,8 @@ public class SmartLoadingService {
|
||||
if (replay != null) return replay;
|
||||
LoadingPlanEntity plan = editing(planId, request.expectedVersion(), operatorId, operatorName);
|
||||
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
|
||||
Candidate candidate = repository.candidate(booking.getWarehouseId(), request.inboundId(), request.inboundDetailId());
|
||||
Candidate candidate = repository.candidate(planId, booking.getWarehouseId(), request.inboundId(),
|
||||
request.inboundDetailId());
|
||||
if (candidate == null) throw conflict("入库货物不存在或尚未完成入库");
|
||||
requireSameChannel(booking, candidate);
|
||||
requireSameCustomerScope(booking, candidate);
|
||||
@@ -307,7 +308,8 @@ public class SmartLoadingService {
|
||||
throw conflict("计划箱数不能低于已拣货箱数");
|
||||
}
|
||||
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
|
||||
Candidate candidate = repository.candidate(booking.getWarehouseId(), item.getInboundId(), item.getInboundDetailId());
|
||||
Candidate candidate = repository.candidate(planId, booking.getWarehouseId(), item.getInboundId(),
|
||||
item.getInboundDetailId());
|
||||
if (candidate == null || request.packageCount() > candidate.availablePackageCount() + item.getPackageCount()) throw validation("调整箱数超过可用箱数");
|
||||
requireSameChannel(booking, candidate);
|
||||
requireSameCustomerScope(booking, candidate);
|
||||
|
||||
+7
-1
@@ -44,7 +44,7 @@ class SmartLoadingCandidateMapperContractTest {
|
||||
@Test
|
||||
void detailUsesSameBatchRule() throws Exception {
|
||||
Method detail = SmartLoadingCandidateMapper.class.getDeclaredMethod(
|
||||
"candidate", long.class, long.class, long.class);
|
||||
"candidate", long.class, long.class, long.class, long.class);
|
||||
String sql = String.join(" ", detail.getAnnotation(Select.class).value());
|
||||
|
||||
assertThat(sql)
|
||||
@@ -53,6 +53,12 @@ class SmartLoadingCandidateMapperContractTest {
|
||||
.contains("SELECT MAX(m2.id)")
|
||||
.contains("o.warehouse_id=#{warehouseId}")
|
||||
.contains("o.process_status='WAIT_SPLIT'")
|
||||
.contains("o.process_status='LOADING'")
|
||||
.contains("same_plan_item.loading_plan_id=#{planId}")
|
||||
.contains("same_plan_item.account_id=o.tenant_id")
|
||||
.contains("same_plan_item.inbound_id=o.id")
|
||||
.contains("same_plan_item.deleted=0")
|
||||
.doesNotContain("o.process_status IN ('WAIT_SPLIT','LOADING')")
|
||||
.contains("unitGrossWeightKg")
|
||||
.contains("unitNetWeightKg")
|
||||
.doesNotContain("i.unit_weight_kg")
|
||||
|
||||
@@ -242,7 +242,7 @@ class SmartLoadingServiceTest {
|
||||
LoadingPlanEntity plan = plan("EDITING", 0);
|
||||
when(repository.plan(1)).thenReturn(plan);
|
||||
when(repository.booking(99L)).thenReturn(booking());
|
||||
when(repository.candidate(100, 10, 20)).thenReturn(candidate(5));
|
||||
when(repository.candidate(1, 100, 10, 20)).thenReturn(candidate(5));
|
||||
when(repository.activeItem(1L, 9L, 20L)).thenReturn(item(7, 9, 20, 4));
|
||||
|
||||
BizException error = catchThrowableOfType(() -> service.assign(1,
|
||||
@@ -259,7 +259,7 @@ class SmartLoadingServiceTest {
|
||||
linked.setCustomerId(88L);
|
||||
when(repository.plan(1L)).thenReturn(plan);
|
||||
when(repository.booking(99L)).thenReturn(linked);
|
||||
when(repository.candidate(100L, 10L, 20L)).thenReturn(candidate(5));
|
||||
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(candidate(5));
|
||||
|
||||
BizException error = catchThrowableOfType(() -> service.assign(1L,
|
||||
new AssignRequest(10L, 20L, 1, 0, "assign-customer-mismatch"), 7L, "u"), BizException.class);
|
||||
@@ -357,7 +357,7 @@ class SmartLoadingServiceTest {
|
||||
when(repository.booking(99)).thenReturn(booking());
|
||||
when(repository.touch(1, 5, 7, "u")).thenReturn(1);
|
||||
when(repository.items(1)).thenReturn(List.of());
|
||||
when(repository.candidate(100, 10, 20)).thenReturn(candidate(10));
|
||||
when(repository.candidate(1, 100, 10, 20)).thenReturn(candidate(10));
|
||||
when(repository.activeItem(1L, 9L, 20L)).thenReturn(null);
|
||||
when(loadingPickService.mutationSnapshot(1L)).thenReturn(
|
||||
new LoadingPickService.MutationSnapshot(77L, "LOADING", 6, Map.of()));
|
||||
@@ -368,6 +368,7 @@ class SmartLoadingServiceTest {
|
||||
Plan result = service.assign(1, new AssignRequest(10L, 20L, 1, 5, "assign-loading"), 7, "u");
|
||||
|
||||
assertThat(result.status()).isEqualTo("LOADING");
|
||||
verify(repository).candidate(1L, 100L, 10L, 20L);
|
||||
var order = inOrder(loadingPickService, splitPreloadService, repository, loadingModelBridge);
|
||||
order.verify(loadingPickService).lockMutable(1L);
|
||||
order.verify(splitPreloadService).ensureForRunningLoadingAllocation(9L, 10L, 7L, "u");
|
||||
@@ -393,7 +394,7 @@ class SmartLoadingServiceTest {
|
||||
Plan result = service.assign(1, request, 7, "u");
|
||||
|
||||
assertThat(result.status()).isEqualTo("LOADING");
|
||||
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong());
|
||||
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong(), anyLong());
|
||||
verify(cargoClient, never()).detail(anyString(), anyLong(), anyLong(), anyLong());
|
||||
}
|
||||
|
||||
@@ -592,7 +593,7 @@ class SmartLoadingServiceTest {
|
||||
when(repository.plan(1L)).thenReturn(plan, plan("LOADING", 3));
|
||||
when(repository.item(1L, 8L)).thenReturn(line);
|
||||
when(repository.booking(99L)).thenReturn(booking());
|
||||
when(repository.candidate(100L, 10L, 20L)).thenReturn(candidate(10));
|
||||
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(candidate(10));
|
||||
when(repository.items(1L)).thenReturn(List.of(line));
|
||||
when(repository.touch(1L, 2, 7L, "u")).thenReturn(1);
|
||||
when(repository.update(line)).thenReturn(1);
|
||||
@@ -617,7 +618,7 @@ class SmartLoadingServiceTest {
|
||||
new AdjustRequest(1, 2, 0, "adjust-picked"), 7L, "u"))
|
||||
.hasMessageContaining("不能低于已拣货箱数");
|
||||
|
||||
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong());
|
||||
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong(), anyLong());
|
||||
verify(repository, never()).touch(anyLong(), anyInt(), anyLong(), anyString());
|
||||
}
|
||||
|
||||
@@ -878,7 +879,7 @@ class SmartLoadingServiceTest {
|
||||
when(repository.plan(1)).thenReturn(plan, plan("EDITING", 1));
|
||||
when(repository.booking(99)).thenReturn(booking());
|
||||
when(repository.items(1)).thenReturn(List.of());
|
||||
when(repository.candidate(100, 10, 20)).thenReturn(candidate(10));
|
||||
when(repository.candidate(1, 100, 10, 20)).thenReturn(candidate(10));
|
||||
when(repository.activeItem(1L, 9L, 20L)).thenReturn(null);
|
||||
when(repository.touch(1, 0, 7, "u")).thenReturn(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user