|
|
@@ -2274,6 +2274,7 @@ public class KwtLogisticsConsignmentService {
|
|
|
// 3. 获取物流订单ID集合
|
|
|
log.debug("获取物流订单ID集合");
|
|
|
Set<Long> logOrderIds = getLogOrderIds(req, entList, allEnt);
|
|
|
+ // 应用数据权限过滤
|
|
|
logOrderIds = applyDataPermissionFilterToLogOrderIds(logOrderIds);
|
|
|
|
|
|
// 4. 检查是否需要返回空结果
|
|
|
@@ -2719,95 +2720,177 @@ public class KwtLogisticsConsignmentService {
|
|
|
*/
|
|
|
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
- * 按数据权限收缩物流订单ID:
|
|
|
- * 企业权限:贸易合同 ent_id 落在已勾选企业范围内;
|
|
|
- * 个人权限:贸易合同 salesman_id 为当前用户;
|
|
|
- * 两者同时开启时为 AND(与系统模块 DataPermissionDTO 规则一致)。
|
|
|
+ * 应用数据权限过滤到物流订单ID集合
|
|
|
+ * <p>
|
|
|
+ * 根据当前登录用户的数据权限配置,对传入的物流订单ID集合进行过滤。
|
|
|
+ * 支持企业维度权限(可见企业范围)和个人维度权限(销售员匹配)。
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param logOrderIds 待过滤的物流订单ID集合
|
|
|
+ * @return 过滤后的物流订单ID集合
|
|
|
*/
|
|
|
private Set<Long> applyDataPermissionFilterToLogOrderIds(Set<Long> logOrderIds) {
|
|
|
// 1. 获取当前用户的数据权限配置
|
|
|
DataPermissionDTO perm = fetchDataPermissionForCurrentUser();
|
|
|
- // 如果无需过滤或权限对象为空,直接返回原始ID集合
|
|
|
+
|
|
|
+ // 如果未获取到权限配置或不需要进行数据过滤,直接返回原始ID集合da
|
|
|
if (perm == null || !perm.needFilter()) {
|
|
|
+ log.debug("数据权限过滤:无需过滤或权限配置为空,返回原始订单ID集合,大小: {}",
|
|
|
+ CollectionUtils.isEmpty(logOrderIds) ? 0 : logOrderIds.size());
|
|
|
return logOrderIds;
|
|
|
}
|
|
|
- // 如果输入ID集合为空,直接返回
|
|
|
+
|
|
|
+ // 如果输入的订单ID集合为空,直接返回
|
|
|
if (CollectionUtils.isEmpty(logOrderIds)) {
|
|
|
+ log.debug("数据权限过滤:输入订单ID集合为空");
|
|
|
return logOrderIds;
|
|
|
}
|
|
|
|
|
|
- // 2. 查询物流订单详情,获取关联的贸易订单ID
|
|
|
+ log.info("开始应用数据权限过滤,初始订单ID数量: {}, 用户ID: {}", logOrderIds.size(), LoginUserHolder.getUserId());
|
|
|
+ Set<Long> result = new HashSet<>(logOrderIds);
|
|
|
+
|
|
|
+ // 2. 处理企业维度数据权限
|
|
|
+ // 如果不是所有数据可见,则需要根据可见企业ID进行过滤
|
|
|
+ if (!perm.isAllVisible()) {
|
|
|
+ // 如果可见企业ID列表为空,说明该用户无权查看任何企业数据,返回空集合
|
|
|
+ if (CollectionUtils.isEmpty(perm.getVisibleEntIds())) {
|
|
|
+ log.warn("数据权限过滤:用户无可见企业权限,返回空集合");
|
|
|
+ return Sets.newHashSet();
|
|
|
+ }
|
|
|
+
|
|
|
+ log.debug("数据权限过滤:根据可见企业ID过滤,可见企业数量: {}", perm.getVisibleEntIds().size());
|
|
|
+ // 查询这些企业关联的所有物流订单单位信息
|
|
|
+ List<KwtLogisticsOrderUnit> units =
|
|
|
+ logisticsOrderUnitRepository.queryByEntIds(new HashSet<>(perm.getVisibleEntIds()));
|
|
|
+
|
|
|
+ // 提取出这些单位对应的物流订单ID
|
|
|
+ Set<Long> entScopeLogOrderIds = units.stream()
|
|
|
+ .map(KwtLogisticsOrderUnit::getLOrderId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ log.debug("数据权限过滤:企业维度关联的订单ID数量: {}", entScopeLogOrderIds.size());
|
|
|
+
|
|
|
+ // 取交集:只保留在当前用户可见企业范围内的订单ID
|
|
|
+ result.retainAll(entScopeLogOrderIds);
|
|
|
+ log.debug("数据权限过滤:企业维度过滤后剩余订单ID数量: {}", result.size());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果经过企业维度过滤后结果为空,直接返回
|
|
|
+ if (CollectionUtils.isEmpty(result)) {
|
|
|
+ log.info("数据权限过滤:企业维度过滤后无剩余订单,提前返回");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 处理个人维度数据权限
|
|
|
+ // 如果未启用个人数据权限控制,则直接返回当前结果
|
|
|
+ if (!perm.isPersonalDataEnabled()) {
|
|
|
+ log.info("数据权限过滤:未启用个人数据权限,最终订单ID数量: {}", result.size());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 启用个人数据权限时,进一步过滤:仅保留关联贸易合同中销售员为当前用户的物流订单
|
|
|
+ log.debug("数据权限过滤:启用个人数据权限,开始按销售员过滤");
|
|
|
+ Set<Long> finalResult = filterLogOrderIdsByTradeContractSalesman(result, perm);
|
|
|
+ log.info("数据权限过滤完成,最终订单ID数量: {}", finalResult.size());
|
|
|
+
|
|
|
+ return finalResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 个人数据权限过滤:仅保留关联贸易合同中销售员为当前用户的物流订单
|
|
|
+ * <p>
|
|
|
+ * 逻辑链路:物流订单 -> 贸易订单ID -> 贸易合同ID -> 合同销售员ID == 当前用户ID
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param logOrderIds 待过滤的物流订单ID集合
|
|
|
+ * @param perm 当前用户的数据权限DTO
|
|
|
+ * @return 过滤后的物流订单ID集合
|
|
|
+ */
|
|
|
+ private Set<Long> filterLogOrderIdsByTradeContractSalesman(Set<Long> logOrderIds, DataPermissionDTO perm) {
|
|
|
+ // 校验用户ID,若为空则无法进行个人权限匹配,返回空集合
|
|
|
+ if (perm.getUserId() == null) {
|
|
|
+ log.warn("个人数据权限过滤:用户ID为空,返回空集合");
|
|
|
+ return Sets.newHashSet();
|
|
|
+ }
|
|
|
+
|
|
|
+ Long currentUserId = perm.getUserId();
|
|
|
+ log.debug("个人数据权限过滤:开始处理,待过滤订单数: {}, 当前用户ID: {}", logOrderIds.size(), currentUserId);
|
|
|
+
|
|
|
+ // 1. 查询物流订单详情,获取关联的贸易订单ID
|
|
|
List<KwtLogisticsOrder> orders = logisticsOrderRepository.queryByLogOrderIds(logOrderIds);
|
|
|
if (CollectionUtils.isEmpty(orders)) {
|
|
|
+ log.debug("个人数据权限过滤:未查询到物流订单详情,返回空集合");
|
|
|
return Sets.newHashSet();
|
|
|
}
|
|
|
+
|
|
|
+ // 提取所有非空的贸易订单ID
|
|
|
Set<Long> tradeIds = orders.stream()
|
|
|
.map(KwtLogisticsOrder::getTOrderId)
|
|
|
.filter(Objects::nonNull)
|
|
|
.collect(Collectors.toSet());
|
|
|
+
|
|
|
if (CollectionUtils.isEmpty(tradeIds)) {
|
|
|
+ log.warn("个人数据权限过滤:物流订单中未找到关联的贸易订单ID,返回空集合");
|
|
|
return Sets.newHashSet();
|
|
|
}
|
|
|
+ log.debug("个人数据权限过滤:提取到贸易订单ID数量: {}", tradeIds.size());
|
|
|
|
|
|
- // 3. 通过贸易订单ID查询关联的合同ID
|
|
|
+ // 2. 查询贸易订单与合同的关联关系
|
|
|
List<TradeOrderContractVo> contractLinks = tradeOrderInfoService.queryTradeOrderIds(tradeIds);
|
|
|
Map<Long, Long> tradeIdToContractId = new HashMap<>();
|
|
|
if (CollectionUtils.isNotEmpty(contractLinks)) {
|
|
|
for (TradeOrderContractVo link : contractLinks) {
|
|
|
+ // 确保贸易订单ID和合同ID均不为空
|
|
|
if (link.getTOrderId() == null || link.getContractId() == null) {
|
|
|
continue;
|
|
|
}
|
|
|
+ // 使用 putIfAbsent 避免覆盖,通常一个贸易订单对应一个主合同
|
|
|
tradeIdToContractId.putIfAbsent(link.getTOrderId(), link.getContractId());
|
|
|
}
|
|
|
}
|
|
|
+ log.debug("个人数据权限过滤:贸易订单-合同映射关系数量: {}", tradeIdToContractId.size());
|
|
|
|
|
|
- // 4. 批量查询合同基础信息
|
|
|
+ // 3. 批量查询合同基础信息,获取销售员ID
|
|
|
List<Long> contractIdList = tradeIdToContractId.values().stream().distinct().collect(Collectors.toList());
|
|
|
Map<Long, ContractCommonInfoResDto> contractMap = Maps.newHashMap();
|
|
|
if (CollectionUtils.isNotEmpty(contractIdList)) {
|
|
|
contractMap = contractService.queryContractBaseInfo(contractIdList);
|
|
|
+ log.debug("个人数据权限过滤:查询到合同信息数量: {}", contractMap.size());
|
|
|
+ } else {
|
|
|
+ log.warn("个人数据权限过滤:未找到关联的合同ID列表");
|
|
|
}
|
|
|
|
|
|
- // 5. 根据数据权限规则过滤允许的贸易订单ID
|
|
|
+ // 4. 筛选出销售员为当前用户的贸易订单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) {
|
|
|
+ ContractCommonInfoResDto contractInfo = contractMap.get(cid);
|
|
|
+ if (contractInfo == 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) {
|
|
|
+ // 判断合同销售员是否等于当前用户
|
|
|
+ if (currentUserId.equals(contractInfo.getSalesmanId())) {
|
|
|
allowedTradeIds.add(tid);
|
|
|
}
|
|
|
}
|
|
|
+ log.debug("个人数据权限过滤:匹配到当前用户作为销售员的贸易订单数量: {}", allowedTradeIds.size());
|
|
|
|
|
|
- // 6. 返回过滤后的物流订单ID集合
|
|
|
- return orders.stream()
|
|
|
- .filter(o -> o.getTOrderId() != null && allowedTradeIds.contains(o.getTOrderId()))
|
|
|
+ // 5. 根据允许的贸易订单ID,反向过滤出最终的物流订单ID
|
|
|
+ Set<Long> finalLogOrderIds = orders.stream()
|
|
|
+ .filter(order -> order.getTOrderId() != null && allowedTradeIds.contains(order.getTOrderId()))
|
|
|
.map(KwtLogisticsOrder::getId)
|
|
|
.collect(Collectors.toSet());
|
|
|
+
|
|
|
+ log.debug("个人数据权限过滤:最终保留的物流订单数量: {}", finalLogOrderIds.size());
|
|
|
+ return finalLogOrderIds;
|
|
|
}
|
|
|
|
|
|
private DataPermissionDTO fetchDataPermissionForCurrentUser() {
|
|
|
@@ -2930,7 +3013,6 @@ public class KwtLogisticsConsignmentService {
|
|
|
return logOrderIds;
|
|
|
}
|
|
|
|
|
|
- @NotNull
|
|
|
private Long getAllEnt(String entId) {
|
|
|
//根据企业类型查询企业
|
|
|
Long enterId = null;
|
|
|
@@ -2942,8 +3024,6 @@ public class KwtLogisticsConsignmentService {
|
|
|
|
|
|
return enterId;
|
|
|
}
|
|
|
-
|
|
|
- @NotNull
|
|
|
private static LogisticsOrderResp getLogisticsOrderResp(KwtLogisticsOrder kwtLogisticsOrder,
|
|
|
Map<String, KwtLogisticsOrderUnit> finalLogOrderIdAndUnitTypeKeyAndUnitMap,
|
|
|
Map<Long, KwtLogisticsOrderGoods> finalLogIdAndGoodsMap,
|