This commit is contained in:
2026-09-20 14:43:26 +08:00
parent 398f4e6983
commit a7d458cddd
11 changed files with 356 additions and 23 deletions
@@ -22,6 +22,15 @@ public interface ColoadGroupMapper {
(SELECT COUNT(*) FROM fl_loading_plan_item item
WHERE item.account_id=o.tenant_id AND item.inbound_id=o.id AND item.deleted=0)
activeAllocationCount,
(SELECT COUNT(DISTINCT item.loading_plan_id) FROM fl_loading_plan_item item
WHERE item.account_id=o.tenant_id AND item.inbound_id=o.id AND item.deleted=0)
activeAllocationPlanCount,
(SELECT MIN(item.loading_plan_id) FROM fl_loading_plan_item item
WHERE item.account_id=o.tenant_id AND item.inbound_id=o.id AND item.deleted=0)
activeAllocationPlanId,
(SELECT COALESCE(SUM(item.package_count),0) FROM fl_loading_plan_item item
WHERE item.account_id=o.tenant_id AND item.inbound_id=o.id AND item.deleted=0)
activeAllocatedPackageCount,
(SELECT member.group_id FROM fl_coload_group_member member
WHERE member.tenant_id=o.tenant_id AND member.inbound_id=o.id
AND member.active_flag=1 LIMIT 1) activeGroupId
@@ -25,6 +25,9 @@ public final class ColoadPersistenceRows {
private String channelName;
private Integer fullPackageCount;
private Integer activeAllocationCount;
private Integer activeAllocationPlanCount;
private Long activeAllocationPlanId;
private Integer activeAllocatedPackageCount;
private Long activeGroupId;
}
@@ -35,6 +35,9 @@ import java.util.Set;
@Service
public class ColoadGroupService implements ColoadGroupAssignmentPort {
private static final Set<String> CURRENT_GROUP_STATUSES = Set.of("ACTIVE", "LOCKED", "CONSUMED");
private static final Set<String> PRE_LOADING_GROUP_STATUSES = Set.of(
"PREPARING", "WAIT_MEASURE", "MEASURING", "MEASURE_PENDING", "MEASURE_REJECTED",
"WAIT_PRICING", "FEE_CONFIRMING", "INBOUNDING", "WAIT_SPLIT");
@Resource
private ColoadGroupMapper mapper;
@@ -50,6 +53,7 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort {
List<InboundCandidateRow> candidates = authoritativeCandidates(orderIds, null);
validateSameRoute(candidates);
Long lockedPlanId = validateAllocationState(candidates);
long groupId = IdWorker.getId();
String groupNo = "CLG-" + groupId;
InboundCandidateRow first = candidates.get(0);
@@ -60,6 +64,14 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort {
candidate.getInboundId(), candidate.getFullPackageCount());
}
history(groupId, "CREATE", null, "ACTIVE", null, key, null, operatorId, operatorName);
if (lockedPlanId != null) {
if (mapper.lockToPlan(groupId, lockedPlanId, operatorId, trim(operatorName)) != 1) {
throw conflict("装柜中订单的同柜组锁定失败,请刷新后重试");
}
history(groupId, "LOCK", "ACTIVE", "LOCKED", lockedPlanId,
"CREATE-LOCK-" + sha256(key).substring(0, 48), null,
operatorId, operatorName);
}
complete(claim.commandId(), groupId);
return requiredSnapshot(groupId);
}
@@ -257,8 +269,10 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort {
if (row.getTenantId() == null || row.getTenantId() <= 0
|| row.getInboundId() == null || row.getInboundId() <= 0
|| !StringUtils.hasText(row.getInboundCode())) return "权威业务快照缺失";
if (!"WAIT_SPLIT".equals(row.getProcessStatus())) return "状态非待分柜";
if (!Objects.equals(row.getActiveAllocationCount(), 0)) return "已分配装柜计划";
if (!PRE_LOADING_GROUP_STATUSES.contains(row.getProcessStatus())
&& !"LOADING".equals(row.getProcessStatus())) {
return "状态不允许创建同柜组";
}
if (row.getActiveGroupId() != null && !Objects.equals(row.getActiveGroupId(), allowedGroupId)) {
return "已在其他同柜组";
}
@@ -271,6 +285,33 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort {
return null;
}
private Long validateAllocationState(List<InboundCandidateRow> rows) {
boolean hasAllocation = rows.stream().anyMatch(row -> !Objects.equals(row.getActiveAllocationCount(), 0));
boolean hasUnallocated = rows.stream().anyMatch(row -> Objects.equals(row.getActiveAllocationCount(), 0));
if (!hasAllocation) {
if (rows.stream().anyMatch(row -> "LOADING".equals(row.getProcessStatus()))) {
throw conflict("装柜中订单缺少有效装柜计划占用");
}
return null;
}
if (hasUnallocated) {
throw conflict("所选订单只有部分成员进入装柜计划,不能创建同柜组");
}
Long planId = null;
for (InboundCandidateRow row : rows) {
if (!Objects.equals(row.getActiveAllocationPlanCount(), 1)
|| row.getActiveAllocationPlanId() == null
|| !Objects.equals(row.getActiveAllocatedPackageCount(), row.getFullPackageCount())) {
throw conflict(candidateLabel(row) + "未完整分配到唯一装柜计划");
}
if (planId == null) planId = row.getActiveAllocationPlanId();
else if (!Objects.equals(planId, row.getActiveAllocationPlanId())) {
throw conflict("所选装柜中订单不在同一个装柜计划,不能创建同柜组");
}
}
return planId;
}
private static String candidateLabel(InboundCandidateRow row) {
return StringUtils.hasText(row.getInboundCode())
? "入仓码“" + row.getInboundCode().trim() + "”" : "入仓码缺失的片段";