🐛 运次级接单与拒单补上更新痕迹,与单票路径一致
单票接单/拒单走 updateById,写前会把 update_time 刷成提交时刻、 update_user 填成当前用户(无登录态不填);运次级原来用 wrapper 一次写完, 这两列保持旧值,同一动作的两条路径在库里留下不同痕迹。 现显式补上同样两列,时刻取与接单/拒单时刻同一个 Date。
This commit is contained in:
+19
-1
@@ -28,6 +28,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
@@ -651,7 +652,11 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
List<TripVO.TripWaybillVO> children = tripChildren(tripId);
|
||||
assertTripAcceptable(children);
|
||||
List<Long> pendingIds = writeCandidateIds(children, "当前运单状态不允许接单");
|
||||
// 更新痕迹与单票接单一致:单票走 updateById,写前会把 update_time 刷成提交时刻、
|
||||
// 把 update_user 填成当前用户(无登录态则不填);这里一次写完,显式补上同样两列,
|
||||
// 时刻取与接单时刻同一个 now,操作人取同一个登录用户
|
||||
Date now = new Date();
|
||||
Long operatorId = currentOperatorId();
|
||||
return waybillService.update(Wrappers.<Waybill>lambdaUpdate()
|
||||
.set(Waybill::getDriverAcceptStatus, WaybillProcessSupport.ACCEPT_ACCEPTED)
|
||||
.set(Waybill::getDriverAcceptTime, now)
|
||||
@@ -659,6 +664,8 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
.set(Waybill::getDriverRejectTime, null)
|
||||
.set(Waybill::getDriverRejectReason, null)
|
||||
.set(Waybill::getBusinessStatus, STATUS_RUNNING)
|
||||
.set(Waybill::getUpdateTime, now)
|
||||
.set(operatorId != null, Waybill::getUpdateUser, operatorId)
|
||||
.in(Waybill::getId, pendingIds));
|
||||
}
|
||||
|
||||
@@ -673,8 +680,9 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
throw new ServiceException("拒绝原因不能超过200字");
|
||||
}
|
||||
List<Long> pendingIds = writeCandidateIds(children, "当前运单状态不允许拒绝接单");
|
||||
// 整单拒绝落在每张未终态子运单上,一次一条语句写完,拒单时刻与更新痕迹全趟车一致
|
||||
Date now = new Date();
|
||||
// 整单拒绝落在每张未终态子运单上,一次一条语句写完,接单时刻与拒单时刻全趟车一致
|
||||
Long operatorId = currentOperatorId();
|
||||
return waybillService.update(Wrappers.<Waybill>lambdaUpdate()
|
||||
.set(Waybill::getDriverAcceptStatus, WaybillProcessSupport.ACCEPT_REJECTED)
|
||||
.set(Waybill::getDriverAcceptTime, null)
|
||||
@@ -682,9 +690,19 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
|
||||
.set(Waybill::getDriverRejectTime, now)
|
||||
.set(Waybill::getDriverRejectReason, rejectReason)
|
||||
.set(Waybill::getBusinessStatus, STATUS_PENDING)
|
||||
.set(Waybill::getUpdateTime, now)
|
||||
.set(operatorId != null, Waybill::getUpdateUser, operatorId)
|
||||
.in(Waybill::getId, pendingIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录用户主键:与框架写入时填充更新人的口径一致——没有登录态就不填
|
||||
*/
|
||||
private Long currentOperatorId() {
|
||||
BladeUser operator = AuthUtil.getUser();
|
||||
return operator == null ? null : operator.getUserId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 运次 → 子运单集合:配载的运次走运次读服务解析(配载单主键命中后按配载单号取子运单),
|
||||
* 未配载的就是那张运单本身。收口与列表一致——别人的运次在这里已经被挡住。
|
||||
|
||||
+73
-2
@@ -12,6 +12,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.system.feign.IMpUserClient;
|
||||
import org.springblade.transport.mapper.ExceptionDisposalMapper;
|
||||
@@ -29,11 +30,13 @@ import org.springblade.transport.service.IWaybillService;
|
||||
import org.springblade.transport.support.CertificationGate;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -110,7 +113,9 @@ class DriverTripAcceptRejectTest {
|
||||
"driver_accept_driver_id",
|
||||
"driver_reject_time",
|
||||
"driver_reject_reason",
|
||||
"business_status"), updatedColumns(), "只写接单相关的列,司机字段一概不动");
|
||||
"business_status",
|
||||
"update_time",
|
||||
"update_user"), updatedColumns(), "只写接单相关的列与刷新痕迹,司机字段一概不动");
|
||||
assertTrue(capturedUpdateParams().containsAll(List.of(PENDING_ID, SECOND_ID, DRIVER_ID)),
|
||||
"两张子运单与接单司机一起下发:" + capturedUpdateParams());
|
||||
assertTrue(capturedWhereSql().contains("(id IN ("), capturedWhereSql());
|
||||
@@ -118,6 +123,49 @@ class DriverTripAcceptRejectTest {
|
||||
assertEquals(PHONE, capturedQuery().getDriverPhone(), "归属仍按司机手机号收口");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("运次接单的更新时间与接单时刻是同一个 now、更新人是当前操作人")
|
||||
void tripAcceptRefreshesUpdateTrace() {
|
||||
stubTrip(requireAcceptChild(PENDING_ID, "pending", "pending"));
|
||||
|
||||
runAsDriver(() -> service.tripAccept(TRIP_ID));
|
||||
|
||||
List<Date> dates = capturedUpdateDates();
|
||||
assertEquals(2, dates.size(), "接单时刻与更新时间各占一列");
|
||||
assertSame(dates.get(0), dates.get(1), "update_time 与接单时刻必须是同一个 now");
|
||||
assertTrue(capturedUpdateParams().contains(USER_ID), "update_user 就是当前操作人:" + capturedUpdateParams());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("没有登录态时不写 update_user,但 update_time 仍随操作刷新")
|
||||
void tripAcceptWithoutLoginSkipsUpdateUser() {
|
||||
stubTrip(requireAcceptChild(PENDING_ID, "pending", "pending"));
|
||||
|
||||
runWithoutLoginUser(() -> service.tripAccept(TRIP_ID));
|
||||
|
||||
assertEquals(List.of(
|
||||
"driver_accept_status",
|
||||
"driver_accept_time",
|
||||
"driver_accept_driver_id",
|
||||
"driver_reject_time",
|
||||
"driver_reject_reason",
|
||||
"business_status",
|
||||
"update_time"), updatedColumns(), "无登录态时与框架填充口径一致:只刷 update_time");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("运次拒单的更新时间与拒单时刻是同一个 now、更新人是当前操作人")
|
||||
void tripRejectRefreshesUpdateTrace() {
|
||||
stubTrip(requireAcceptChild(PENDING_ID, "pending", "pending"));
|
||||
|
||||
runAsDriver(() -> service.tripReject(TRIP_ID, "不要了"));
|
||||
|
||||
List<Date> dates = capturedUpdateDates();
|
||||
assertEquals(2, dates.size(), "拒单时刻与更新时间各占一列");
|
||||
assertSame(dates.get(0), dates.get(1), "update_time 与拒单时刻必须是同一个 now");
|
||||
assertTrue(capturedUpdateParams().contains(USER_ID), "update_user 就是当前操作人:" + capturedUpdateParams());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("任一子单已接单 → 整单已接单,不再重复写")
|
||||
void tripAcceptRefusesSecondCall() {
|
||||
@@ -204,7 +252,9 @@ class DriverTripAcceptRejectTest {
|
||||
"driver_accept_driver_id",
|
||||
"driver_reject_time",
|
||||
"driver_reject_reason",
|
||||
"business_status"), updatedColumns(), "只写拒单相关的列,司机字段一概不动");
|
||||
"business_status",
|
||||
"update_time",
|
||||
"update_user"), updatedColumns(), "只写拒单相关的列与刷新痕迹,司机字段一概不动");
|
||||
assertTrue(capturedUpdateParams().contains("车坏了"), "拒单原因原样下发(去首尾空格):" + capturedUpdateParams());
|
||||
assertTrue(capturedUpdateParams().containsAll(List.of(PENDING_ID, SECOND_ID)));
|
||||
}
|
||||
@@ -294,10 +344,27 @@ class DriverTripAcceptRejectTest {
|
||||
private <T> T runAsDriver(Supplier<T> action) {
|
||||
try (MockedStatic<AuthUtil> authUtil = mockStatic(AuthUtil.class)) {
|
||||
authUtil.when(AuthUtil::getUserId).thenReturn(USER_ID);
|
||||
authUtil.when(AuthUtil::getUser).thenReturn(bladeUser());
|
||||
return action.get();
|
||||
}
|
||||
}
|
||||
|
||||
/** 框架填充更新人看的是 getUserId() 背后的登录用户:为空就不填,这里把这一口径钉住 */
|
||||
private <T> T runWithoutLoginUser(Supplier<T> action) {
|
||||
try (MockedStatic<AuthUtil> authUtil = mockStatic(AuthUtil.class)) {
|
||||
authUtil.when(AuthUtil::getUserId).thenReturn(USER_ID);
|
||||
authUtil.when(AuthUtil::getUser).thenReturn(null);
|
||||
return action.get();
|
||||
}
|
||||
}
|
||||
|
||||
private BladeUser bladeUser() {
|
||||
BladeUser user = new BladeUser();
|
||||
user.setUserId(USER_ID);
|
||||
user.setUserName("黄宇富");
|
||||
return user;
|
||||
}
|
||||
|
||||
private void stubTrip(TripVO.TripWaybillVO... children) {
|
||||
stubTrip(new TripVO.TripWaybillVO[0], children);
|
||||
}
|
||||
@@ -360,6 +427,10 @@ class DriverTripAcceptRejectTest {
|
||||
.toList();
|
||||
}
|
||||
|
||||
private List<Date> capturedUpdateDates() {
|
||||
return capturedUpdateParams().stream().filter(Date.class::isInstance).map(Date.class::cast).toList();
|
||||
}
|
||||
|
||||
/** SET 与 WHERE 的参数都是渲染时才进参数表的,取值前先把两段都渲染一遍 */
|
||||
private Collection<Object> capturedUpdateParams() {
|
||||
LambdaUpdateWrapper<Waybill> update = capturedUpdate();
|
||||
|
||||
Reference in New Issue
Block a user