From 5bcb908cbd37dc7ec11f40e8a89bfb2dcbf3e389 Mon Sep 17 00:00:00 2001 From: weicw <594098497@qq.com> Date: Sun, 25 Oct 2026 20:20:59 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E7=A9=BA=E7=BB=84=E7=BB=87=E5=8F=B8?= =?UTF-8?q?=E6=9C=BA=E4=BF=9D=E5=AD=98=E6=97=B6=E4=B8=8D=E5=86=8D=E5=8F=91?= =?UTF-8?q?=E8=B5=B7=E7=BB=84=E7=BB=87=E5=8F=8D=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/DriverServiceImpl.java | 13 ++-- .../service/impl/DriverServiceImplTest.java | 70 +++++++++++-------- 2 files changed, 49 insertions(+), 34 deletions(-) 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 b63581a4..423bafec 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 @@ -474,12 +474,15 @@ public class DriverServiceImpl extends BaseServiceImpl imp // 按「组织名称」反查组织树 id:组织改名后这里必然落空——不报错、不掉数据, // 只是该司机账号的权限不再随组织变化(新建账号落空时数据权限为空集,管理端看不到)。 - // 组织为空同样落空,此时 deptId 传 null 而不是空串:updateUser 的 updateById 忽略 null, - // 账号原有的组织与数据权限得以保留;写成空串会把它们覆盖掉。 + // 组织为空时不做反查:DeptServiceImpl 会把空名称拆成空集合,MyBatis-Plus 的 inExpression + // 对空集合拼出 dept_name IN () 非法子句。此时 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())) { - deptId = deptResult.getData(); + if (Func.isNotEmpty(driver.getOrganizationName())) { + R deptResult = sysClient.getDeptIds(tenantId, driver.getOrganizationName()); + if (deptResult != null && R.isSuccess(deptResult) && Func.isNotEmpty(deptResult.getData())) { + deptId = deptResult.getData(); + } } MpUser existing = findExistingMpUser(driver, tenantId, mobile); 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 f520381a..0ecd4f9e 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 @@ -145,52 +145,64 @@ class DriverServiceImplTest { // ------------------------------------------------------------ 无组织司机 @Test - @DisplayName("保存司机:组织为空也能保存(自助注册的档案在管理端不能再是只读的)") + @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)); - } + submitWithExistingMpUser(driver, mpUser(USER_ID, "1123598821738675201")); + verify(mpUserClient).updateUser(any(MpUser.class)); assertEquals("", driver.getOrganizationName(), "无组织按空串落库,不是 NULL"); } @Test - @DisplayName("保存司机:组织为空时不得把账号原有 dept_id 写成空串,deptId 只能留 null 交给更新忽略") + @DisplayName("保存司机:组织为空时不发起组织反查,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)); + submitWithExistingMpUser(driver, mpUser(USER_ID, "1123598821738675201")); - try (MockedStatic authUtil = mockStatic(AuthUtil.class)) { - authUtil.when(AuthUtil::getTenantId).thenReturn(TENANT_ID); - service.submit(driver); - } + verify(sysClient, never()).getDeptIds(any(), any()); ArgumentCaptor captor = ArgumentCaptor.forClass(MpUser.class); verify(mpUserClient).updateUser(captor.capture()); assertNull(captor.getValue().getDeptId(), - "名称反查落空时 deptId 传 null;写成空串会把账号原有组织与数据权限覆盖掉"); + "组织为空时 deptId 只能留 null;写成空串会把账号原有组织与数据权限覆盖掉"); + } + + @Test + @DisplayName("保存司机:组织非空且名称反查命中时,落库的 deptId 是反查到的组织 id") + void submitWithFilledOrganizationUsesResolvedDeptId() { + Driver driver = driver(PLATE, "测试组织"); + when(sysClient.getDeptIds(TENANT_ID, "测试组织")).thenReturn(R.data("1123598821738675201")); + submitWithExistingMpUser(driver, mpUser(USER_ID, "1120666100345487362")); + + ArgumentCaptor captor = ArgumentCaptor.forClass(MpUser.class); + verify(mpUserClient).updateUser(captor.capture()); + assertEquals("1123598821738675201", captor.getValue().getDeptId(), + "组织非空时 deptId 由名称反查结果覆盖账号原组织"); } // ------------------------------------------------------------ 夹具 + // 库里已有该司机与对应的小程序账号:走 submit 的「更新并关联」分支 + private void submitWithExistingMpUser(Driver driver, MpUser existing) { + 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); + 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); + } + } + + private MpUser mpUser(Long id, String deptId) { + MpUser user = new MpUser(); + user.setId(id); + user.setDeptId(deptId); + return user; + } + private Driver driver(String drivingVehicle) { return driver(drivingVehicle, "测试组织"); }