perf(firstleg): streamline smart loading assignments

This commit is contained in:
2026-09-04 09:57:39 +08:00
parent b5be60140e
commit edadca18c6
6 changed files with 36 additions and 11 deletions
@@ -46,6 +46,7 @@ public final class SmartLoadingDtos { private SmartLoadingDtos(){}
}
public record WorkbenchContainer(Long bookingId, String bookingNo, String cabinetNo, String containerNo,
Long warehouseId, String warehouseName, String channelCode, String channelName, String containerType,
BigDecimal capacityCbm, BigDecimal maxWeightKg,
Long planId, String planNo, String planStatus, Integer version) {}
public record Candidate(Long accountId, Long inboundId, Long inboundDetailId, Long orderId, String orderNo, String inboundCode,
Long warehouseId, String channelCode, String channelName, Long destinationWarehouseId, String destinationWarehouseCode, String destinationWarehouseName, String customerName, String goodsName, Integer availablePackageCount,
@@ -252,7 +252,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ba
<script>
SELECT b.id bookingId,b.booking_no bookingNo,b.cabinet_no cabinetNo,b.container_no containerNo,
b.warehouse_id warehouseId,b.warehouse_name warehouseName,b.channel_code channelCode,
b.channel_name channelName,b.container_type containerType,p.id planId,p.plan_no planNo,
b.channel_name channelName,b.container_type containerType,b.capacity_cbm capacityCbm,
b.max_weight_kg maxWeightKg,p.id planId,p.plan_no planNo,
CASE WHEN p.id IS NULL OR NOT EXISTS (SELECT 1 FROM fl_loading_plan_item state_item
WHERE state_item.loading_plan_id=p.id AND state_item.deleted=0)
THEN 'WAIT_LOADING' ELSE p.plan_status END planStatus,b.version version
@@ -559,6 +559,12 @@ public class SmartLoadingService {
private Plan assignInbound(long planId, AssignInboundRequest request,
long operatorId, String operatorName, boolean wholeGroupAssignment) {
return assignInbound(planId, request, operatorId, operatorName, wholeGroupAssignment, null);
}
private Plan assignInbound(long planId, AssignInboundRequest request,
long operatorId, String operatorName, boolean wholeGroupAssignment,
List<Candidate> frozenDetails) {
String operation = operation(request.operationId());
String requestHash = sha256("ASSIGN_INBOUND|" + planId + '|' + request.inboundId() + '|'
+ request.packageCount() + '|' + request.expectedVersion());
@@ -574,8 +580,10 @@ public class SmartLoadingService {
}
LoadingPlanEntity plan = editing(planId, request.expectedVersion(), operatorId, operatorName);
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
List<Candidate> details = candidates(plan.getContainerBookingId(), booking.getWarehouseId()).stream()
.filter(candidate -> Objects.equals(candidate.inboundId(), request.inboundId())).toList();
List<Candidate> details = frozenDetails == null
? candidates(plan.getContainerBookingId(), booking.getWarehouseId()).stream()
.filter(candidate -> Objects.equals(candidate.inboundId(), request.inboundId())).toList()
: List.copyOf(frozenDetails);
if (details.isEmpty()) throw conflict("入仓码不存在、已分配完或尚未完成入库");
Candidate first = details.get(0);
if (!wholeGroupAssignment) requireStandalone(first.accountId(), first.inboundId());
@@ -708,21 +716,21 @@ public class SmartLoadingService {
if (replay != null) return replay;
LoadingPlanEntity plan = editing(planId, request.expectedVersion(), operatorId, operatorName);
ContainerBookingEntity booking = requireBooking(plan.getContainerBookingId());
Candidate selected = candidates(plan.getContainerBookingId(), booking.getWarehouseId()).stream()
.filter(candidate -> Objects.equals(candidate.inboundId(), request.inboundId()))
.findFirst().orElseThrow(() -> conflict("同柜不可拆组成员当前不可分配"));
GroupSnapshot discovered = requiredGroup(selected.accountId(), selected.inboundId());
InboundOrderEntity selected = repository.inbound(request.inboundId());
if (selected == null) throw conflict("同柜不可拆组成员当前不可分配");
GroupSnapshot discovered = requiredGroup(selected.getTenantId(), selected.getId());
Map<Long, List<Candidate>> memberCandidates = requireWholeGroupCandidates(
planId, booking, discovered, repository.items(planId));
GroupSnapshot locked = coloadGroups.lockWholeGroupForAssignment(selected.accountId(),
selected.inboundId(), planId, "LOCK-" + sha256(operation).substring(0, 48),
GroupSnapshot locked = coloadGroups.lockWholeGroupForAssignment(selected.getTenantId(),
selected.getId(), planId, "LOCK-" + sha256(operation).substring(0, 48),
operatorId, operatorName);
requireSameGroup(discovered, locked, planId);
for (Member member : locked.members()) {
LoadingPlanEntity current = repository.plan(planId);
assignInbound(planId, new AssignInboundRequest(member.inboundId(), member.fullPackageCount(),
current.getVersion(), "GRP-INB-" + sha256(operation + '|' + member.inboundId())
.substring(0, 48)), operatorId, operatorName, true);
.substring(0, 48)), operatorId, operatorName, true,
memberCandidates.get(member.inboundId()));
}
LoadingPlanEntity assigned = repository.plan(planId);
history(planId, null, "ADD_COLOAD_GROUP", plan.getPlanStatus(), assigned.getPlanStatus(), operation,