diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java index 9acc9d76..ee8feb27 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java @@ -155,20 +155,27 @@ public class DriverAppServiceImpl implements IDriverAppService { } /** - * 日期字段的展示值:长期有效显示「长期」,没填显示空串,其余显示日期 + * 日期字段的下发值:只下发 {@code yyyy-MM-dd} 或空串,**从不下发「长期」这类文字** *
- * 卡片是「重新认证」表单的回填来源,空值必须是空串而不是「null」这类字符串, - * 否则用户会在日期框里看到一个字面量 null。 + * 卡片是「重新认证」表单的回填来源,值会直接进日期框,所以两条约束必须守住: + *
+ * 起期不再是必填:司机端表单不采集它(管理端车辆表单同样只填止期), + * 存量车辆档案里起期列全是空的,强制必填会让每一次重新认证都卡在提交前。 + * 起止先后只在**两端都有值**时才比较——只有止期时没有可比的对象。 * - * @param start 有效期起 + * @param start 有效期起,可为空 * @param end 有效期止 * @param longTerm 长期有效标志:1 表示长期 - * @param emptyText 缺值提示 - * @param rangeText 区间颠倒提示 + * @param emptyText 缺止期时的提示 + * @param rangeText 区间颠倒时的提示 */ private void requireDateRange(LocalDate start, LocalDate end, Integer longTerm, String emptyText, String rangeText) { if (Integer.valueOf(1).equals(longTerm)) { return; } - if (start == null || end == null) { + if (end == null) { throw new ServiceException(emptyText); } - if (end.isBefore(start)) { + if (start != null && end.isBefore(start)) { throw new ServiceException(rangeText); } } diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverAppServiceImplTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverAppServiceImplTest.java new file mode 100644 index 00000000..0894e214 --- /dev/null +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverAppServiceImplTest.java @@ -0,0 +1,125 @@ +package org.springblade.transport.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.springblade.core.secure.utils.AuthUtil; +import org.springblade.transport.pojo.entity.Driver; +import org.springblade.transport.pojo.entity.TransportVehicle; +import org.springblade.transport.pojo.vo.DriverVehicleCardVO; +import org.springblade.transport.service.IDriverService; +import org.springblade.transport.service.ITransportVehicleService; +import org.springblade.system.feign.IUserClient; + +import java.time.LocalDate; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +/** + * 司机端车辆卡片(重新认证表单的数据来源)测试。 + *
+ * 卡片字段会**直接进表单**,所以这里盯的不是「显示得好不好看」,而是两条会让回显出错的契约:
+ * 日期字段只能是 {@code yyyy-MM-dd} 或空串(不能是「长期」这类文字);
+ * 标了长期有效的字段不能再下发一个作废的止期。
+ */
+class DriverAppServiceImplTest {
+
+ private static final String MOBILE = "15577122721";
+ private static final Long USER_ID = 7001L;
+
+ private IDriverService driverService;
+ private ITransportVehicleService transportVehicleService;
+ private DriverAppServiceImpl service;
+
+ @BeforeEach
+ void setUp() {
+ driverService = mock(IDriverService.class);
+ transportVehicleService = mock(ITransportVehicleService.class);
+ service = new DriverAppServiceImpl(driverService, transportVehicleService, mock(IUserClient.class));
+ }
+
+ @Test
+ @DisplayName("长期有效且没有止期时下发空串,不能下发「长期」——否则它会被当日期填进日期框")
+ void longTermWithoutEndDateSendsEmptyText() {
+ DriverVehicleCardVO card = firstCard(vehicle(LocalDate.of(2022, 8, 17), null, 1));
+
+ assertEquals("", card.getDrivingLicenseEndDate(), "长期有效时日期字段只能是空串");
+ assertEquals(1, card.getDrivingLicenseLongTerm(), "长期有效标志本身要照常下发");
+ assertEquals("2022-08-17", card.getDrivingLicenseStartDate(), "起期有值时照常下发");
+ }
+
+ @Test
+ @DisplayName("长期有效时即使库里还留着止期也不下发:那个止期是上一版证件作废的值")
+ void longTermWithStaleEndDateSendsEmptyText() {
+ DriverVehicleCardVO card = firstCard(vehicle(null, LocalDate.of(2040, 8, 14), 1));
+
+ assertEquals("", card.getDrivingLicenseEndDate());
+ assertEquals("", card.getRoadTransportCertEndDate());
+ assertEquals("", card.getCompulsoryScrapDate());
+ }
+
+ @Test
+ @DisplayName("未标长期有效时照常下发止期,空值一律是空串而不是 null 字面量")
+ void normalVehicleSendsRealDates() {
+ TransportVehicle vehicle = vehicle(null, LocalDate.of(2030, 8, 14), 0);
+ vehicle.setCompulsoryScrapDate(LocalDate.of(2035, 1, 1));
+ vehicle.setRoadTransportCertEndDate(null);
+ vehicle.setRoadTransportCertLongTerm(0);
+ vehicle.setRoadTransportCertStartDate(LocalDate.of(2028, 12, 4));
+ DriverVehicleCardVO card = firstCard(vehicle);
+
+ assertEquals("2030-08-14", card.getDrivingLicenseEndDate());
+ assertEquals("2035-01-01", card.getCompulsoryScrapDate());
+ assertEquals("", card.getRoadTransportCertEndDate(), "没填的止期是空串");
+ assertEquals("2028-12-04", card.getRoadTransportCertStartDate());
+ }
+
+ // ---------------------------------------------------------------- 辅助
+
+ /** 造一辆只关心有效期三个字段的车 */
+ private TransportVehicle vehicle(LocalDate licenseStart, LocalDate licenseEnd, Integer licenseLongTerm) {
+ TransportVehicle vehicle = new TransportVehicle();
+ vehicle.setId(8001L);
+ vehicle.setPlateNo("桂AAW3255");
+ vehicle.setDrivingLicenseStartDate(licenseStart);
+ vehicle.setDrivingLicenseEndDate(licenseEnd);
+ vehicle.setDrivingLicenseLongTerm(licenseLongTerm);
+ // 三组有效期都按同一个长期有效标志造,便于一次断言三处
+ vehicle.setCompulsoryScrapDate(null);
+ vehicle.setCompulsoryScrapLongTerm(licenseLongTerm);
+ vehicle.setRoadTransportCertStartDate(LocalDate.of(2028, 12, 3));
+ vehicle.setRoadTransportCertEndDate(LocalDate.of(2043, 8, 18));
+ vehicle.setRoadTransportCertLongTerm(licenseLongTerm);
+ return vehicle;
+ }
+
+ /** 按当前登录司机的手机号跑一次「我的车辆」,取第一张卡片 */
+ private DriverVehicleCardVO firstCard(TransportVehicle vehicle) {
+ Driver driver = new Driver();
+ driver.setId(9001L);
+ driver.setUserId(USER_ID);
+ driver.setDriverName("韦司机");
+ driver.setMobile(MOBILE);
+ driver.setDrivingVehicle(vehicle.getPlateNo());
+
+ when(driverService.getOne(any(LambdaQueryWrapper.class))).thenReturn(driver);
+ when(transportVehicleService.list(any(LambdaQueryWrapper.class))).thenReturn(List.of(vehicle));
+
+ try (MockedStatic