🐛 恢复合并时丢失的司机端自动完成、地点回退与拒单脱离
合并 websoft/dev 解冲突时 DriverWaybillServiceImpl 整段退回旧版,丢掉三处功能,按原提交补回: - 末位打卡是到货/卸货/签收且回单无需确认时自动完成运单 - 导入运单只有详细地址、没有地点名称时回退显示地址 - 司机拒单后该运单对其列表/计数/详情/打卡/接单全部不可达 归属校验测试原按手机号匹配运单,与打卡、接单的车牌口径冲突,改为按司机档案绑定的车牌断言。
This commit is contained in:
+69
-16
@@ -114,6 +114,10 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
private static final List<String> TAB_ALL_STATUSES = Arrays.asList(
|
||||
STATUS_PENDING, STATUS_WAITING_DISPATCH, STATUS_DISPATCHING, STATUS_RUNNING, STATUS_COMPLETED
|
||||
);
|
||||
/** 允许完成运单的业务状态 */
|
||||
private static final List<String> COMPLETABLE_STATUSES = Arrays.asList(
|
||||
STATUS_RUNNING, STATUS_PENDING, STATUS_WAITING_DISPATCH, STATUS_DISPATCHING
|
||||
);
|
||||
|
||||
private static final int DEFAULT_PREVIEW_SIZE = 2;
|
||||
private static final int MAX_PREVIEW_SIZE = 20;
|
||||
@@ -313,7 +317,8 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
throw new ServiceException("运单ID不能为空");
|
||||
}
|
||||
Driver driver = requireCurrentDriver();
|
||||
Waybill waybill = loadDriverWaybill(dto.getWaybillId(), currentBoundPlates(driver));
|
||||
// 在途打卡单独保留原取单判据,不排除已拒单(见 scopedQuery 的重载说明)
|
||||
Waybill waybill = loadDriverWaybill(dto.getWaybillId(), currentBoundPlates(driver), true);
|
||||
waybill = normalizeAcceptStatus(waybill);
|
||||
|
||||
String processJson = resolveProcessJson(waybill);
|
||||
@@ -415,7 +420,20 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
nodePunchMapper.insert(punch);
|
||||
|
||||
advanceCurrentProcessNode(waybill, nodeCfg);
|
||||
return toNodePunchVO(punch);
|
||||
// 末位打卡节点是到货/卸货/签收、且回单无需确认完成时,本次打卡一并把运单置为完成;
|
||||
// isLastDriverPunchNode 与 returnNeedsNoConfirmation 传的就是上面那份 processJson,未再调 resolveProcessJson 取过程配置。
|
||||
String nodeKey = WaybillProcessSupport.nodeKey(nodeCfg);
|
||||
String nodeName = WaybillProcessSupport.nodeName(nodeCfg);
|
||||
boolean completed = false;
|
||||
if (WaybillProcessSupport.isLastDriverPunchNode(processJson, nodeKey)
|
||||
&& WaybillProcessSupport.isDeliveryNode(nodeKey, nodeName)
|
||||
&& WaybillProcessSupport.returnNeedsNoConfirmation(processJson)
|
||||
&& canAutoCompleteWaybill(waybill)) {
|
||||
completed = waybillService.completeWithoutDeptCheck(waybill.getId());
|
||||
}
|
||||
DriverNodePunchVO vo = toNodePunchVO(punch);
|
||||
vo.setWaybillCompleted(completed);
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -502,10 +520,7 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
Driver driver = requireCurrentDriver();
|
||||
Waybill waybill = loadDriverWaybill(id, currentBoundPlates(driver));
|
||||
waybill = normalizeAcceptStatus(waybill);
|
||||
if (!STATUS_RUNNING.equals(waybill.getBusinessStatus())
|
||||
&& !STATUS_PENDING.equals(waybill.getBusinessStatus())
|
||||
&& !STATUS_WAITING_DISPATCH.equals(waybill.getBusinessStatus())
|
||||
&& !STATUS_DISPATCHING.equals(waybill.getBusinessStatus())) {
|
||||
if (!COMPLETABLE_STATUSES.contains(waybill.getBusinessStatus())) {
|
||||
throw new ServiceException("当前运单状态不允许完成");
|
||||
}
|
||||
// 有未了结异常时不允许完成——完成接口不要求节点全部打卡,不挡住就能绕过打卡门禁
|
||||
@@ -524,6 +539,10 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
if (WaybillProcessSupport.isAccepted(waybill.getDriverAcceptStatus())) {
|
||||
throw new ServiceException("该运单已接单");
|
||||
}
|
||||
// 拒单后运单已对本人脱离,不给自己接回来的入口;要改主意只能由调度重新派单
|
||||
if (WaybillProcessSupport.isRejected(waybill.getDriverAcceptStatus())) {
|
||||
throw new ServiceException("该运单已拒单,请联系调度重新派单");
|
||||
}
|
||||
}
|
||||
|
||||
private void assertRejectable(Waybill waybill) {
|
||||
@@ -539,13 +558,19 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
}
|
||||
|
||||
private Waybill loadDriverWaybill(Long id, List<String> plates) {
|
||||
return loadDriverWaybill(id, plates, false);
|
||||
}
|
||||
|
||||
/** @param includeRejected 仅 submitEnroute 传 true,见 scopedQuery 的重载说明 */
|
||||
private Waybill loadDriverWaybill(Long id, List<String> plates, boolean includeRejected) {
|
||||
if (id == null) {
|
||||
throw new ServiceException("运单ID不能为空");
|
||||
}
|
||||
if (plates.isEmpty()) {
|
||||
throw new ServiceException("当前司机未绑定车辆");
|
||||
}
|
||||
Waybill waybill = waybillService.getOne(scopedQuery(plates).eq(Waybill::getId, id).last("LIMIT 1"));
|
||||
Waybill waybill = waybillService.getOne(scopedQuery(plates, includeRejected)
|
||||
.eq(Waybill::getId, id).last("LIMIT 1"));
|
||||
if (waybill == null) {
|
||||
throw new ServiceException("运单不存在或无权操作");
|
||||
}
|
||||
@@ -577,8 +602,7 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
}
|
||||
switch (status) {
|
||||
case 0 -> wrapper.in(Waybill::getBusinessStatus, PENDING_STATUSES);
|
||||
case 1 -> wrapper.in(Waybill::getBusinessStatus, List.of(STATUS_RUNNING, STATUS_PENDING,
|
||||
STATUS_WAITING_DISPATCH, STATUS_DISPATCHING));
|
||||
case 1 -> wrapper.in(Waybill::getBusinessStatus, COMPLETABLE_STATUSES);
|
||||
case 2 -> wrapper.eq(Waybill::getBusinessStatus, STATUS_COMPLETED);
|
||||
case 3 -> wrapper.eq(Waybill::getBusinessStatus, STATUS_CANCELLED);
|
||||
default -> wrapper.in(Waybill::getBusinessStatus, TAB_ALL_STATUSES);
|
||||
@@ -602,11 +626,23 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 司机可见运单范围:运单车牌(主车/挂车)落在当前司机绑定车牌内。
|
||||
* 绑定来源:blade_transport_driver.driving_vehicle
|
||||
* 司机可见运单范围:运单车牌(主车/挂车)落在当前司机绑定车牌内,
|
||||
* 且该运单未被这个司机拒单。绑定来源:blade_transport_driver.driving_vehicle
|
||||
* <p>
|
||||
* 拒单后运单对司机彻底脱离——列表、计数、详情、打卡、接单一律不可达,等管理员重新派单。
|
||||
* 运单上的司机姓名/手机/车牌不清空,调度重新派单时要知道原来派给谁。
|
||||
*/
|
||||
private LambdaQueryWrapper<Waybill> scopedQuery(List<String> plates) {
|
||||
return Wrappers.<Waybill>lambdaQuery().and(w -> {
|
||||
return scopedQuery(plates, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param includeRejected true 时不排除已拒单的运单,仅限在途打卡使用:
|
||||
* 拒单的运单不可能处于运输中,收口拦不到合法操作,
|
||||
* 而保留原判据可避免「已拒单 + 进行中」的历史脏数据被误伤
|
||||
*/
|
||||
private LambdaQueryWrapper<Waybill> scopedQuery(List<String> plates, boolean includeRejected) {
|
||||
LambdaQueryWrapper<Waybill> wrapper = Wrappers.<Waybill>lambdaQuery().and(w -> {
|
||||
w.in(Waybill::getVehicleNo, plates)
|
||||
.or().in(Waybill::getTrailerVehicleNo, plates);
|
||||
for (String plate : plates) {
|
||||
@@ -620,6 +656,11 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
);
|
||||
}
|
||||
});
|
||||
if (!includeRejected) {
|
||||
wrapper.and(w -> w.isNull(Waybill::getDriverAcceptStatus)
|
||||
.or().ne(Waybill::getDriverAcceptStatus, WaybillProcessSupport.ACCEPT_REJECTED));
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
private void applyKeyword(LambdaQueryWrapper<Waybill> wrapper, String keyword) {
|
||||
@@ -707,10 +748,12 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
DriverWaybillCardVO card = new DriverWaybillCardVO();
|
||||
card.setId(waybill.getId());
|
||||
card.setWaybillNo(waybill.getWaybillNo());
|
||||
card.setFromName(Func.toStr(waybill.getDepartureName(), ""));
|
||||
card.setToName(Func.toStr(waybill.getArrivalName(), ""));
|
||||
card.setFromAddress(Func.toStr(waybill.getDepartureAddress(), card.getFromName()));
|
||||
card.setToAddress(Func.toStr(waybill.getArrivalAddress(), card.getToName()));
|
||||
// 批量导入的运单只有发货/到货地址、没有地点名称,名称为空时回退到地址,
|
||||
// 否则司机端首页、运单列表与打卡页的地点位置都是空的
|
||||
card.setFromName(Func.toStrWithEmpty(waybill.getDepartureName(), Func.toStr(waybill.getDepartureAddress(), "")));
|
||||
card.setToName(Func.toStrWithEmpty(waybill.getArrivalName(), Func.toStr(waybill.getArrivalAddress(), "")));
|
||||
card.setFromAddress(Func.toStrWithEmpty(waybill.getDepartureAddress(), card.getFromName()));
|
||||
card.setToAddress(Func.toStrWithEmpty(waybill.getArrivalAddress(), card.getToName()));
|
||||
card.setCargoNames(splitCargoNames(waybill.getCargoName()));
|
||||
card.setCargoCategory(Func.toStr(waybill.getCargoType(), ""));
|
||||
card.setWeight(formatWeight(waybill.getQuantity(), waybill.getQuantityUnit()));
|
||||
@@ -1096,6 +1139,16 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
return countByType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动完成的前置:与司机端「完成运单」同一套——业务状态允许完成,且没有未了结异常。
|
||||
* <p>
|
||||
* 不满足返回 false,由调用方静默跳过,打卡不受影响。
|
||||
*/
|
||||
private boolean canAutoCompleteWaybill(Waybill waybill) {
|
||||
return COMPLETABLE_STATUSES.contains(waybill.getBusinessStatus())
|
||||
&& unresolvedExceptionNodeCodeList(waybill.getId()).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言该运单没有未了结的异常。
|
||||
* <p>
|
||||
|
||||
Reference in New Issue
Block a user