🐛 车辆停用与未认证分开提示,不再把停用报成「认证没通过」

接单门槛对「车辆停用」和「车辆未认证」返回同一句「该车辆尚未通过认证审核,暂不可接单,请先提交认证」。生产上有一辆车已认证、只是被停用,司机照着提示做了两轮重新认证仍然接不了单——停用要找调度启用、认证才要提交资料,本是两件事。现在按运营状态优先逐车给出原因:停用报「该车辆已停用,请联系调度启用」,未认证才报认证。
This commit is contained in:
2026-10-07 19:30:31 +08:00
parent f3dc451802
commit 5496f487c7
3 changed files with 48 additions and 21 deletions
@@ -403,12 +403,17 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
LambdaQueryWrapper<TransportVehicle> plateQuery = Wrappers.lambdaQuery();
VehiclePlateSupport.applyPlateMatch(plateQuery, currentBoundPlates(driver));
List<TransportVehicle> boundVehicles = transportVehicleService.list(plateQuery);
boolean anyCertified = boundVehicles.stream().anyMatch(vehicle ->
certificationGate.isVehicleAvailable(
// 逐车取不可用原因:停用与未认证要分开报,否则「车已认证但被停用」
// 会被报成「认证没通过」,把人引去做无用的重新认证
String unavailableReason = boundVehicles.stream()
.map(vehicle -> certificationGate.vehicleUnavailableReason(
vehicle.getStatus() != null && vehicle.getStatus() == BladeConstant.DB_STATUS_NORMAL,
vehicle.getEffectiveCertRecordId()));
if (!anyCertified) {
throw new ServiceException(certificationGate.vehicleUnavailableReason());
vehicle.getEffectiveCertRecordId()))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
if (unavailableReason != null) {
throw new ServiceException(unavailableReason);
}
}
@@ -76,13 +76,30 @@ public class CertificationGate {
* @return 是否可用
*/
public boolean isVehicleAvailable(Boolean enabledState, Long effectiveRecordId) {
return vehicleUnavailableReason(enabledState, effectiveRecordId) == null;
}
/**
* 车辆不可用的原因
* <p>
* 停用与未认证是两件事,处置方式也不同:一个要找调度启用车辆,一个要去提交认证。
* 合并成同一句话,会把「车已认证、只是被停用」误导成「认证没通过」,
* 让人白做一轮重新认证。
*
* @param enabledState 运营状态:TRUE 启用
* @param effectiveRecordId 生效快照指针
* @return 不可用原因;可用时返回 null
*/
public String vehicleUnavailableReason(Boolean enabledState, Long effectiveRecordId) {
if (!Boolean.TRUE.equals(enabledState)) {
return false;
return "该车辆已停用,暂不可接单,请联系调度启用";
}
if (!vehicleGateEnabled) {
return true;
return null;
}
return CertificationRuleSupport.isCertified(effectiveRecordId);
return CertificationRuleSupport.isCertified(effectiveRecordId)
? null
: "该车辆尚未通过认证审核,暂不可接单,请先提交认证";
}
/**
@@ -98,15 +115,6 @@ public class CertificationGate {
return CertificationRuleSupport.isCertified(effectiveRecordId);
}
/**
* 车辆不可用的提示文案
*
* @return 面向司机的中文提示
*/
public String vehicleUnavailableReason() {
return "该车辆尚未通过认证审核,暂不可接单,请先提交认证";
}
/**
* 司机不可用的提示文案
*
@@ -5,6 +5,7 @@ import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
@@ -96,10 +97,23 @@ class CertificationGateTest {
// ------------------------------------------------------------ 提示文案
@Test
@DisplayName("拒绝原因可读,且不泄露内部字段名")
void rejectReasonIsReadable() {
assertTrue(gate.vehicleUnavailableReason().contains("认证"));
assertFalse(gate.vehicleUnavailableReason().contains("effective_cert_record_id"));
@DisplayName("停用与未认证分开报:前者让人去启用车辆,后者才让人去认证")
void unavailableReasonsDistinguishDisabledFromUncertified() {
String disabled = gate.vehicleUnavailableReason(Boolean.FALSE, 7001L);
assertTrue(disabled.contains("停用"), disabled);
assertFalse(disabled.contains("认证审核"), "已认证的车被停用,不该报成认证没通过");
String uncertified = gate.vehicleUnavailableReason(Boolean.TRUE, null);
assertTrue(uncertified.contains("认证"), uncertified);
assertFalse(uncertified.contains("停用"), uncertified);
}
@Test
@DisplayName("可用时没有原因;两种不可用文案都不泄露内部字段名")
void availableHasNoReasonAndTextIsReadable() {
assertNull(gate.vehicleUnavailableReason(Boolean.TRUE, 7001L));
assertFalse(gate.vehicleUnavailableReason(Boolean.TRUE, null).contains("effective_cert_record_id"));
assertFalse(gate.vehicleUnavailableReason(Boolean.FALSE, null).contains("effective_cert_record_id"));
assertTrue(gate.driverUnavailableReason().contains("认证"));
}