|
|
@ -429,7 +429,6 @@ public class HaiAnSearchIssureNotifyServiceImpl implements HaiAnSearchIssureNoti |
|
|
enrichOrderFields(row, order, area); |
|
|
enrichOrderFields(row, order, area); |
|
|
row.setOrderSatisfactionStatus(inventoryComplete && targetAreaValid ? "COMPLETE" : "INCOMPLETE"); |
|
|
row.setOrderSatisfactionStatus(inventoryComplete && targetAreaValid ? "COMPLETE" : "INCOMPLETE"); |
|
|
} |
|
|
} |
|
|
copySummaryQuantities(orderRows, summaryRows); |
|
|
|
|
|
if (!targetAreaValid) { |
|
|
if (!targetAreaValid) { |
|
|
HaiAnInventoryMatchResult targetFailure = createFailureRow(order, "TARGET_AREA", "业务目标区域未配置或缺少wcs_area_code", "TARGET_AREA"); |
|
|
HaiAnInventoryMatchResult targetFailure = createFailureRow(order, "TARGET_AREA", "业务目标区域未配置或缺少wcs_area_code", "TARGET_AREA"); |
|
|
enrichOrderFields(targetFailure, order, area); |
|
|
enrichOrderFields(targetFailure, order, area); |
|
|
@ -496,9 +495,144 @@ public class HaiAnSearchIssureNotifyServiceImpl implements HaiAnSearchIssureNoti |
|
|
response.setInventoryShortageOrderCount(shortageCount); |
|
|
response.setInventoryShortageOrderCount(shortageCount); |
|
|
response.setTargetAreaFailureOrderCount(targetAreaFailureCount); |
|
|
response.setTargetAreaFailureOrderCount(targetAreaFailureCount); |
|
|
response.setSummaryMessage("共" + orders.size() + "个订单,库存完整" + completeCount + "个,可推送" + pushableCount + "个"); |
|
|
response.setSummaryMessage("共" + orders.size() + "个订单,库存完整" + completeCount + "个,可推送" + pushableCount + "个"); |
|
|
|
|
|
// 将内部标签事件压缩成物料汇总和指定明细两类预览行,避免把推送所需的托盘级技术字段暴露给页面 - rqrq |
|
|
|
|
|
response.setRows(buildCompactPreviewRows(rows)); |
|
|
return response; |
|
|
return response; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* @author rqrq |
|
|
|
|
|
* @Description 将标签级匹配事件整理成紧凑预览:物料行显示总需求/总匹配,指定行显示本条指定需求/匹配,标签按格合并 - rqrq |
|
|
|
|
|
*/ |
|
|
|
|
|
private List<HaiAnInventoryMatchResult> buildCompactPreviewRows(List<HaiAnInventoryMatchResult> sourceRows) { |
|
|
|
|
|
List<HaiAnInventoryMatchResult> compactRows = new ArrayList<HaiAnInventoryMatchResult>(); |
|
|
|
|
|
if (sourceRows == null || sourceRows.isEmpty()) { |
|
|
|
|
|
return compactRows; |
|
|
|
|
|
} |
|
|
|
|
|
for (HaiAnInventoryMatchResult summary : sourceRows) { |
|
|
|
|
|
if (summary == null || !"SUMMARY".equalsIgnoreCase(StringUtils.defaultString(summary.getEventType()).trim())) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
HaiAnInventoryMatchResult materialRow = copyPreviewBase(summary); |
|
|
|
|
|
materialRow.setDisplayRowType("MATERIAL"); |
|
|
|
|
|
materialRow.setEventType("SUMMARY"); |
|
|
|
|
|
LinkedHashSet<String> materialSerialNos = new LinkedHashSet<String>(); |
|
|
|
|
|
Map<Integer, HaiAnInventoryMatchResult> specifiedRows = new LinkedHashMap<Integer, HaiAnInventoryMatchResult>(); |
|
|
|
|
|
Map<Integer, LinkedHashSet<String>> specifiedSerialNos = new LinkedHashMap<Integer, LinkedHashSet<String>>(); |
|
|
|
|
|
|
|
|
|
|
|
for (HaiAnInventoryMatchResult event : sourceRows) { |
|
|
|
|
|
if (!sameMaterial(summary, event)) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
boolean matchedEvent = isMatchedEvent(event); |
|
|
|
|
|
if (matchedEvent && StringUtils.isNotBlank(event.getSerialNo())) { |
|
|
|
|
|
materialSerialNos.add(event.getSerialNo().trim()); |
|
|
|
|
|
} |
|
|
|
|
|
if (event.getAllocSeq() == null) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
HaiAnInventoryMatchResult specifiedRow = specifiedRows.get(event.getAllocSeq()); |
|
|
|
|
|
if (specifiedRow == null) { |
|
|
|
|
|
specifiedRow = createSpecifiedPreviewRow(summary, event); |
|
|
|
|
|
specifiedRows.put(event.getAllocSeq(), specifiedRow); |
|
|
|
|
|
specifiedSerialNos.put(event.getAllocSeq(), new LinkedHashSet<String>()); |
|
|
|
|
|
} |
|
|
|
|
|
if (matchedEvent) { |
|
|
|
|
|
BigDecimal eventQty = event.getEventMatchedQty() == null ? BigDecimal.ZERO : event.getEventMatchedQty(); |
|
|
|
|
|
specifiedRow.setMatchedQty(specifiedRow.getMatchedQty().add(eventQty)); |
|
|
|
|
|
if (StringUtils.isNotBlank(event.getSerialNo())) { |
|
|
|
|
|
specifiedSerialNos.get(event.getAllocSeq()).add(event.getSerialNo().trim()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (StringUtils.isNotBlank(event.getFailureCode()) && StringUtils.isBlank(specifiedRow.getFailureCode())) { |
|
|
|
|
|
specifiedRow.setMatchStatus("FAILED"); |
|
|
|
|
|
specifiedRow.setFailureCode(event.getFailureCode()); |
|
|
|
|
|
specifiedRow.setFailureMessage(event.getFailureMessage()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
materialRow.setMatchedSerialNos(joinSerialNos(materialSerialNos)); |
|
|
|
|
|
compactRows.add(materialRow); |
|
|
|
|
|
for (Map.Entry<Integer, HaiAnInventoryMatchResult> entry : specifiedRows.entrySet()) { |
|
|
|
|
|
entry.getValue().setMatchedSerialNos(joinSerialNos(specifiedSerialNos.get(entry.getKey()))); |
|
|
|
|
|
compactRows.add(entry.getValue()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return compactRows; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* @author rqrq |
|
|
|
|
|
* @Description 复制前端预览需要的物料字段,明确排除托盘、位置、批次日期等推送内部字段 - rqrq |
|
|
|
|
|
*/ |
|
|
|
|
|
private HaiAnInventoryMatchResult copyPreviewBase(HaiAnInventoryMatchResult source) { |
|
|
|
|
|
HaiAnInventoryMatchResult target = new HaiAnInventoryMatchResult(); |
|
|
|
|
|
target.setSite(source.getSite()); |
|
|
|
|
|
target.setNotifyNo(source.getNotifyNo()); |
|
|
|
|
|
target.setItemNo(source.getItemNo()); |
|
|
|
|
|
target.setSoorderNo(source.getSoorderNo()); |
|
|
|
|
|
target.setBomItemNo(source.getBomItemNo()); |
|
|
|
|
|
target.setPartNo(source.getPartNo()); |
|
|
|
|
|
target.setRequiredQty(source.getRequiredQty()); |
|
|
|
|
|
target.setMatchedQty(source.getMatchedQty() == null ? BigDecimal.ZERO : source.getMatchedQty()); |
|
|
|
|
|
target.setMatchStatus(source.getMatchStatus()); |
|
|
|
|
|
target.setFailureCode(source.getFailureCode()); |
|
|
|
|
|
target.setFailureMessage(source.getFailureMessage()); |
|
|
|
|
|
target.setSpecifiedBlocked(source.getSpecifiedBlocked()); |
|
|
|
|
|
target.setOrderSatisfactionStatus(source.getOrderSatisfactionStatus()); |
|
|
|
|
|
target.setProductionArea(source.getProductionArea()); |
|
|
|
|
|
target.setAreaDesc(source.getAreaDesc()); |
|
|
|
|
|
target.setTargetAreaWcsCode(source.getTargetAreaWcsCode()); |
|
|
|
|
|
return target; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* @author rqrq |
|
|
|
|
|
* @Description 创建指定明细预览行,保留父物料键供排序和着色,页面负责将父级字段显示为空形成展开效果 - rqrq |
|
|
|
|
|
*/ |
|
|
|
|
|
private HaiAnInventoryMatchResult createSpecifiedPreviewRow(HaiAnInventoryMatchResult summary, |
|
|
|
|
|
HaiAnInventoryMatchResult event) { |
|
|
|
|
|
HaiAnInventoryMatchResult row = copyPreviewBase(summary); |
|
|
|
|
|
row.setDisplayRowType("SPECIFIED"); |
|
|
|
|
|
row.setEventType("SPECIFIED"); |
|
|
|
|
|
row.setAllocSeq(event.getAllocSeq()); |
|
|
|
|
|
row.setAllocType(event.getAllocType()); |
|
|
|
|
|
row.setRequiredQty(event.getRequiredQty() == null ? BigDecimal.ZERO : event.getRequiredQty()); |
|
|
|
|
|
row.setMatchedQty(BigDecimal.ZERO); |
|
|
|
|
|
row.setMatchStatus("MATCHED"); |
|
|
|
|
|
row.setFailureCode(null); |
|
|
|
|
|
row.setFailureMessage(null); |
|
|
|
|
|
if ("BATCH".equalsIgnoreCase(StringUtils.defaultString(event.getAllocType()).trim())) { |
|
|
|
|
|
row.setSpecifiedContent("批次:" + StringUtils.defaultString(event.getBatchNo())); |
|
|
|
|
|
} else { |
|
|
|
|
|
row.setSpecifiedContent("标签:" + StringUtils.defaultString(event.getSerialNo())); |
|
|
|
|
|
} |
|
|
|
|
|
return row; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* @author rqrq |
|
|
|
|
|
* @Description 判断事件是否属于同一订单物料行,防止相同物料编码跨BOM行合并标签 - rqrq |
|
|
|
|
|
*/ |
|
|
|
|
|
private boolean sameMaterial(HaiAnInventoryMatchResult summary, HaiAnInventoryMatchResult event) { |
|
|
|
|
|
return summary != null && event != null |
|
|
|
|
|
&& summary.getItemNo() != null && event.getItemNo() != null |
|
|
|
|
|
&& summary.getItemNo().compareTo(event.getItemNo()) == 0 |
|
|
|
|
|
&& sameText(summary.getBomItemNo(), event.getBomItemNo()) |
|
|
|
|
|
&& sameText(summary.getPartNo(), event.getPartNo()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* @author rqrq |
|
|
|
|
|
* @Description 按匹配顺序合并标签号,空集合返回空文本避免页面显示null - rqrq |
|
|
|
|
|
*/ |
|
|
|
|
|
private String joinSerialNos(Set<String> serialNos) { |
|
|
|
|
|
if (serialNos == null || serialNos.isEmpty()) { |
|
|
|
|
|
return ""; |
|
|
|
|
|
} |
|
|
|
|
|
return StringUtils.join(serialNos.iterator(), "、"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
* @Description 创建统一失败事件,保证前端能定位失败阶段和订单 - rqrq |
|
|
* @Description 创建统一失败事件,保证前端能定位失败阶段和订单 - rqrq |
|
|
@ -533,35 +667,6 @@ public class HaiAnSearchIssureNotifyServiceImpl implements HaiAnSearchIssureNoti |
|
|
row.setTargetAreaWcsCode(area == null ? null : area.getWcsAreaCode()); |
|
|
row.setTargetAreaWcsCode(area == null ? null : area.getWcsAreaCode()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* @author rqrq |
|
|
|
|
|
* @Description 将物料summary数量复制到标签事件,保证前端查看任一匹配标签时仍能看到需求和差额 - rqrq |
|
|
|
|
|
*/ |
|
|
|
|
|
private void copySummaryQuantities(List<HaiAnInventoryMatchResult> orderRows, |
|
|
|
|
|
List<HaiAnInventoryMatchResult> summaryRows) { |
|
|
|
|
|
for (HaiAnInventoryMatchResult row : orderRows) { |
|
|
|
|
|
if (row == null || "SUMMARY".equalsIgnoreCase(StringUtils.defaultString(row.getEventType()).trim())) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
HaiAnInventoryMatchResult summary = null; |
|
|
|
|
|
for (HaiAnInventoryMatchResult candidate : summaryRows) { |
|
|
|
|
|
if (sameText(row.getBomItemNo(), candidate.getBomItemNo()) |
|
|
|
|
|
&& sameText(row.getPartNo(), candidate.getPartNo())) { |
|
|
|
|
|
summary = candidate; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (summary != null) { |
|
|
|
|
|
row.setRequiredQty(summary.getRequiredQty()); |
|
|
|
|
|
row.setSpecifiedQty(summary.getSpecifiedQty()); |
|
|
|
|
|
row.setSpecifiedMatchedQty(summary.getSpecifiedMatchedQty()); |
|
|
|
|
|
row.setFallbackMatchedQty(summary.getFallbackMatchedQty()); |
|
|
|
|
|
row.setMatchedQty(summary.getMatchedQty()); |
|
|
|
|
|
row.setShortageQty(summary.getShortageQty()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
* @Description 比较SQL返回的可空文本,避免BOM或物料为空时复制错物料汇总 - rqrq |
|
|
* @Description 比较SQL返回的可空文本,避免BOM或物料为空时复制错物料汇总 - rqrq |
|
|
|