From 717f50a52c4bd1f98e55ba18fabfdb857407654d Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Thu, 29 Oct 2026 16:22:52 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E4=B8=9A=E5=8A=A1=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E5=8F=AF=E8=A7=81=E5=90=88=E5=90=8C=E4=B8=8E=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E5=B9=B6=E8=A1=A5=E9=BD=90=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=BD=AE=E5=8D=95=E6=B5=8B=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../impl/ContractChangeServiceImpl.java | 12 +++-- .../impl/ContractManageServiceImpl.java | 12 +++-- .../impl/LoadingManageServiceImpl.java | 6 ++- .../impl/ShippingTemplateServiceImpl.java | 6 ++- .../impl/TemporaryCreditLimitServiceImpl.java | 6 ++- .../impl/TransportPlanServiceImpl.java | 9 ++-- .../service/impl/WaybillServiceImpl.java | 27 ++++++---- .../support/TransportBusinessSupport.java | 52 +++++++++++++++++++ .../ExceptionDisposalDetailPayloadTest.java | 4 +- .../impl/ExceptionDisposalListQueryTest.java | 4 +- .../ExceptionDisposalRejectRevokeTest.java | 3 +- .../impl/ExceptionDisposalReportGateTest.java | 3 +- .../ExceptionDisposalRouteAdjustTest.java | 4 +- 13 files changed, 119 insertions(+), 29 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java index a663c015..bb66d1c9 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractChangeServiceImpl.java @@ -263,9 +263,12 @@ public class ContractChangeServiceImpl extends BaseServiceImpl wrapper.eq(ContractChange::getOrganizationId, currentDeptId) - .or().eq(ContractChange::getCreateUser, currentUserId) - .or().eq(ContractChange::getHandlerUserId, currentUserId)); + queryWrapper.and(wrapper -> { + wrapper.eq(ContractChange::getOrganizationId, currentDeptId) + .or().eq(ContractChange::getCreateUser, currentUserId) + .or().eq(ContractChange::getHandlerUserId, currentUserId); + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, List.of(currentDeptId)); + }); } else if (Func.isNotEmpty(contractChange.getOrganizationId())) { queryWrapper.eq(ContractChange::getOrganizationId, contractChange.getOrganizationId()); } @@ -451,7 +454,8 @@ public class ContractChangeServiceImpl extends BaseServiceImpl wrapper.eq(ContractManage::getOrganizationId, currentDeptId) - .or().eq(ContractManage::getCreateUser, currentUserId) - .or().eq(ContractManage::getHandlerUserId, currentUserId)); + queryWrapper.and(wrapper -> { + wrapper.eq(ContractManage::getOrganizationId, currentDeptId) + .or().eq(ContractManage::getCreateUser, currentUserId) + .or().eq(ContractManage::getHandlerUserId, currentUserId); + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, List.of(currentDeptId)); + }); } else if (Func.isNotEmpty(contractManage.getOrganizationId())) { queryWrapper.eq(ContractManage::getOrganizationId, contractManage.getOrganizationId()); } @@ -1473,7 +1476,8 @@ public class ContractManageServiceImpl extends BaseServiceImpl queryWrapper = Wrappers.lambdaQuery().eq(LoadingManage::getIsDeleted, 0); if (!Objects.equals(loadingManage.getAllDept(), 1)) { - queryWrapper.eq(LoadingManage::getDeptId, TransportBusinessSupport.currentDeptId("配载管理")); + Long currentDeptId = TransportBusinessSupport.currentDeptId("配载管理"); + queryWrapper.and(wrapper -> { + wrapper.eq(LoadingManage::getDeptId, currentDeptId); + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, List.of(currentDeptId)); + }); } else if (Func.isNotEmpty(loadingManage.getDeptId())) { queryWrapper.eq(LoadingManage::getDeptId, loadingManage.getDeptId()); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java index 892018b9..c4265240 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java @@ -195,7 +195,11 @@ public class ShippingTemplateServiceImpl extends BaseServiceImpl queryWrapper = Wrappers.lambdaQuery().eq(ShippingTemplate::getIsDeleted, 0); if (!Objects.equals(shippingTemplate.getAllDept(), 1)) { - queryWrapper.eq(ShippingTemplate::getDeptId, TransportBusinessSupport.currentDeptId("发货模板")); + Long currentDeptId = TransportBusinessSupport.currentDeptId("发货模板"); + queryWrapper.and(wrapper -> { + wrapper.eq(ShippingTemplate::getDeptId, currentDeptId); + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, List.of(currentDeptId)); + }); } else if (Func.isNotEmpty(shippingTemplate.getDeptId())) { queryWrapper.eq(ShippingTemplate::getDeptId, shippingTemplate.getDeptId()); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TemporaryCreditLimitServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TemporaryCreditLimitServiceImpl.java index fdcc043d..5668c4ef 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TemporaryCreditLimitServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TemporaryCreditLimitServiceImpl.java @@ -190,7 +190,11 @@ public class TemporaryCreditLimitServiceImpl extends BaseServiceImpl { + wrapper.eq(TemporaryCreditLimit::getApplyDeptId, currentDeptId); + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, List.of(currentDeptId)); + }); } else if (Func.isNotEmpty(temporaryCreditLimit.getApplyDeptId())) { queryWrapper.eq(TemporaryCreditLimit::getApplyDeptId, temporaryCreditLimit.getApplyDeptId()); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java index 12479023..fb47d985 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java @@ -701,9 +701,12 @@ public class TransportPlanServiceImpl extends BaseServiceImpl queryWrapper = Wrappers.lambdaQuery().eq(TransportPlan::getIsDeleted, 0); if (!Objects.equals(transportPlan.getAllDept(), 1)) { Long currentDeptId = TransportBusinessSupport.currentDeptId("运输计划"); - // dept_id 为空的历史数据按创建组织归入当前组织 - queryWrapper.and(wrapper -> wrapper.eq(TransportPlan::getDeptId, currentDeptId) - .or(item -> item.isNull(TransportPlan::getDeptId).eq(TransportPlan::getCreateDept, currentDeptId))); + // dept_id 为空的历史数据按创建组织归入当前组织;业务部门可见其项目下的计划 + queryWrapper.and(wrapper -> { + wrapper.eq(TransportPlan::getDeptId, currentDeptId) + .or(item -> item.isNull(TransportPlan::getDeptId).eq(TransportPlan::getCreateDept, currentDeptId)); + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, List.of(currentDeptId)); + }); } else if (Func.isNotEmpty(transportPlan.getDeptId())) { queryWrapper.eq(TransportPlan::getDeptId, transportPlan.getDeptId()); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java index 611b4e5f..cd6ebbe6 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java @@ -1331,11 +1331,14 @@ public class WaybillServiceImpl extends BaseServiceImpl List deptIdList = TransportBusinessSupport.resolveDeptFilterIds( waybill.getAllDept(), waybill.getDeptId(), "运单管理", TransportBusinessSupport.MENU_WAYBILL_MANAGE); if (Func.isNotEmpty(deptIdList)) { - if (deptIdList.size() == 1) { - queryWrapper.eq(Waybill::getDeptId, deptIdList.get(0)); - } else { - queryWrapper.in(Waybill::getDeptId, deptIdList); - } + queryWrapper.and(wrapper -> { + if (deptIdList.size() == 1) { + wrapper.eq(Waybill::getDeptId, deptIdList.get(0)); + } else { + wrapper.in(Waybill::getDeptId, deptIdList); + } + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, deptIdList); + }); } if (TransportBusinessSupport.isOwnCreateScope(TransportBusinessSupport.MENU_WAYBILL_MANAGE)) { queryWrapper.eq(Waybill::getCreateUser, AuthUtil.getUserId()); @@ -1820,14 +1823,18 @@ public class WaybillServiceImpl extends BaseServiceImpl private LambdaQueryWrapper buildQuery(WaybillVO waybill) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(Waybill::getIsDeleted, 0); // 与常用线路等模块一致:超管默认不按组织过滤;普通用户 allDept!=1 时强制当前组织 + // 同时放行「所属项目业务部门」落在可见组织内的数据 List deptIdList = TransportBusinessSupport.resolveDeptFilterIds( waybill.getAllDept(), waybill.getDeptId(), "运单管理", TransportBusinessSupport.MENU_WAYBILL_MANAGE); if (Func.isNotEmpty(deptIdList)) { - if (deptIdList.size() == 1) { - queryWrapper.eq(Waybill::getDeptId, deptIdList.get(0)); - } else { - queryWrapper.in(Waybill::getDeptId, deptIdList); - } + queryWrapper.and(wrapper -> { + if (deptIdList.size() == 1) { + wrapper.eq(Waybill::getDeptId, deptIdList.get(0)); + } else { + wrapper.in(Waybill::getDeptId, deptIdList); + } + TransportBusinessSupport.orProjectVisibleByBusinessDept(wrapper, deptIdList); + }); } if (TransportBusinessSupport.isOwnCreateScope(TransportBusinessSupport.MENU_WAYBILL_MANAGE)) { queryWrapper.eq(Waybill::getCreateUser, AuthUtil.getUserId()); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/TransportBusinessSupport.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/TransportBusinessSupport.java index 0a5dd9e1..fd4c4547 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/support/TransportBusinessSupport.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/support/TransportBusinessSupport.java @@ -23,23 +23,30 @@ package org.springblade.transport.support; +import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.constant.RoleConstant; import org.springblade.core.tool.utils.Func; +import org.springblade.core.tool.utils.SpringUtil; import org.springblade.system.cache.RoleDataScopeCache; import org.springblade.system.cache.SysCache; import org.springblade.system.pojo.entity.Dept; import org.springblade.system.pojo.vo.RoleDataScopeVO; +import org.springblade.transport.mapper.ProjectApplyMapper; +import org.springblade.transport.pojo.entity.ProjectApply; import java.math.BigDecimal; import java.time.LocalDate; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * 运输业务公共校验支持 @@ -234,6 +241,51 @@ public final class TransportBusinessSupport { } } + /** + * 列表可见范围 OR:所属项目的业务部门落在指定组织内。 + *

+ * 与项目立项「本部门可见 business_dept_id」对齐,使合同/运单等业务数据 + * 在负责部门(organizationId/deptId)不是当前组织时,业务部门用户仍可看到。 + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public static void orProjectVisibleByBusinessDept(AbstractWrapper wrapper, Collection deptIds) { + if (wrapper == null || Func.isEmpty(deptIds)) { + return; + } + List ids = deptIds.stream().filter(Objects::nonNull).filter(id -> id > 0).distinct().toList(); + if (ids.isEmpty()) { + return; + } + if (ids.size() == 1) { + wrapper.or().apply( + "project_id IN (SELECT id FROM blade_project_apply WHERE is_deleted = 0 AND business_dept_id = {0})", + ids.get(0)); + return; + } + String inList = ids.stream().map(String::valueOf).collect(Collectors.joining(",")); + wrapper.or().apply( + "project_id IN (SELECT id FROM blade_project_apply WHERE is_deleted = 0 AND business_dept_id IN (" + + inList + "))"); + } + + /** + * 判断项目是否归属指定业务部门(用于详情只读/可操作判定)。 + */ + public static boolean isProjectOwnedByBusinessDept(Long projectId, Long deptId) { + if (Func.isEmpty(projectId) || Func.isEmpty(deptId) || deptId <= 0) { + return false; + } + ProjectApplyMapper projectApplyMapper = SpringUtil.getBean(ProjectApplyMapper.class); + if (projectApplyMapper == null) { + return false; + } + Long count = projectApplyMapper.selectCount(Wrappers.lambdaQuery() + .eq(ProjectApply::getId, projectId) + .eq(ProjectApply::getBusinessDeptId, deptId) + .eq(ProjectApply::getIsDeleted, 0)); + return count != null && count > 0; + } + /** * 解析列表组织筛选 ID。 * diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalDetailPayloadTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalDetailPayloadTest.java index 7f425f84..2834ff42 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalDetailPayloadTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalDetailPayloadTest.java @@ -19,6 +19,7 @@ import org.springblade.transport.pojo.entity.LoadingManage; import org.springblade.transport.pojo.entity.Waybill; import org.springblade.transport.pojo.vo.ExceptionDisposalVO; import org.springblade.transport.service.IDriverWaybillService; +import org.springblade.transport.service.IMaintenanceRecordService; import org.springblade.transport.service.IWaybillService; import java.lang.reflect.Field; @@ -86,7 +87,8 @@ class ExceptionDisposalDetailPayloadTest { loadingManageMapper = mock(LoadingManageMapper.class); service = new ExceptionDisposalServiceImpl( followRecordMapper, waybillService, mock(IDriverWaybillService.class), - mock(org.springblade.transport.support.MpUserDataScopeSupport.class), loadingManageMapper); + mock(org.springblade.transport.support.MpUserDataScopeSupport.class), loadingManageMapper, + mock(IMaintenanceRecordService.class)); inject("baseMapper", disposalMapper); } diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalListQueryTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalListQueryTest.java index a8c9d84b..80688ef5 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalListQueryTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalListQueryTest.java @@ -20,6 +20,7 @@ import org.springblade.transport.pojo.entity.ExceptionDisposal; import org.springblade.transport.pojo.entity.Waybill; import org.springblade.transport.pojo.vo.ExceptionDisposalVO; import org.springblade.transport.service.IDriverWaybillService; +import org.springblade.transport.service.IMaintenanceRecordService; import org.springblade.transport.service.IWaybillService; import java.lang.reflect.Field; @@ -73,7 +74,8 @@ class ExceptionDisposalListQueryTest { waybillService, mock(IDriverWaybillService.class), scopeSupport, - loadingManageMapper); + loadingManageMapper, + mock(IMaintenanceRecordService.class)); inject("baseMapper", disposalMapper); when(disposalMapper.selectPage(any(), any())).thenReturn(new Page(1, 10)); } diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRejectRevokeTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRejectRevokeTest.java index 706b5d37..667a1168 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRejectRevokeTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRejectRevokeTest.java @@ -21,6 +21,7 @@ import org.springblade.transport.pojo.entity.ExceptionDisposal; import org.springblade.transport.pojo.entity.ExceptionDisposalFollowRecord; import org.springblade.transport.pojo.vo.ExceptionDisposalVO; import org.springblade.transport.service.IDriverWaybillService; +import org.springblade.transport.service.IMaintenanceRecordService; import org.springblade.transport.service.IWaybillService; import java.lang.reflect.Field; @@ -69,7 +70,7 @@ class ExceptionDisposalRejectRevokeTest { service = new ExceptionDisposalServiceImpl( followRecordMapper, mock(IWaybillService.class), mock(IDriverWaybillService.class), mock(org.springblade.transport.support.MpUserDataScopeSupport.class), - mock(LoadingManageMapper.class)); + mock(LoadingManageMapper.class), mock(IMaintenanceRecordService.class)); inject("baseMapper", disposalMapper); when(disposalMapper.updateById(any(ExceptionDisposal.class))).thenReturn(1); when(followRecordMapper.insert(any(ExceptionDisposalFollowRecord.class))).thenReturn(1); diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalReportGateTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalReportGateTest.java index 04ba435c..4328e1a9 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalReportGateTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalReportGateTest.java @@ -19,6 +19,7 @@ import org.springblade.transport.mapper.LoadingManageMapper; import org.springblade.transport.pojo.entity.ExceptionDisposal; import org.springblade.transport.pojo.entity.Waybill; import org.springblade.transport.service.IDriverWaybillService; +import org.springblade.transport.service.IMaintenanceRecordService; import org.springblade.transport.service.IWaybillService; import java.lang.reflect.Field; @@ -74,7 +75,7 @@ class ExceptionDisposalReportGateTest { service = new ExceptionDisposalServiceImpl( mock(ExceptionDisposalFollowRecordMapper.class), waybillService, driverWaybillService, mock(org.springblade.transport.support.MpUserDataScopeSupport.class), - mock(LoadingManageMapper.class)); + mock(LoadingManageMapper.class), mock(IMaintenanceRecordService.class)); inject("baseMapper", disposalMapper); when(waybillService.getById(WAYBILL_ID)).thenReturn(waybill()); diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRouteAdjustTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRouteAdjustTest.java index 7c9c0b6b..26067a72 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRouteAdjustTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/ExceptionDisposalRouteAdjustTest.java @@ -23,6 +23,7 @@ import org.springblade.transport.pojo.entity.ExceptionDisposalFollowRecord; import org.springblade.transport.pojo.entity.LoadingManage; import org.springblade.transport.pojo.entity.Waybill; import org.springblade.transport.service.IDriverWaybillService; +import org.springblade.transport.service.IMaintenanceRecordService; import org.springblade.transport.service.IWaybillService; import java.lang.reflect.Field; @@ -88,7 +89,8 @@ class ExceptionDisposalRouteAdjustTest { loadingManageMapper = mock(LoadingManageMapper.class); service = new ExceptionDisposalServiceImpl( followRecordMapper, waybillService, mock(IDriverWaybillService.class), - mock(org.springblade.transport.support.MpUserDataScopeSupport.class), loadingManageMapper); + mock(org.springblade.transport.support.MpUserDataScopeSupport.class), loadingManageMapper, + mock(IMaintenanceRecordService.class)); inject("baseMapper", disposalMapper); when(disposalMapper.updateById(any(ExceptionDisposal.class))).thenReturn(1); when(followRecordMapper.insert(any(ExceptionDisposalFollowRecord.class))).thenReturn(1);