|
|
@@ -5496,9 +5496,7 @@ public class KwtWaybillOrderV1Service {
|
|
|
// 获取时间节点,并按前端五步序号排序(映射写入 orderStatus / orderStatusName)
|
|
|
List<WaybillOrderNodeVo.WaybillOrderNode> nodeList = getWaybillOrderNodes(voList);
|
|
|
log.info("查询运单节点轨迹,时间节点:{}", JSON.toJSONString(nodeList));
|
|
|
- // 将原始运单状态映射为前端五步时间轴阶段(1-5),并更新节点的状态码和名称
|
|
|
- applyTimelinePhaseFromWaybillStatus(nodeList);
|
|
|
- // 对映射后的节点列表按阶段去重,保留每个阶段最早的一条记录
|
|
|
+ // 按前端五步时间轴阶段去重,取满足状态中的最小原始状态对应时间
|
|
|
nodeList = dedupeWaybillOrderNodesByStatus(nodeList);
|
|
|
nodeList = nodeList.stream()
|
|
|
.sorted(Comparator.comparing(WaybillOrderNodeVo.WaybillOrderNode::getOrderStatus))
|
|
|
@@ -5590,20 +5588,76 @@ public class KwtWaybillOrderV1Service {
|
|
|
return nodeList;
|
|
|
}
|
|
|
return nodeList.stream()
|
|
|
- .filter(node -> node.getOrderStatus() != null)
|
|
|
- .collect(Collectors.toMap(
|
|
|
- WaybillOrderNodeVo.WaybillOrderNode::getOrderStatus,
|
|
|
- Function.identity(),
|
|
|
- (a, b) -> {
|
|
|
- Date ta = parseWaybillNodeCreateTime(a.getCreateTime());
|
|
|
- Date tb = parseWaybillNodeCreateTime(b.getCreateTime());
|
|
|
- return !ta.after(tb) ? a : b;
|
|
|
- }))
|
|
|
+ .filter(node -> Objects.nonNull(node.getOrderStatus()))
|
|
|
+ .collect(Collectors.groupingBy(node -> WaybillTimelinePhaseEnum.resolve(node.getOrderStatus())
|
|
|
+ .map(WaybillTimelinePhaseEnum::getPhaseOrder)
|
|
|
+ .orElse(node.getOrderStatus())))
|
|
|
.values()
|
|
|
.stream()
|
|
|
+ .map(KwtWaybillOrderV1Service::selectMinStatusEarliestNode)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
.collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 从同一前端时间轴阶段的节点列表中,筛选出用于展示的单一节点。
|
|
|
+ * <p>
|
|
|
+ * 处理逻辑:
|
|
|
+ * 1. 找出列表中原始状态码(orderStatus)最小的节点集合(通常代表该阶段最早触发的业务状态)。
|
|
|
+ * 2. 在最小状态码的节点中,选取创建时间(createTime)最早的一个节点。
|
|
|
+ * 3. 将选中节点的 orderStatus 和 orderStatusName 映射为前端时间轴所需的阶段序号和阶段名称。
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param nodes 属于同一前端展示阶段的运单节点列表
|
|
|
+ * @return 筛选后的单个节点对象,若列表为空或无有效数据则返回 null
|
|
|
+ */
|
|
|
+ private static WaybillOrderNodeVo.WaybillOrderNode selectMinStatusEarliestNode(
|
|
|
+ List<WaybillOrderNodeVo.WaybillOrderNode> nodes) {
|
|
|
+ // 1. 空值校验
|
|
|
+ if (CollectionUtils.isEmpty(nodes)) {
|
|
|
+ log.debug("selectMinStatusEarliestNode: 节点列表为空,返回 null");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 提取最小原始状态码
|
|
|
+ // 在同一阶段映射下,可能存在多个原始业务状态,取数值最小的作为基准(通常代表初始状态)
|
|
|
+ Integer minStatus = nodes.stream()
|
|
|
+ .map(WaybillOrderNodeVo.WaybillOrderNode::getOrderStatus)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .min(Integer::compareTo)
|
|
|
+ .orElse(null);
|
|
|
+
|
|
|
+ if (Objects.isNull(minStatus)) {
|
|
|
+ log.warn("selectMinStatusEarliestNode: 无法从节点列表中提取有效的最小状态码,节点数量: {}", nodes.size());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ log.debug("selectMinStatusEarliestNode: 提取到最小状态码: {}", minStatus);
|
|
|
+
|
|
|
+ // 3. 筛选具有最小状态码且创建时间最早的节点
|
|
|
+ WaybillOrderNodeVo.WaybillOrderNode selected = nodes.stream()
|
|
|
+ .filter(node -> Objects.equals(node.getOrderStatus(), minStatus))
|
|
|
+ .min(Comparator.comparing(node -> parseWaybillNodeCreateTime(node.getCreateTime())))
|
|
|
+ .orElse(null);
|
|
|
+
|
|
|
+ if (Objects.isNull(selected)) {
|
|
|
+ log.warn("selectMinStatusEarliestNode: 状态码为 {} 的节点中未找到有效创建时间的节点", minStatus);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ log.debug("selectMinStatusEarliestNode: 选中节点 ID: {}, 状态: {}, 创建时间: {}",
|
|
|
+ selected.getId(), selected.getOrderStatus(), selected.getCreateTime());
|
|
|
+
|
|
|
+ // 4. 映射前端时间轴阶段信息
|
|
|
+ // 将原始业务状态转换为前端展示用的阶段序号(phaseOrder)和阶段名称(phaseLabel)
|
|
|
+ WaybillTimelinePhaseEnum.resolve(minStatus).ifPresent(phase -> {
|
|
|
+ log.debug("selectMinStatusEarliestNode: 映射前端阶段,原始状态: {} -> 阶段序号: {}, 阶段名称: {}",
|
|
|
+ minStatus, phase.getPhaseOrder(), phase.getPhaseLabel());
|
|
|
+ selected.setOrderStatus(phase.getPhaseOrder());
|
|
|
+ selected.setOrderStatusName(phase.getPhaseLabel());
|
|
|
+ });
|
|
|
+
|
|
|
+ return selected;
|
|
|
+ }
|
|
|
+
|
|
|
private static Date parseWaybillNodeCreateTime(String createTime) {
|
|
|
if (org.apache.commons.lang3.StringUtils.isBlank(createTime)) {
|
|
|
return new Date(0L);
|