✨ 配载提交与重新派单按项目实时配置逐张推导子运单状态并清除接单事实

This commit is contained in:
2026-10-18 14:27:44 +08:00
parent 543a690902
commit f684666a01
2 changed files with 538 additions and 4 deletions
@@ -28,7 +28,9 @@ import org.springblade.transport.pojo.vo.LoadingCarrierContractVO;
import org.springblade.transport.pojo.vo.LoadingManageVO;
import org.springblade.transport.service.IContractManageService;
import org.springblade.transport.service.ILoadingManageService;
import org.springblade.transport.service.IProcessConfigService;
import org.springblade.transport.service.IReceivablePayableDetailService;
import org.springblade.transport.support.LiveProcessConfigSupport;
import org.springblade.transport.support.TransportBusinessSupport;
import org.springblade.transport.support.WaybillProcessSupport;
import org.springblade.transport.wrapper.LoadingManageWrapper;
@@ -43,8 +45,10 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -76,6 +80,9 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
@Lazy
private IReceivablePayableDetailService receivablePayableDetailService;
@Resource
private IProcessConfigService processConfigService;
@Override
public IPage<LoadingManageVO> selectLoadingManagePage(IPage<LoadingManage> page, LoadingManageVO loadingManage) {
IPage<LoadingManage> entityPage = page(page, buildQuery(loadingManage));
@@ -163,7 +170,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
validateCarrierContract(loadingManage, true);
boolean result = saveOrUpdate(loadingManage);
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
writeWaybillsForDriver(loadingManage, oldWaybillIds);
return result;
}
@@ -412,8 +419,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
validateCarrierContract(loadingManage, true);
boolean result = updateById(loadingManage);
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
clearAssociatedWaybillAcceptRecords(loadingManage);
writeWaybillsForDriver(loadingManage, oldWaybillIds);
return result;
}
@@ -819,7 +825,59 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
.orderByDesc(ContractManage::getCreateTime));
}
/**
* 配载提交与重新派单共用:子运单状态逐张按该票自己项目的实时过程配置推导后落库,再清除接单事实。
* <p>
* 推导按「接单事实已清、尚未接单」的口径取值,故清接单事实放在状态写入之后,两者口径一致。
*/
private void writeWaybillsForDriver(LoadingManage loadingManage, List<Long> oldWaybillIds) {
syncAssociatedWaybills(loadingManage,
deriveWaybillBusinessStatuses(waybillIds(loadingManage.getWaybillIdsJson())), oldWaybillIds);
// 接单事实不清,被拒的票对新司机不可见——司机端一切入口都排除已拒绝的运单
clearAssociatedWaybillAcceptRecords(loadingManage);
}
/**
* 子运单业务状态逐张按各自项目的实时过程配置推导:需要接单 → 待执行,不需要 → 进行中。
* <p>
* 配置取法与运单读路径同一处:项目生效配置优先,取不到时才回退该运单的过程配置快照;
* 快照只作兜底、永不优先,否则项目改配置后写入值与读时的归一化结果会分叉。
* 项目为空且快照也为空 → 视为不需要接单 → 进行中。
*/
private Map<Long, String> deriveWaybillBusinessStatuses(List<Long> waybillIds) {
Map<Long, String> businessStatusByWaybillId = new LinkedHashMap<>();
if (Func.isEmpty(waybillIds)) {
return businessStatusByWaybillId;
}
List<Waybill> waybills = waybillMapper.selectList(Wrappers.<Waybill>lambdaQuery()
.select(Waybill::getId, Waybill::getProjectId, Waybill::getProcessJson)
.eq(Waybill::getIsDeleted, 0)
.in(Waybill::getId, waybillIds));
// 一次查全所有项目的生效配置,不逐张回查
Map<Long, String> liveConfigByProject = LiveProcessConfigSupport.byProjects(processConfigService,
waybills.stream().map(Waybill::getProjectId).toList());
for (Waybill waybill : waybills) {
String processJson = LiveProcessConfigSupport.resolve(
liveConfigByProject.get(waybill.getProjectId()), waybill.getProcessJson());
// 以「待执行 + 待接单」为输入走读路径同一个归一化:需要接单留下待执行,不需要接单提升为进行中
businessStatusByWaybillId.put(waybill.getId(), WaybillProcessSupport.normalizeBusinessStatus(
STATUS_PENDING, processJson, WaybillProcessSupport.ACCEPT_PENDING));
}
return businessStatusByWaybillId;
}
private void syncAssociatedWaybills(LoadingManage loadingManage, String status, List<Long> oldWaybillIds) {
Map<Long, String> statusByWaybillId = new LinkedHashMap<>();
for (Long waybillId : waybillIds(loadingManage.getWaybillIdsJson())) {
statusByWaybillId.put(waybillId, status);
}
syncAssociatedWaybills(loadingManage, statusByWaybillId, oldWaybillIds);
}
/**
* 逐张写状态:同状态的票合成一条批量更新,配载字段对每张票都写全。
*/
private void syncAssociatedWaybills(LoadingManage loadingManage, Map<Long, String> statusByWaybillId, List<Long> oldWaybillIds) {
List<Long> newWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
if (Func.isNotEmpty(oldWaybillIds)) {
List<Long> removedIds = new ArrayList<>(oldWaybillIds);
@@ -829,8 +887,18 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
if (Func.isEmpty(newWaybillIds)) {
return;
}
Map<String, List<Long>> waybillIdsByStatus = new LinkedHashMap<>();
for (Long waybillId : newWaybillIds) {
waybillIdsByStatus
.computeIfAbsent(statusByWaybillId.getOrDefault(waybillId, STATUS_PENDING), key -> new ArrayList<>())
.add(waybillId);
}
waybillIdsByStatus.forEach((status, ids) -> updateAssociatedWaybillFields(loadingManage, ids, status));
}
private void updateAssociatedWaybillFields(LoadingManage loadingManage, List<Long> waybillIds, String status) {
waybillMapper.update(null, Wrappers.<Waybill>lambdaUpdate()
.in(Waybill::getId, newWaybillIds)
.in(Waybill::getId, waybillIds)
.set(Waybill::getLoadingNo, loadingManage.getLoadingNo())
.set(Waybill::getBusinessStatus, status)
.set(Waybill::getCarrierType, loadingManage.getCarrierType())