fix(firstleg): explain coload group eligibility
This commit is contained in:
+5
-3
@@ -14,9 +14,11 @@ import static com.baiyue.firstleg.loading.coload.persistence.ColoadPersistenceRo
|
||||
@Mapper
|
||||
public interface ColoadGroupMapper {
|
||||
@Select({"<script>", """
|
||||
SELECT o.tenant_id tenantId,o.order_id orderId,o.id inboundId,
|
||||
o.process_status processStatus,o.warehouse_id warehouseId,
|
||||
o.channel_code channelCode,o.total_package_count fullPackageCount,
|
||||
SELECT o.tenant_id tenantId,o.order_id orderId,o.order_no orderNo,
|
||||
o.id inboundId,o.inbound_code inboundCode,o.process_status processStatus,
|
||||
o.warehouse_id warehouseId,o.warehouse_name warehouseName,
|
||||
o.channel_code channelCode,o.channel_name channelName,
|
||||
o.total_package_count fullPackageCount,
|
||||
(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,
|
||||
|
||||
+4
@@ -15,10 +15,14 @@ public final class ColoadPersistenceRows {
|
||||
public static class InboundCandidateRow {
|
||||
private Long tenantId;
|
||||
private Long orderId;
|
||||
private String orderNo;
|
||||
private Long inboundId;
|
||||
private String inboundCode;
|
||||
private String processStatus;
|
||||
private Long warehouseId;
|
||||
private String warehouseName;
|
||||
private String channelCode;
|
||||
private String channelName;
|
||||
private Integer fullPackageCount;
|
||||
private Integer activeAllocationCount;
|
||||
private Long activeGroupId;
|
||||
|
||||
+39
-19
@@ -237,35 +237,55 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort {
|
||||
.computeIfAbsent(row.getOrderId(), ignored -> new ArrayList<>()).add(row));
|
||||
List<InboundCandidateRow> resolved = new ArrayList<>();
|
||||
for (Long orderId : orderIds) {
|
||||
List<InboundCandidateRow> eligible = byOrder.getOrDefault(orderId, List.of()).stream()
|
||||
.filter(row -> eligible(row, allowedGroupId)).toList();
|
||||
List<InboundCandidateRow> rows = byOrder.getOrDefault(orderId, List.of());
|
||||
if (rows.isEmpty()) throw conflict("所选订单不存在或已失效");
|
||||
List<InboundCandidateRow> eligible = rows.stream()
|
||||
.filter(row -> unavailableReason(row, allowedGroupId) == null).toList();
|
||||
if (eligible.isEmpty()) {
|
||||
throw conflict("订单 " + orderId + " 不存在可创建同柜不可拆组的可用入库片段");
|
||||
String order = StringUtils.hasText(rows.get(0).getOrderNo())
|
||||
? "订单“" + rows.get(0).getOrderNo().trim() + "”" : "所选订单";
|
||||
String reasons = rows.stream().map(row -> candidateLabel(row) + unavailableReason(row, allowedGroupId))
|
||||
.distinct().limit(10).collect(java.util.stream.Collectors.joining(";"));
|
||||
throw conflict(order + "当前没有可建组的入仓片段:" + reasons);
|
||||
}
|
||||
resolved.addAll(eligible);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
private boolean eligible(InboundCandidateRow row, Long allowedGroupId) {
|
||||
return row.getTenantId() != null && row.getTenantId() > 0
|
||||
&& row.getInboundId() != null && row.getInboundId() > 0
|
||||
&& "WAIT_SPLIT".equals(row.getProcessStatus())
|
||||
&& row.getFullPackageCount() != null && row.getFullPackageCount() > 0
|
||||
&& Objects.equals(row.getActiveAllocationCount(), 0)
|
||||
&& (row.getActiveGroupId() == null || Objects.equals(row.getActiveGroupId(), allowedGroupId));
|
||||
private String unavailableReason(InboundCandidateRow row, Long allowedGroupId) {
|
||||
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 (row.getActiveGroupId() != null && !Objects.equals(row.getActiveGroupId(), allowedGroupId)) {
|
||||
return "已在其他同柜组";
|
||||
}
|
||||
if (row.getFullPackageCount() == null || row.getFullPackageCount() <= 0) return "箱数无效";
|
||||
if (row.getWarehouseId() == null || row.getWarehouseId() <= 0
|
||||
|| !StringUtils.hasText(row.getWarehouseName())) return "缺少平台收货仓权威快照";
|
||||
if (!StringUtils.hasText(row.getChannelCode()) || !StringUtils.hasText(row.getChannelName())) {
|
||||
return "缺少渠道权威快照";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String candidateLabel(InboundCandidateRow row) {
|
||||
return StringUtils.hasText(row.getInboundCode())
|
||||
? "入仓码“" + row.getInboundCode().trim() + "”" : "入仓码缺失的片段";
|
||||
}
|
||||
|
||||
private void validateSameRoute(List<InboundCandidateRow> rows) {
|
||||
InboundCandidateRow first = rows.get(0);
|
||||
if (first.getWarehouseId() == null || first.getWarehouseId() <= 0
|
||||
|| !StringUtils.hasText(first.getChannelCode())) {
|
||||
throw conflict("订单缺少国内仓或渠道权威快照");
|
||||
}
|
||||
for (InboundCandidateRow row : rows) {
|
||||
if (!Objects.equals(first.getWarehouseId(), row.getWarehouseId())
|
||||
|| !normalized(first.getChannelCode()).equals(normalized(row.getChannelCode()))) {
|
||||
throw conflict("同柜不可拆组成员必须属于同一国内仓和渠道");
|
||||
if (!Objects.equals(first.getWarehouseId(), row.getWarehouseId())) {
|
||||
throw conflict(candidateLabel(first) + "(" + first.getWarehouseName() + ")与"
|
||||
+ candidateLabel(row) + "(" + row.getWarehouseName() + ")平台收货仓不同");
|
||||
}
|
||||
if (!normalized(first.getChannelCode()).equals(normalized(row.getChannelCode()))) {
|
||||
throw conflict(candidateLabel(first) + "(" + first.getChannelName() + ")与"
|
||||
+ candidateLabel(row) + "(" + row.getChannelName() + ")渠道不同");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,11 +380,11 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort {
|
||||
}
|
||||
|
||||
private static List<Long> normalizedOrderIds(List<Long> source, int minimum, int maximum) {
|
||||
if (source == null) throw badRequest("orderIds不能为空");
|
||||
if (source == null) throw badRequest("请选择需要设置为同柜不可拆组的订单");
|
||||
List<Long> values = source.stream().filter(Objects::nonNull).distinct().sorted().toList();
|
||||
if (values.size() != source.size() || values.size() < minimum || values.size() > maximum
|
||||
|| values.stream().anyMatch(value -> value <= 0)) {
|
||||
throw badRequest("orderIds数量、重复项或ID值不合法");
|
||||
throw badRequest("请选择" + minimum + "至" + maximum + "个不同的有效订单");
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user