✨ 调度首页把司机已拒单的运单列为重新派单待处理,并在司机端让该运单脱离
This commit is contained in:
+1
-1
@@ -72,7 +72,7 @@ public class ManageWaybillController extends BladeController {
|
||||
|
||||
@GetMapping("/home")
|
||||
@ApiOperationSupport(order = 2)
|
||||
@Operation(summary = "首页聚合", description = "统计 + 异常/风险角标 + 待处理事项(异常处置≠已完成)+ 当前用户名")
|
||||
@Operation(summary = "首页聚合", description = "统计 + 异常/风险/重新派单角标 + 待处理事项(异常处置≠已完成,或司机已拒单待重新派单)+ 当前用户名")
|
||||
public R<AdminHomeVO> home() {
|
||||
return R.data(manageWaybillService.home());
|
||||
}
|
||||
|
||||
+33
-5
@@ -262,7 +262,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);
|
||||
@@ -483,6 +484,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) {
|
||||
@@ -498,13 +503,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("运单不存在或无权操作");
|
||||
}
|
||||
@@ -560,11 +571,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) {
|
||||
@@ -578,6 +601,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) {
|
||||
|
||||
+94
-4
@@ -57,6 +57,7 @@ import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
@@ -85,6 +86,13 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
|
||||
private static final String DISPOSAL_PROCESSING = "processing";
|
||||
private static final String RISK_PENDING = "pending";
|
||||
|
||||
/** 小程序首页待处理事项的类型:异常待处置 */
|
||||
private static final String TODO_EXCEPTION = "exception";
|
||||
/** 小程序首页待处理事项的类型:重新派单待处理 */
|
||||
private static final String TODO_REASSIGN = "reassign";
|
||||
/** 重派条目跳转页码:参数 id 是运单主键(不是运单号),该页据此回显运单;buyerPaid 恒为 0,与列表卡片一致 */
|
||||
private static final String REASSIGN_TARGET_URL = "/pages/waybill/reassign?id=%s&buyerPaid=0";
|
||||
|
||||
private static final String EXCEPTION_YES = "exception";
|
||||
private static final String EXCEPTION_NO = "normal";
|
||||
private static final String TRANSPORT_COMMON = "common";
|
||||
@@ -122,8 +130,9 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
|
||||
AdminHomeBadgesVO badges = new AdminHomeBadgesVO();
|
||||
badges.setException(home.getStats().getException());
|
||||
badges.setRisk(countPendingRisks());
|
||||
badges.setPendingReassign(countPendingReassignments());
|
||||
home.setBadges(badges);
|
||||
home.setFeed(buildExceptionFeed());
|
||||
home.setFeed(buildAdminFeed());
|
||||
return home;
|
||||
}
|
||||
|
||||
@@ -561,18 +570,66 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
|
||||
.eq(RiskDisposal::getDisposalStatus, RISK_PENDING));
|
||||
}
|
||||
|
||||
private List<AdminTodoItemVO> buildExceptionFeed() {
|
||||
/** 待重新派单:司机已拒单,且运单尚未取消/完成 */
|
||||
private long countPendingReassignments() {
|
||||
return waybillService.count(pendingReassignQuery());
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<Waybill> pendingReassignQuery() {
|
||||
return Wrappers.<Waybill>lambdaQuery()
|
||||
.eq(Waybill::getDriverAcceptStatus, ACCEPT_REJECTED)
|
||||
.in(Waybill::getBusinessStatus, STATUS_PENDING, STATUS_RUNNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页待处理事项:异常待处置 + 重新派单待处理。
|
||||
* 两类各按自己的业务发生时间(上报时刻 / 拒单时刻)倒序,合并后再整体倒序取前 N 条。
|
||||
* 排序时间随条目一起携带,不塞进 id 字段——id 在两型下各自是处置主键与运单主键。
|
||||
*/
|
||||
List<AdminTodoItemVO> buildAdminFeed() {
|
||||
List<TimedTodo> merged = new ArrayList<>();
|
||||
merged.addAll(buildExceptionFeed());
|
||||
merged.addAll(buildReassignFeed());
|
||||
merged.sort(java.util.Comparator.comparing(
|
||||
(TimedTodo entry) -> entry.time, java.util.Comparator.nullsFirst(java.util.Comparator.naturalOrder())));
|
||||
java.util.Collections.reverse(merged);
|
||||
int to = Math.min(merged.size(), FEED_LIMIT);
|
||||
return merged.subList(0, to).stream().map(TimedTodo::item).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/** 待处理事项 + 它的业务发生时间(仅用于排序) */
|
||||
private record TimedTodo(AdminTodoItemVO item, LocalDateTime time) {
|
||||
}
|
||||
|
||||
private List<TimedTodo> buildExceptionFeed() {
|
||||
List<ExceptionDisposal> list = exceptionDisposalService.list(Wrappers.<ExceptionDisposal>lambdaQuery()
|
||||
.in(ExceptionDisposal::getDisposalStatus, DISPOSAL_PENDING, DISPOSAL_PROCESSING)
|
||||
.orderByDesc(ExceptionDisposal::getReportTime)
|
||||
.last("LIMIT " + FEED_LIMIT));
|
||||
return list.stream().map(this::toTodoItem).collect(Collectors.toList());
|
||||
return list.stream()
|
||||
.map(disposal -> new TimedTodo(toTodoItem(disposal), exceptionTimeOf(disposal)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<TimedTodo> buildReassignFeed() {
|
||||
List<Waybill> list = waybillService.list(pendingReassignQuery()
|
||||
.orderByDesc(Waybill::getDriverRejectTime)
|
||||
.last("LIMIT " + FEED_LIMIT));
|
||||
return list.stream()
|
||||
.map(waybill -> new TimedTodo(toReassignTodoItem(waybill), rejectTimeOf(waybill)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private LocalDateTime exceptionTimeOf(ExceptionDisposal disposal) {
|
||||
return disposal.getReportTime() != null
|
||||
? disposal.getReportTime()
|
||||
: toLocalDateTime(disposal.getCreateTime());
|
||||
}
|
||||
|
||||
private AdminTodoItemVO toTodoItem(ExceptionDisposal disposal) {
|
||||
AdminTodoItemVO item = new AdminTodoItemVO();
|
||||
item.setId(disposal.getId());
|
||||
item.setType("exception");
|
||||
item.setType(TODO_EXCEPTION);
|
||||
item.setTitle("异常待处置");
|
||||
item.setTimeAgo(formatTimeAgo(disposal.getReportTime() != null
|
||||
? disposal.getReportTime()
|
||||
@@ -585,6 +642,38 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
|
||||
return item;
|
||||
}
|
||||
|
||||
private AdminTodoItemVO toReassignTodoItem(Waybill waybill) {
|
||||
AdminTodoItemVO item = new AdminTodoItemVO();
|
||||
item.setId(waybill.getId());
|
||||
item.setType(TODO_REASSIGN);
|
||||
item.setTitle("重新派单待处理");
|
||||
item.setTimeAgo(formatTimeAgo(rejectTimeOf(waybill)));
|
||||
item.setDesc(buildReassignDesc(waybill));
|
||||
item.setWaybillNo(Func.toStr(waybill.getWaybillNo(), ""));
|
||||
item.setActionLabel("重新派单");
|
||||
item.setTargetUrl(String.format(REASSIGN_TARGET_URL, waybill.getId()));
|
||||
return item;
|
||||
}
|
||||
|
||||
/** 拒单时刻是「被拒了多久」的唯一依据;为空(历史数据)才回退到最后修改时间 */
|
||||
private LocalDateTime rejectTimeOf(Waybill waybill) {
|
||||
if (waybill.getDriverRejectTime() != null) {
|
||||
return toLocalDateTime(waybill.getDriverRejectTime());
|
||||
}
|
||||
return toLocalDateTime(waybill.getUpdateTime());
|
||||
}
|
||||
|
||||
/** 拒单原因的输入是可选的,没填时正文不能留下空的「:」 */
|
||||
private String buildReassignDesc(Waybill waybill) {
|
||||
String driver = Func.toStr(waybill.getDriverName(), "原司机");
|
||||
String text = "运单已指派" + driver + ",被拒绝,请重新派单";
|
||||
String reason = Func.toStr(waybill.getDriverRejectReason(), "").trim();
|
||||
if (Func.isNotBlank(reason)) {
|
||||
text = text + ":" + reason;
|
||||
}
|
||||
return text.length() > 80 ? text.substring(0, 80) + "…" : text;
|
||||
}
|
||||
|
||||
private String buildExceptionDesc(ExceptionDisposal disposal) {
|
||||
String reporter = Func.toStr(disposal.getReporterName(), "司机");
|
||||
String type = Func.toStr(disposal.getExceptionType(), "异常");
|
||||
@@ -606,6 +695,7 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
|
||||
return Func.toStr(AuthUtil.getUserName(), "");
|
||||
}
|
||||
|
||||
/** 相对时间文案;时间取不到时留空,避免把「现在」当成发生时刻显示成「刚刚」 */
|
||||
private String formatTimeAgo(LocalDateTime time) {
|
||||
if (time == null) {
|
||||
return "";
|
||||
|
||||
Reference in New Issue
Block a user