瀏覽代碼

提交数据权限

chenxiaofei 2 月之前
父節點
當前提交
9e8a44c597

+ 10 - 0
sckw-modules-api/sckw-contract-api/src/main/java/com/sckw/contract/api/model/dto/res/ContractCommonInfoResDto.java

@@ -62,5 +62,15 @@ public class ContractCommonInfoResDto implements Serializable {
      */
     private Integer dispatchWay;
 
+    /**
+     * 贸易合同归属企业ID(仅贸易合同有值,用于数据权限按企业过滤)
+     */
+    private Long entId;
+
+    /**
+     * 贸易合同销售人员用户ID(仅贸易合同有值,用于个人数据权限过滤)
+     */
+    private Long salesmanId;
+
 
 }

+ 2 - 0
sckw-modules/sckw-contract/src/main/java/com/sckw/contract/dubbo/RemoteContractServiceImpl.java

@@ -394,6 +394,8 @@ public class RemoteContractServiceImpl implements RemoteContractService {
         contractCommonInfoResDto.setStatus(kwcContractTrade.getStatus());
         contractCommonInfoResDto.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(kwcContractTrade.getStatus())).getName());
         contractCommonInfoResDto.setDispatchWay(kwcContractTrade.getDispatchWay());
+        contractCommonInfoResDto.setEntId(kwcContractTrade.getEntId());
+        contractCommonInfoResDto.setSalesmanId(kwcContractTrade.getSalesmanId());
         List<KwcContractLogisticsUnit> kwcContractLogisticsUnits = kwcContractLogisticsUnitService.queryByContractId(kwcContractTrade.getId());
         if (CollectionUtils.isNotEmpty(kwcContractLogisticsUnits)) {
             for (KwcContractLogisticsUnit kwcContractLogisticsUnit : kwcContractLogisticsUnits) {

+ 111 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtLogisticsConsignmentService.java

@@ -47,6 +47,9 @@ import com.sckw.stream.enums.MessageEnum;
 import com.sckw.stream.model.SckwBusSum;
 import com.sckw.system.api.RemoteSystemService;
 import com.sckw.system.api.RemoteUserService;
+import com.sckw.system.api.feign.DataPermissionFeignService;
+import com.sckw.system.api.model.dto.req.DataPermissionFilterReqDto;
+import com.sckw.system.api.model.dto.res.DataPermissionDTO;
 import com.sckw.system.api.model.dto.res.EntCacheResDto;
 import com.sckw.system.api.model.dto.res.UserResDto;
 import com.sckw.transport.api.model.LogisticsBaseOrderVo;
@@ -139,6 +142,9 @@ public class KwtLogisticsConsignmentService {
     @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
     RemoteContractService contractService;
 
+    @Autowired
+    DataPermissionFeignService dataPermissionFeignService;
+
     @Autowired
     public KwtLogisticsOrderConsignmentService logisticsOrderConsignmentService;
 
@@ -2259,6 +2265,7 @@ public class KwtLogisticsConsignmentService {
         // 3. 获取物流订单ID集合
         log.debug("获取物流订单ID集合");
         Set<Long> logOrderIds = getLogOrderIds(req, entList, allEnt);
+        logOrderIds = applyDataPermissionFilterToLogOrderIds(logOrderIds);
 
         // 4. 检查是否需要返回空结果
         log.debug("检查是否需要返回空结果,logOrderIds大小: {}, entList大小: {}", logOrderIds.size(), entList.size());
@@ -2703,6 +2710,110 @@ public class KwtLogisticsConsignmentService {
      */
 
 
+    /**
+     * 按数据权限收缩物流订单ID:
+     * 企业权限:贸易合同 ent_id 落在已勾选企业范围内;
+     * 个人权限:贸易合同 salesman_id 为当前用户;
+     * 两者同时开启时为 AND(与系统模块 DataPermissionDTO 规则一致)。
+     */
+    private Set<Long> applyDataPermissionFilterToLogOrderIds(Set<Long> logOrderIds) {
+        // 1. 获取当前用户的数据权限配置
+        DataPermissionDTO perm = fetchDataPermissionForCurrentUser();
+        // 如果无需过滤或权限对象为空,直接返回原始ID集合
+        if (perm == null || !perm.needFilter()) {
+            return logOrderIds;
+        }
+        // 如果输入ID集合为空,直接返回
+        if (CollectionUtils.isEmpty(logOrderIds)) {
+            return logOrderIds;
+        }
+
+        // 2. 查询物流订单详情,获取关联的贸易订单ID
+        List<KwtLogisticsOrder> orders = logisticsOrderRepository.queryByLogOrderIds(logOrderIds);
+        if (CollectionUtils.isEmpty(orders)) {
+            return Sets.newHashSet();
+        }
+        Set<Long> tradeIds = orders.stream()
+                .map(KwtLogisticsOrder::getTOrderId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (CollectionUtils.isEmpty(tradeIds)) {
+            return Sets.newHashSet();
+        }
+
+        // 3. 通过贸易订单ID查询关联的合同ID
+        List<TradeOrderContractVo> contractLinks = tradeOrderInfoService.queryTradeOrderIds(tradeIds);
+        Map<Long, Long> tradeIdToContractId = new HashMap<>();
+        if (CollectionUtils.isNotEmpty(contractLinks)) {
+            for (TradeOrderContractVo link : contractLinks) {
+                if (link.getTOrderId() == null || link.getContractId() == null) {
+                    continue;
+                }
+                tradeIdToContractId.putIfAbsent(link.getTOrderId(), link.getContractId());
+            }
+        }
+
+        // 4. 批量查询合同基础信息
+        List<Long> contractIdList = tradeIdToContractId.values().stream().distinct().collect(Collectors.toList());
+        Map<Long, ContractCommonInfoResDto> contractMap = Maps.newHashMap();
+        if (CollectionUtils.isNotEmpty(contractIdList)) {
+            contractMap = contractService.queryContractBaseInfo(contractIdList);
+        }
+
+        // 5. 根据数据权限规则过滤允许的贸易订单ID
+        Set<Long> allowedTradeIds = new HashSet<>();
+        for (Long tid : tradeIds) {
+            Long cid = tradeIdToContractId.get(tid);
+            if (cid == null) {
+                continue;
+            }
+            ContractCommonInfoResDto c = contractMap.get(cid);
+            if (c == null) {
+                continue;
+            }
+
+            // 校验企业权限:如果不是全部可见,则检查合同所属企业是否在可见列表中
+            boolean entOk = true;
+            if (!perm.isAllVisible()) {
+                if (CollectionUtils.isEmpty(perm.getVisibleEntIds())) {
+                    entOk = false;
+                } else {
+                    entOk = c.getEntId() != null && perm.getVisibleEntIds().contains(c.getEntId());
+                }
+            }
+
+            // 校验个人权限:如果开启了个人数据隔离,则检查合同销售员是否为当前用户
+            boolean salesOk = true;
+            if (perm.isPersonalDataEnabled()) {
+                salesOk = perm.getUserId() != null && perm.getUserId().equals(c.getSalesmanId());
+            }
+
+            // 同时满足企业权限和个人权限(AND逻辑)
+            if (entOk && salesOk) {
+                allowedTradeIds.add(tid);
+            }
+        }
+
+        // 6. 返回过滤后的物流订单ID集合
+        return orders.stream()
+                .filter(o -> o.getTOrderId() != null && allowedTradeIds.contains(o.getTOrderId()))
+                .map(KwtLogisticsOrder::getId)
+                .collect(Collectors.toSet());
+    }
+
+    private DataPermissionDTO fetchDataPermissionForCurrentUser() {
+        try {
+            DataPermissionFilterReqDto reqDto = new DataPermissionFilterReqDto();
+            reqDto.setUserId(LoginUserHolder.getUserId());
+            reqDto.setRoleId(LoginUserHolder.getCurrentRoleId());
+            reqDto.setManager(LoginUserHolder.isManager());
+            return dataPermissionFeignService.getDataPermissionFilter(reqDto);
+        } catch (Exception e) {
+            log.warn("获取数据权限失败,跳过本接口数据权限过滤: {}", e.getMessage());
+            return null;
+        }
+    }
+
     @NotNull
     private static Set<Long> getEntList(QueryLogisticsOrderReq req) {
         Set<Long> entList = Sets.newHashSet();

+ 123 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/KwtWaybillOrderV1Service.java

@@ -50,7 +50,10 @@ import com.sckw.stream.model.SckwMessage;
 import com.sckw.stream.model.UserInfo;
 import com.sckw.system.api.RemoteSystemService;
 import com.sckw.system.api.RemoteUserService;
+import com.sckw.system.api.feign.DataPermissionFeignService;
+import com.sckw.system.api.model.dto.req.DataPermissionFilterReqDto;
 import com.sckw.system.api.model.dto.res.*;
+import com.sckw.contract.api.model.dto.res.ContractCommonInfoResDto;
 import com.sckw.transport.api.feign.VehicleTraceClient;
 import com.sckw.transport.common.config.UrlConfigProperties;
 import com.sckw.transport.dao.*;
@@ -168,6 +171,8 @@ public class KwtWaybillOrderV1Service {
 
     @Autowired
     LogisticsScoreFeignService logisticsScoreFeignService;
+    @Resource
+    DataPermissionFeignService dataPermissionFeignService;
     @Autowired
     private KwtLogisticsOrderAddressRepository kwtLogisticsOrderAddressRepository;
     // 定义超时时间常量
@@ -3025,6 +3030,10 @@ public class KwtWaybillOrderV1Service {
         Set<Long> billOrderIds = billOrderIdsFuture.join();
         log.debug("物流订单ID查询结果数量: {}, 运单ID查询结果数量: {}", logOrderIds.size(), billOrderIds.size());
 
+        // 应用数据权限过滤:个人数据权限与企业层级数据权限为并集关系
+        logOrderIds = applyDataPermissionFilterToLogOrderIds(logOrderIds);
+        log.debug("数据权限过滤后物流订单ID数量: {}", logOrderIds.size());
+
         // 检查是否需要返回空结果
         log.debug("检查是否需要返回空结果");
         if (shouldReturnEmptyResultForLogistics(req, logOrderIds) ||
@@ -3622,6 +3631,120 @@ public class KwtWaybillOrderV1Service {
         return entIds;
     }
 
+    /**
+     * 获取当前登录用户的数据权限配置
+     */
+    private DataPermissionDTO fetchDataPermissionForCurrentUser() {
+        try {
+            DataPermissionFilterReqDto reqDto = new DataPermissionFilterReqDto();
+            reqDto.setUserId(LoginUserHolder.getUserId());
+            reqDto.setRoleId(LoginUserHolder.getCurrentRoleId());
+            reqDto.setManager(LoginUserHolder.isManager());
+            return dataPermissionFeignService.getDataPermissionFilter(reqDto);
+        } catch (Exception e) {
+            log.warn("获取数据权限失败,跳过运单列表数据权限过滤: {}", e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * 根据数据权限过滤物流订单ID集合
+     * <p>
+     * 个人数据权限与企业层级数据权限为并集关系:
+     * 勾选后只查已勾选的企业并且贸易合同中销售人员是自己的数据
+     * <p>
+     * 过滤链路:物流订单 → 贸易订单 → 贸易合同 → 校验企业ID + 销售人员
+     *
+     * @param logOrderIds 待过滤的物流订单ID集合
+     * @return 过滤后的物流订单ID集合
+     */
+    private Set<Long> applyDataPermissionFilterToLogOrderIds(Set<Long> logOrderIds) {
+        // 获取当前用户的数据权限配置
+        DataPermissionDTO perm = fetchDataPermissionForCurrentUser();
+        // 如果无需过滤或权限配置为空,直接返回原集合
+        if (perm == null || !perm.needFilter()) {
+            return logOrderIds;
+        }
+        // 如果待过滤集合为空,直接返回
+        if (CollectionUtils.isEmpty(logOrderIds)) {
+            return logOrderIds;
+        }
+
+        // 1. 查询物流订单详情
+        List<KwtLogisticsOrder> orders = logisticsOrderRepository.queryByLogOrderIds(logOrderIds);
+        if (CollectionUtils.isEmpty(orders)) {
+            return Sets.newHashSet();
+        }
+
+        // 2. 提取关联的贸易订单ID
+        Set<Long> tradeIds = orders.stream()
+                .map(KwtLogisticsOrder::getTOrderId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (CollectionUtils.isEmpty(tradeIds)) {
+            return Sets.newHashSet();
+        }
+
+        // 3. 查询贸易订单与合同的关联关系
+        List<TradeOrderContractVo> contractLinks = tradeOrderInfoService.queryTradeOrderIds(tradeIds);
+        Map<Long, Long> tradeIdToContractId = new HashMap<>();
+        if (CollectionUtils.isNotEmpty(contractLinks)) {
+            for (TradeOrderContractVo link : contractLinks) {
+                if (link.getTOrderId() == null || link.getContractId() == null) {
+                    continue;
+                }
+                tradeIdToContractId.putIfAbsent(link.getTOrderId(), link.getContractId());
+            }
+        }
+
+        // 4. 批量查询合同基础信息
+        List<Long> contractIdList = tradeIdToContractId.values().stream().distinct().collect(Collectors.toList());
+        Map<Long, ContractCommonInfoResDto> contractMap = Maps.newHashMap();
+        if (CollectionUtils.isNotEmpty(contractIdList)) {
+            contractMap = remoteContractService.queryContractBaseInfo(contractIdList);
+        }
+
+        // 5. 根据权限规则筛选允许的贸易订单ID
+        Set<Long> allowedTradeIds = new HashSet<>();
+        for (Long tid : tradeIds) {
+            Long cid = tradeIdToContractId.get(tid);
+            if (cid == null) {
+                continue;
+            }
+            ContractCommonInfoResDto c = contractMap.get(cid);
+            if (c == null) {
+                continue;
+            }
+
+            // 校验企业权限:如果不是全部可见,则检查合同所属企业是否在可见列表中
+            boolean entOk = true;
+            if (!perm.isAllVisible()) {
+                if (CollectionUtils.isEmpty(perm.getVisibleEntIds())) {
+                    entOk = false;
+                } else {
+                    entOk = c.getEntId() != null && perm.getVisibleEntIds().contains(c.getEntId());
+                }
+            }
+
+            // 校验个人数据权限:如果启用个人数据权限,则检查合同销售员是否为当前用户
+            boolean salesOk = true;
+            if (perm.isPersonalDataEnabled()) {
+                salesOk = perm.getUserId() != null && perm.getUserId().equals(c.getSalesmanId());
+            }
+
+            // 同时满足企业权限和个人数据权限才允许访问
+            if (entOk && salesOk) {
+                allowedTradeIds.add(tid);
+            }
+        }
+
+        // 6. 返回符合权限要求的物流订单ID集合
+        return orders.stream()
+                .filter(o -> o.getTOrderId() != null && allowedTradeIds.contains(o.getTOrderId()))
+                .map(KwtLogisticsOrder::getId)
+                .collect(Collectors.toSet());
+    }
+
     /**
      * 根据企业ID集合获取物流订单ID集合
      */