Merge branch 'feat/pending-return-confirm' into feat/rc-12

This commit is contained in:
2026-10-22 13:50:05 +08:00
8 changed files with 439 additions and 24 deletions
@@ -520,19 +520,32 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
nodePunchMapper.insert(punch);
advanceCurrentProcessNode(waybill, nodeCfg);
// 末位打卡节点是到货/卸货/签收、且回单无需确认完成时,本次打卡一并把运单置为完成;
// 末位打卡节点是到货/卸货/签收、且运单本身允许完成时,本次打卡就是运单的去向决定点:
// 回单无需确认 → 一并完成;回单需业务员确认 → 停在待回单确认等业务员确认。
// isLastDriverPunchNode 与 returnNeedsNoConfirmation 传的就是上面那份 processJson,未再调 resolveProcessJson 取过程配置。
String nodeKey = WaybillProcessSupport.nodeKey(nodeCfg);
String nodeName = WaybillProcessSupport.nodeName(nodeCfg);
String waybillBusinessStatus = waybill.getBusinessStatus();
boolean completed = false;
if (WaybillProcessSupport.isLastDriverPunchNode(processJson, nodeKey)
&& WaybillProcessSupport.isDeliveryNode(nodeKey, nodeName)
&& WaybillProcessSupport.returnNeedsNoConfirmation(processJson)
&& canAutoCompleteWaybill(waybill)) {
completed = waybillService.completeWithoutDeptCheck(waybill.getId());
if (WaybillProcessSupport.returnNeedsNoConfirmation(processJson)) {
completed = waybillService.completeWithoutDeptCheck(waybill.getId());
if (completed) {
waybillBusinessStatus = STATUS_COMPLETED;
}
} else if (WaybillProcessSupport.STATUS_RUNNING.equals(waybill.getBusinessStatus())) {
// 只有进行中能进入:canAutoCompleteWaybill 的状态口径含待执行/待调度等,不能替代这一条;
// 待回单确认在 isPunchEnded 里算已结束,不能从结束态重进。
waybill.setBusinessStatus(WaybillProcessSupport.STATUS_PENDING_RETURN_CONFIRM);
waybillService.updateById(waybill);
waybillBusinessStatus = WaybillProcessSupport.STATUS_PENDING_RETURN_CONFIRM;
}
}
DriverNodePunchVO vo = toNodePunchVO(punch);
vo.setWaybillCompleted(completed);
vo.setWaybillBusinessStatus(waybillBusinessStatus);
return vo;
}
@@ -531,6 +531,12 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
}
// 只有显式传 false 才是取消打卡,未传按已打卡处理
boolean punched = !Boolean.FALSE.equals(request.getPunched());
// 待回单确认的运单司机已无待打卡节点,再补一条打卡流水与状态含义矛盾;
// 漏打的出路是先取消该节点的打卡退回进行中(punched=false),再重新补录。
if (punched && WaybillProcessSupport.STATUS_PENDING_RETURN_CONFIRM
.equalsIgnoreCase(waybill.getBusinessStatus())) {
throw new ServiceException("运单待业务员确认回单,不能补录打卡");
}
if (ENROUTE_PUNCH_TYPE.equalsIgnoreCase(TransportBusinessSupport.trimToEmpty(request.getType()))) {
return saveEnroutePunchRecord(waybill, request, punched);
}
@@ -1062,10 +1068,11 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
waybill.setMasterNo(null);
waybill.setMileageRemark(null);
}
// 新建若已带业务状态(如复制提交已完成)则在过程校正后回写,保证与原运单一致
// 新建若已带业务状态(如复制提交已完成)则在过程校正后回写,保证与原运单一致;
// 编辑保存只改资料,business_status 以库里的值为准,请求体里的值不回写
String preservedBusinessStatus = created
? TransportBusinessSupport.trimToNull(waybill.getBusinessStatus())
: null;
: editPreservedBusinessStatus(oldRecord);
if (isCompletedBusinessStatus(preservedBusinessStatus)) {
preservedBusinessStatus = "completed";
}
@@ -1087,6 +1094,17 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
}
}
/**
* 编辑保存要回写的业务状态:取库里的值。
* 草稿返回 null —— submit 即正式提交,草稿须由过程校正提升为待执行 / 进行中。
*/
private String editPreservedBusinessStatus(Waybill oldRecord) {
String currentStatus = oldRecord == null
? null
: TransportBusinessSupport.trimToNull(oldRecord.getBusinessStatus());
return STATUS_DRAFT.equals(currentStatus) ? null : currentStatus;
}
private void fillCustomerName(Waybill waybill) {
if (Func.isNotEmpty(waybill.getContractId())) {
ContractManage contract = contractManageService.getById(waybill.getContractId());
@@ -49,6 +49,8 @@ public final class WaybillProcessSupport {
public static final String STATUS_PENDING = "pending";
public static final String STATUS_RUNNING = "running";
/** 司机已打完末位卡、回单需业务员确认,尚未生成应收应付 */
public static final String STATUS_PENDING_RETURN_CONFIRM = "pending_return_confirm";
public static final String ACCEPT_PENDING = "pending";
public static final String ACCEPT_ACCEPTED = "accepted";
public static final String ACCEPT_REJECTED = "rejected";
@@ -134,14 +136,16 @@ public final class WaybillProcessSupport {
}
/**
* 运单已结束:已完成或已取消。此后不再接受司机打卡。
* 运单已结束:已完成、已取消,或已打完末位卡停在待回单确认。此后不再接受司机打卡。
* <p>
* 只认这两个状态,大小写不敏感。草稿、待执行、待调度、调度中的运单司机仍要能打卡,
* 只认这三个状态,大小写不敏感。草稿、待执行、待调度、调度中的运单司机仍要能打卡,
* 所以不能按 {@link #isTerminalBusinessStatus} 的「终态或调度中间态」口径判定。
*/
public static boolean isPunchEnded(String businessStatus) {
String status = stringVal(businessStatus);
return "completed".equalsIgnoreCase(status) || "cancelled".equalsIgnoreCase(status);
return "completed".equalsIgnoreCase(status)
|| "cancelled".equalsIgnoreCase(status)
|| STATUS_PENDING_RETURN_CONFIRM.equalsIgnoreCase(status);
}
/**
@@ -155,6 +159,9 @@ public final class WaybillProcessSupport {
if ("cancelled".equalsIgnoreCase(status)) {
return "运单已取消";
}
if (STATUS_PENDING_RETURN_CONFIRM.equalsIgnoreCase(status)) {
return "运单待业务员确认回单";
}
return null;
}
@@ -195,7 +202,7 @@ public final class WaybillProcessSupport {
* 上报异常前的运单状态门禁原因;可上报时返回 null。
* <p>
* 与打卡共用「已开始运输」判据,但文案说的是能不能报,不是能不能打。
* 结束优先于未开始:已完成/已取消的运单先说结束,不再提「等你上路」。
* 结束优先于未开始:已结束的运单先说结束,不再提「等你上路」。
*/
public static String reportBlockedReason(String businessStatus) {
String endedReason = punchEndedReason(businessStatus);
@@ -213,7 +220,8 @@ public final class WaybillProcessSupport {
|| "completed".equals(businessStatus)
|| "cancelled".equals(businessStatus)
|| "waiting_dispatch".equals(businessStatus)
|| "dispatching".equals(businessStatus);
|| "dispatching".equals(businessStatus)
|| STATUS_PENDING_RETURN_CONFIRM.equals(businessStatus);
}
/**