🐛 修认证流程清空司机车辆绑定,导致车辆列表消失
Driver.drivingVehicle 标了 @TableField(updateStrategy = FieldStrategy.ALWAYS), 该策略忽略 null 直接写:任何一次 updateById 只要 patch 里没带这个字段, 就会把库里的 driving_vehicle 写成 NULL。而司机端的车辆列表正是按这一列 的车牌匹配出来的(DriverAppServiceImpl.myVehicles 开头就判空返回空列表), 清空即页面显示「暂无绑定车辆」,且司机在界面上无法自行恢复。 两条链路都会触发: - 提交认证:updateDriverDisplayCache 只 patch id/状态/驳回原因; - 审核通过:本次改动新增的快照写回,同样只 patch 证件字段。 已在两处 updateById 前把该车的原值搬进 patch,并补回归测试: 先确认去掉修复后测试确实失败(expected 桂A12345,桂B67890 but was null)。 保留 ALWAYS 策略不动——它保证了「能显式清空车辆绑定」这一能力, 问题在于 patch 式更新必须自己带上原值,而不是删掉策略。
This commit is contained in:
+22
@@ -213,6 +213,10 @@ public class CertAuditServiceImpl implements ICertAuditService {
|
||||
driver.setId(record.getBizId());
|
||||
driver.setCertificationStatus(status);
|
||||
driver.setCertificationRejectReason(reason);
|
||||
// 必须带上 driving_vehicle 原值:该列是 FieldStrategy.ALWAYS,
|
||||
// 更新时忽略 null 直接写,patch 里不带它就会把司机的车辆绑定清成 NULL,
|
||||
// 而车辆列表正是按这一列匹配的(清空即「暂无绑定车辆」)。
|
||||
copyDrivingVehicle(record.getBizId(), driver);
|
||||
if (pass) {
|
||||
driver.setEffectiveCertRecordId(newEffectiveId);
|
||||
// 通过即生效:与车辆侧同理,把这次快照的证件内容一并写回司机档案。
|
||||
@@ -224,6 +228,24 @@ public class CertAuditServiceImpl implements ICertAuditService {
|
||||
driverService.updateById(driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把司机当前的车辆绑定原值搬进 patch,避免被 ALWAYS 更新策略清空
|
||||
* <p>
|
||||
* {@code driving_vehicle} 上标了 {@code FieldStrategy.ALWAYS},任何一次
|
||||
* {@code updateById} 都会把该列写成 patch 里的值(null 也照写)。
|
||||
* 而司机端的车辆列表是按这一列的车牌匹配出来的,一旦被清空,
|
||||
* 页面就变成「暂无绑定车辆」,且无法从界面上恢复。
|
||||
*
|
||||
* @param driverId 司机主键
|
||||
* @param patch 待更新的司机 patch(就地写入原值)
|
||||
*/
|
||||
private void copyDrivingVehicle(Long driverId, Driver patch) {
|
||||
Driver current = driverService.getById(driverId);
|
||||
if (current != null) {
|
||||
patch.setDrivingVehicle(current.getDrivingVehicle());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把生效快照里的司机证件字段搬进司机档案(就地写入同一个 patch 对象)
|
||||
* <p>
|
||||
|
||||
+7
@@ -368,6 +368,13 @@ public class DriverCertServiceImpl implements IDriverCertService {
|
||||
patch.setId(driverId);
|
||||
patch.setCertificationStatus(status);
|
||||
patch.setCertificationRejectReason(rejectReason);
|
||||
// 必须带上 driving_vehicle 原值:该列标了 FieldStrategy.ALWAYS,
|
||||
// 更新时忽略 null 直接写,patch 里不带它就会把司机的车辆绑定清成 NULL,
|
||||
// 而司机端的车辆列表正是按这一列的车牌匹配出来的(清空即「暂无绑定车辆」)。
|
||||
Driver current = driverService.getById(driverId);
|
||||
if (current != null) {
|
||||
patch.setDrivingVehicle(current.getDrivingVehicle());
|
||||
}
|
||||
driverService.updateById(patch);
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -155,6 +155,25 @@ class CertAuditServiceImplTest {
|
||||
assertEquals(RECORD_ID, captor.getValue().getEffectiveCertRecordId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("通过司机认证:patch 必须带上车辆绑定,不得把 driving_vehicle 清空")
|
||||
void approveDriverKeepsDrivingVehicle() {
|
||||
TransportCertRecord record = driverRecord(TransportCertRecord.STATUS_PENDING);
|
||||
when(certRecordService.getById(RECORD_ID)).thenReturn(record);
|
||||
Driver existing = driver(null);
|
||||
existing.setDrivingVehicle("桂A12345,桂B67890");
|
||||
when(driverService.getById(DRIVER_ID)).thenReturn(existing);
|
||||
|
||||
service.audit(RECORD_ID, true, null);
|
||||
|
||||
ArgumentCaptor<Driver> captor = ArgumentCaptor.forClass(Driver.class);
|
||||
verify(driverService).updateById(captor.capture());
|
||||
// driving_vehicle 标了 FieldStrategy.ALWAYS,patch 里为 null 就会把该列写成 NULL;
|
||||
// 而司机端车辆列表正是按这一列匹配的,清空即「暂无绑定车辆」且界面上无法恢复
|
||||
assertEquals("桂A12345,桂B67890", captor.getValue().getDrivingVehicle(),
|
||||
"审核通过不得把司机的车辆绑定清空");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 驳回
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user