diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java index 41964813..b63581a4 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java @@ -383,9 +383,6 @@ public class DriverServiceImpl extends BaseServiceImpl imp if (Func.isEmpty(driver.getMobile())) { throw new ServiceException("手机号不能为空"); } - if (Func.isEmpty(driver.getOrganizationName())) { - throw new ServiceException("所属组织不能为空"); - } if (Func.isEmpty(driver.getEmergencyContactName())) { throw new ServiceException("紧急联系人姓名不能为空"); } @@ -475,7 +472,10 @@ public class DriverServiceImpl extends BaseServiceImpl imp } } - // 部门可选:匹配到则写入小程序用户,匹配不到不阻断同步 + // 按「组织名称」反查组织树 id:组织改名后这里必然落空——不报错、不掉数据, + // 只是该司机账号的权限不再随组织变化(新建账号落空时数据权限为空集,管理端看不到)。 + // 组织为空同样落空,此时 deptId 传 null 而不是空串:updateUser 的 updateById 忽略 null, + // 账号原有的组织与数据权限得以保留;写成空串会把它们覆盖掉。 String deptId = null; R deptResult = sysClient.getDeptIds(tenantId, driver.getOrganizationName()); if (deptResult != null && R.isSuccess(deptResult) && Func.isNotEmpty(deptResult.getData())) { diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverServiceImplTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverServiceImplTest.java index 878fa815..f520381a 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverServiceImplTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverServiceImplTest.java @@ -23,6 +23,7 @@ import java.time.LocalDate; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -141,9 +142,60 @@ class DriverServiceImplTest { verify(driverMapper, never()).updateById(any(Driver.class)); } + // ------------------------------------------------------------ 无组织司机 + + @Test + @DisplayName("保存司机:组织为空也能保存(自助注册的档案在管理端不能再是只读的)") + void submitAllowsEmptyOrganization() { + Driver driver = driver(PLATE, ""); + when(driverMapper.selectByIdIncludingDeleted(DRIVER_ID)).thenReturn(driver); + when(driverMapper.selectByIdCardNoIncludingDeleted(driver.getIdCardNo())).thenReturn(null); + when(driverMapper.selectById(DRIVER_ID)).thenReturn(driver); + when(driverMapper.updateById(any(Driver.class))).thenReturn(1); + MpUser existing = new MpUser(); + existing.setId(USER_ID); + when(mpUserClient.userByPhone(TENANT_ID, MOBILE)).thenReturn(R.data(existing)); + when(mpUserClient.updateUser(any(MpUser.class))).thenReturn(R.data(true)); + + try (MockedStatic authUtil = mockStatic(AuthUtil.class)) { + authUtil.when(AuthUtil::getTenantId).thenReturn(TENANT_ID); + assertTrue(service.submit(driver)); + } + assertEquals("", driver.getOrganizationName(), "无组织按空串落库,不是 NULL"); + } + + @Test + @DisplayName("保存司机:组织为空时不得把账号原有 dept_id 写成空串,deptId 只能留 null 交给更新忽略") + void submitWithEmptyOrganizationKeepsMpUserDeptId() { + Driver driver = driver(PLATE, ""); + when(driverMapper.selectByIdIncludingDeleted(DRIVER_ID)).thenReturn(driver); + when(driverMapper.selectByIdCardNoIncludingDeleted(driver.getIdCardNo())).thenReturn(null); + when(driverMapper.selectById(DRIVER_ID)).thenReturn(driver); + when(driverMapper.updateById(any(Driver.class))).thenReturn(1); + MpUser existing = new MpUser(); + existing.setId(USER_ID); + existing.setDeptId("1123598821738675201"); + when(mpUserClient.userByPhone(TENANT_ID, MOBILE)).thenReturn(R.data(existing)); + when(mpUserClient.updateUser(any(MpUser.class))).thenReturn(R.data(true)); + + try (MockedStatic authUtil = mockStatic(AuthUtil.class)) { + authUtil.when(AuthUtil::getTenantId).thenReturn(TENANT_ID); + service.submit(driver); + } + + ArgumentCaptor captor = ArgumentCaptor.forClass(MpUser.class); + verify(mpUserClient).updateUser(captor.capture()); + assertNull(captor.getValue().getDeptId(), + "名称反查落空时 deptId 传 null;写成空串会把账号原有组织与数据权限覆盖掉"); + } + // ------------------------------------------------------------ 夹具 private Driver driver(String drivingVehicle) { + return driver(drivingVehicle, "测试组织"); + } + + private Driver driver(String drivingVehicle, String organizationName) { Driver driver = new Driver(); driver.setId(DRIVER_ID); driver.setIsDeleted(0); @@ -160,7 +212,7 @@ class DriverServiceImplTest { driver.setQualificationLongTerm(1); driver.setDriverType("自有"); driver.setMobile(MOBILE); - driver.setOrganizationName("测试组织"); + driver.setOrganizationName(organizationName); driver.setEmergencyContactName("李四"); driver.setEmergencyContactMobile("13800000000"); driver.setIdCardFront("https://oss/id-front.jpg");