🐛 审核未命中目标档案时整体回滚,不再静默置为已通过
审核通过时对司机/车辆档案的 updateById 命中 0 行只返回 false、不抛异常,而这个返回值原先被丢弃,于是「认证记录已通过、档案一个字没变」能静默成立:生效快照指针没写进去,对象下次接单仍被判未认证,审核页却显示已通过。现在命中 0 行即抛异常并回滚整次审核,宁可报错也不留下状态与档案互相矛盾的数据。
This commit is contained in:
+21
-2
@@ -206,7 +206,7 @@ public class CertAuditServiceImpl implements ICertAuditService {
|
|||||||
// 与指针合并成同一次 UPDATE,不额外多写一次同一行。
|
// 与指针合并成同一次 UPDATE,不额外多写一次同一行。
|
||||||
applySnapshotToVehicle(vehicle, record.getSnapshotJson());
|
applySnapshotToVehicle(vehicle, record.getSnapshotJson());
|
||||||
}
|
}
|
||||||
transportVehicleService.updateById(vehicle);
|
requireTargetUpdated(transportVehicleService.updateById(vehicle), "车辆", record.getBizId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Driver driver = new Driver();
|
Driver driver = new Driver();
|
||||||
@@ -225,7 +225,26 @@ public class CertAuditServiceImpl implements ICertAuditService {
|
|||||||
// 与指针合并成同一次 UPDATE,不额外多写一次同一行。
|
// 与指针合并成同一次 UPDATE,不额外多写一次同一行。
|
||||||
applySnapshotToDriver(driver, record.getSnapshotJson());
|
applySnapshotToDriver(driver, record.getSnapshotJson());
|
||||||
}
|
}
|
||||||
driverService.updateById(driver);
|
requireTargetUpdated(driverService.updateById(driver), "司机", record.getBizId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目标对象的写入必须命中一行,否则整体失败
|
||||||
|
* <p>
|
||||||
|
* {@code updateById} 命中 0 行时**不抛异常、只返回 false**。原先丢弃这个返回值,
|
||||||
|
* 于是「审核记录已通过、司机/车辆档案一个字没变」能静默成立:生效快照指针没写进去,
|
||||||
|
* 对象下次接单仍被判未认证,而审核页显示的是已通过。此处让事务整体回滚,
|
||||||
|
* 宁可报错也不留下状态与档案互相矛盾的数据。
|
||||||
|
*
|
||||||
|
* @param updated 更新结果
|
||||||
|
* @param target 对象名称,用于提示
|
||||||
|
* @param id 对象主键
|
||||||
|
*/
|
||||||
|
private void requireTargetUpdated(boolean updated, String target, Long id) {
|
||||||
|
if (!updated) {
|
||||||
|
throw new ServiceException("未能更新" + target + "档案(ID:" + id
|
||||||
|
+ "),本次审核已回滚、未生效;请核对该对象是否存在、未被删除,且与认证记录属于同一租户");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+26
@@ -50,6 +50,9 @@ class CertAuditServiceImplTest {
|
|||||||
transportVehicleService = mock(ITransportVehicleService.class);
|
transportVehicleService = mock(ITransportVehicleService.class);
|
||||||
driverService = mock(IDriverService.class);
|
driverService = mock(IDriverService.class);
|
||||||
service = new CertAuditServiceImpl(certRecordService, certRecordMapper, transportVehicleService, driverService);
|
service = new CertAuditServiceImpl(certRecordService, certRecordMapper, transportVehicleService, driverService);
|
||||||
|
// 目标对象的写入默认成功;「写入一行都没命中」由专门的用例覆盖
|
||||||
|
when(transportVehicleService.updateById(any(TransportVehicle.class))).thenReturn(true);
|
||||||
|
when(driverService.updateById(any(Driver.class))).thenReturn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------ 通过
|
// ------------------------------------------------------------ 通过
|
||||||
@@ -174,6 +177,29 @@ class CertAuditServiceImplTest {
|
|||||||
"审核通过不得把司机的车辆绑定清空");
|
"审核通过不得把司机的车辆绑定清空");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("通过:目标对象一行都没命中时必须整体失败,不得「记录已通过、档案没变」")
|
||||||
|
void approveFailsWhenVehicleNotUpdated() {
|
||||||
|
when(certRecordService.getById(RECORD_ID)).thenReturn(vehicleRecord(TransportCertRecord.STATUS_PENDING));
|
||||||
|
when(transportVehicleService.updateById(any(TransportVehicle.class))).thenReturn(false);
|
||||||
|
|
||||||
|
ServiceException exception = assertThrows(ServiceException.class,
|
||||||
|
() -> service.audit(RECORD_ID, true, null));
|
||||||
|
assertTrue(exception.getMessage().contains("未生效"), exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("通过司机认证:司机档案没命中时同样必须整体失败,不得静默放行")
|
||||||
|
void approveFailsWhenDriverNotUpdated() {
|
||||||
|
when(certRecordService.getById(RECORD_ID)).thenReturn(driverRecord(TransportCertRecord.STATUS_PENDING));
|
||||||
|
when(driverService.getById(DRIVER_ID)).thenReturn(driver(null));
|
||||||
|
when(driverService.updateById(any(Driver.class))).thenReturn(false);
|
||||||
|
|
||||||
|
ServiceException exception = assertThrows(ServiceException.class,
|
||||||
|
() -> service.audit(RECORD_ID, true, null));
|
||||||
|
assertTrue(exception.getMessage().contains("司机"), exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------ 驳回
|
// ------------------------------------------------------------ 驳回
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user