669 lines
26 KiB
Java
669 lines
26 KiB
Java
package com.designhub.service;
|
||
|
||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
import com.designhub.dto.DepartmentCreateRequest;
|
||
import com.designhub.dto.DepartmentLimitSettingsRequest;
|
||
import com.designhub.dto.DepartmentScoreAdjustRequest;
|
||
import com.designhub.dto.DepartmentUpdateRequest;
|
||
import com.designhub.entity.Brand;
|
||
import com.designhub.entity.Department;
|
||
import com.designhub.entity.DeptBrandRelation;
|
||
import com.designhub.entity.User;
|
||
import com.designhub.exception.BusinessException;
|
||
import com.designhub.mapper.BrandMapper;
|
||
import com.designhub.mapper.DepartmentMapper;
|
||
import com.designhub.mapper.DeptBrandRelationMapper;
|
||
import com.designhub.mapper.UserMapper;
|
||
import com.designhub.vo.DepartmentOverviewVO;
|
||
import lombok.RequiredArgsConstructor;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.transaction.annotation.Transactional;
|
||
import org.springframework.util.CollectionUtils;
|
||
import org.springframework.util.StringUtils;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.Arrays;
|
||
import java.util.Collections;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
import java.util.Objects;
|
||
import java.util.stream.Collectors;
|
||
|
||
/**
|
||
* 部门管理Service
|
||
*/
|
||
@Slf4j
|
||
@Service
|
||
@RequiredArgsConstructor
|
||
public class DepartmentService {
|
||
|
||
private final DepartmentMapper departmentMapper;
|
||
private final TeamScorePoolService teamScorePoolService;
|
||
private final UserMapper userMapper;
|
||
private final DeptBrandRelationMapper deptBrandRelationMapper;
|
||
private final BrandMapper brandMapper;
|
||
|
||
/**
|
||
* 获取所有部门列表
|
||
*/
|
||
public List<Department> getAllDepartments() {
|
||
return departmentMapper.selectList(
|
||
new LambdaQueryWrapper<Department>()
|
||
.eq(Department::getStatus, 1)
|
||
.orderByAsc(Department::getSortOrder)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 获取部门树形结构
|
||
*/
|
||
public List<Department> getDepartmentTree() {
|
||
List<Department> allDepts = departmentMapper.selectDeptTree();
|
||
return buildTree(allDepts, 0L);
|
||
}
|
||
|
||
/**
|
||
* 根据类型获取部门列表
|
||
*/
|
||
public List<Department> getDepartmentsByType(String deptType) {
|
||
return departmentMapper.selectList(
|
||
new LambdaQueryWrapper<Department>()
|
||
.eq(Department::getDeptType, deptType)
|
||
.eq(Department::getStatus, 1)
|
||
.orderByAsc(Department::getSortOrder)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 根据ID获取部门
|
||
*/
|
||
public Department getDepartmentById(Long id) {
|
||
return departmentMapper.selectById(id);
|
||
}
|
||
|
||
/**
|
||
* 部门概览列表
|
||
*/
|
||
public List<DepartmentOverviewVO> getDepartmentOverviewList() {
|
||
List<Department> departments = getAllDepartments();
|
||
Map<Long, Long> memberCountMap = loadMemberCountMap();
|
||
Map<Long, String> leaderNameMap = loadLeaderNames(departments);
|
||
return departments.stream()
|
||
.map(dept -> buildOverviewVO(dept, memberCountMap, leaderNameMap))
|
||
.collect(Collectors.toList());
|
||
}
|
||
|
||
/**
|
||
* 获取单个部门概览
|
||
*/
|
||
public DepartmentOverviewVO getDepartmentOverview(Long deptId) {
|
||
Department department = getDepartmentById(deptId);
|
||
if (department == null) {
|
||
throw new BusinessException("部门不存在");
|
||
}
|
||
Map<Long, Long> memberCountMap = loadMemberCountMap();
|
||
Map<Long, String> leaderNameMap = loadLeaderNames(Collections.singletonList(department));
|
||
return buildOverviewVO(department, memberCountMap, leaderNameMap);
|
||
}
|
||
|
||
/**
|
||
* 创建部门
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public DepartmentOverviewVO createDepartment(DepartmentCreateRequest request) {
|
||
validateDeptType(request.getDeptType());
|
||
|
||
// 验证负责人ID是否有效
|
||
if (request.getLeaderId() != null && request.getLeaderId() > 0) {
|
||
User leader = userMapper.selectById(request.getLeaderId());
|
||
if (leader == null) {
|
||
throw new BusinessException("指定的负责人不存在");
|
||
}
|
||
}
|
||
|
||
Department department = new Department();
|
||
department.setDeptName(request.getDeptName());
|
||
department.setDeptCode(request.getDeptCode());
|
||
department.setDeptType(request.getDeptType());
|
||
department.setParentId(request.getParentId() != null ? request.getParentId() : 0L);
|
||
department.setLeaderId(request.getLeaderId());
|
||
department.setSortOrder(request.getSortOrder());
|
||
department.setStatus(request.getStatus());
|
||
department.setAllowedDemandTypes(joinAllowedTypes(request.getAllowedDemandTypes()));
|
||
|
||
departmentMapper.insert(department);
|
||
|
||
// 初始化积分池(需求部门和一级需求部门都需要积分池)
|
||
teamScorePoolService.upsertPool(department.getId(), department.getDeptName());
|
||
if ("demand".equals(request.getDeptType()) || "primary_demand".equals(request.getDeptType())) {
|
||
if (request.getInitialScoreBalance() != null) {
|
||
teamScorePoolService.setBalance(department.getId(), request.getInitialScoreBalance());
|
||
department.setScoreBalance(request.getInitialScoreBalance());
|
||
}
|
||
teamScorePoolService.updateLimitConfig(
|
||
department.getId(),
|
||
defaultLimitEnabled(request.getLimitEnabled()),
|
||
defaultLimitPeriod(request.getLimitPeriod()),
|
||
request.getPeriodLimit(),
|
||
request.getAlertThreshold()
|
||
);
|
||
department.setLimitEnabled(defaultLimitEnabled(request.getLimitEnabled()));
|
||
department.setLimitPeriod(defaultLimitPeriod(request.getLimitPeriod()));
|
||
department.setPeriodLimit(request.getPeriodLimit());
|
||
department.setAlertThreshold(request.getAlertThreshold());
|
||
department.setOverLimitAction(
|
||
StringUtils.hasText(request.getOverLimitAction()) ? request.getOverLimitAction() : "alert"
|
||
);
|
||
}
|
||
|
||
return getDepartmentOverview(department.getId());
|
||
}
|
||
|
||
/**
|
||
* 更新部门
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public boolean updateDepartment(Long id, DepartmentUpdateRequest request) {
|
||
Department existDept = getDepartmentById(id);
|
||
if (existDept == null) {
|
||
throw new BusinessException("部门不存在");
|
||
}
|
||
|
||
if (StringUtils.hasText(request.getDeptName())) {
|
||
existDept.setDeptName(request.getDeptName());
|
||
}
|
||
if (StringUtils.hasText(request.getDeptCode())) {
|
||
existDept.setDeptCode(request.getDeptCode());
|
||
}
|
||
if (StringUtils.hasText(request.getDeptType())) {
|
||
validateDeptType(request.getDeptType());
|
||
existDept.setDeptType(request.getDeptType());
|
||
}
|
||
// 处理parentId:允许设置为0来清除(设置为null)
|
||
if (request.getParentId() != null) {
|
||
Long parentId = request.getParentId();
|
||
existDept.setParentId(parentId == 0 ? null : parentId);
|
||
}
|
||
// 处理leaderId:前端总是发送leaderId字段
|
||
// null表示清除负责人,非null数字表示设置负责人
|
||
// 由于无法区分字段不存在和字段为null,前端必须总是发送此字段
|
||
// 如果前端不发送字段,这里getLeaderId()也会返回null,但不会更新(保持原值)
|
||
// 为了支持清除,我们检查:如果leaderId字段在请求中存在(通过检查其他必填字段),则处理
|
||
// 简化方案:总是检查leaderId,如果为null且当前有值,则清除;如果为数字,则设置
|
||
// 但由于无法判断字段是否存在,我们采用:如果leaderId不为null,则更新
|
||
if (request.getLeaderId() != null) {
|
||
Long leaderId = request.getLeaderId();
|
||
// 验证负责人ID是否有效(0表示清除,大于0需要验证)
|
||
if (leaderId > 0) {
|
||
User leader = userMapper.selectById(leaderId);
|
||
if (leader == null) {
|
||
throw new BusinessException("指定的负责人不存在");
|
||
}
|
||
}
|
||
existDept.setLeaderId(leaderId == 0 ? null : leaderId);
|
||
} else if (request.getDeptName() != null) {
|
||
// 如果其他字段被更新(说明这是完整的更新请求),且leaderId为null,则清除负责人
|
||
// 这是一个启发式判断:如果请求包含deptName(通常是必填字段),则认为leaderId=null是明确的清除操作
|
||
existDept.setLeaderId(null);
|
||
}
|
||
// 否则(leaderId为null且没有其他字段更新),不处理leaderId,保持原值
|
||
if (request.getSortOrder() != null) {
|
||
existDept.setSortOrder(request.getSortOrder());
|
||
}
|
||
if (request.getStatus() != null) {
|
||
existDept.setStatus(request.getStatus());
|
||
}
|
||
if (request.getAllowedDemandTypes() != null) {
|
||
existDept.setAllowedDemandTypes(joinAllowedTypes(request.getAllowedDemandTypes()));
|
||
}
|
||
if (request.getLimitEnabled() != null) {
|
||
existDept.setLimitEnabled(request.getLimitEnabled());
|
||
}
|
||
if (request.getLimitPeriod() != null) {
|
||
existDept.setLimitPeriod(request.getLimitPeriod());
|
||
}
|
||
if (request.getPeriodLimit() != null) {
|
||
existDept.setPeriodLimit(request.getPeriodLimit());
|
||
}
|
||
if (request.getAlertThreshold() != null) {
|
||
existDept.setAlertThreshold(request.getAlertThreshold());
|
||
}
|
||
if (request.getOverLimitAction() != null) {
|
||
existDept.setOverLimitAction(request.getOverLimitAction());
|
||
}
|
||
|
||
departmentMapper.updateById(existDept);
|
||
|
||
// 同步积分池(需求部门和一级需求部门都需要积分池)
|
||
teamScorePoolService.upsertPool(existDept.getId(), existDept.getDeptName());
|
||
if (("demand".equals(existDept.getDeptType()) || "primary_demand".equals(existDept.getDeptType())) &&
|
||
(request.getLimitEnabled() != null || request.getLimitPeriod() != null ||
|
||
request.getPeriodLimit() != null || request.getAlertThreshold() != null)) {
|
||
teamScorePoolService.updateLimitConfig(
|
||
existDept.getId(),
|
||
request.getLimitEnabled(),
|
||
request.getLimitPeriod(),
|
||
request.getPeriodLimit(),
|
||
request.getAlertThreshold()
|
||
);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 更新部门限制配置
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public boolean updateLimitSettings(Long deptId, DepartmentLimitSettingsRequest request) {
|
||
Department department = getDepartmentById(deptId);
|
||
if (department == null) {
|
||
throw new BusinessException("部门不存在");
|
||
}
|
||
if (!"demand".equals(department.getDeptType()) && !"primary_demand".equals(department.getDeptType())) {
|
||
throw new BusinessException("只有需求部门或一级需求部门需要配置积分限制");
|
||
}
|
||
|
||
department.setLimitEnabled(request.getLimitEnabled());
|
||
department.setLimitPeriod(request.getLimitPeriod());
|
||
department.setPeriodLimit(request.getPeriodLimit());
|
||
department.setAlertThreshold(request.getAlertThreshold());
|
||
department.setOverLimitAction(request.getOverLimitAction());
|
||
departmentMapper.updateById(department);
|
||
|
||
teamScorePoolService.updateLimitConfig(
|
||
deptId,
|
||
request.getLimitEnabled(),
|
||
request.getLimitPeriod(),
|
||
request.getPeriodLimit(),
|
||
request.getAlertThreshold()
|
||
);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 删除部门(逻辑删除)
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public boolean deleteDepartment(Long id) {
|
||
long childCount = departmentMapper.selectCount(
|
||
new LambdaQueryWrapper<Department>()
|
||
.eq(Department::getParentId, id)
|
||
);
|
||
if (childCount > 0) {
|
||
throw new BusinessException("该部门下还有子部门,无法删除");
|
||
}
|
||
|
||
return departmentMapper.deleteById(id) > 0;
|
||
}
|
||
|
||
/**
|
||
* 设置部门负责人/主管
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public boolean setDepartmentHead(Long deptId, Long userId, String type) {
|
||
Department department = getDepartmentById(deptId);
|
||
if (department == null) {
|
||
throw new BusinessException("部门不存在");
|
||
}
|
||
|
||
if ("head".equals(type)) {
|
||
if (!"demand".equals(department.getDeptType()) && !"primary_demand".equals(department.getDeptType())) {
|
||
throw new BusinessException("只有需求部门或一级需求部门可以设置负责人");
|
||
}
|
||
department.setLeaderId(userId);
|
||
} else if ("supervisor".equals(type)) {
|
||
if (!"receiving".equals(department.getDeptType())) {
|
||
throw new BusinessException("只有接单部门可以设置主管");
|
||
}
|
||
department.setSupervisorId(userId);
|
||
} else {
|
||
throw new BusinessException("类型参数错误");
|
||
}
|
||
|
||
return departmentMapper.updateById(department) > 0;
|
||
}
|
||
|
||
/**
|
||
* 调整部门积分
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public void adjustScore(Long deptId, DepartmentScoreAdjustRequest request) {
|
||
Department department = getDepartmentById(deptId);
|
||
if (department == null) {
|
||
throw new BusinessException("部门不存在");
|
||
}
|
||
if (!"demand".equals(department.getDeptType()) && !"primary_demand".equals(department.getDeptType())) {
|
||
throw new BusinessException("只有需求部门或一级需求部门可以调整积分");
|
||
}
|
||
if (request.getAmount() == null || request.getAmount() <= 0) {
|
||
throw new BusinessException("调整积分必须大于0");
|
||
}
|
||
|
||
String action = request.getAction().toLowerCase();
|
||
switch (action) {
|
||
case "recharge" -> teamScorePoolService.rechargeScore(deptId, request.getAmount());
|
||
case "deduct" -> teamScorePoolService.deductScore(deptId, request.getAmount());
|
||
default -> throw new BusinessException("不支持的积分操作类型");
|
||
}
|
||
}
|
||
|
||
private void validateDeptType(String deptType) {
|
||
if (!"demand".equals(deptType) && !"receiving".equals(deptType) && !"primary_demand".equals(deptType)) {
|
||
throw new BusinessException("部门类型必须是 demand、receiving 或 primary_demand");
|
||
}
|
||
}
|
||
|
||
// ==================== 品牌关联管理 ====================
|
||
|
||
/**
|
||
* 根据品牌ID获取负责的需求部门
|
||
*/
|
||
public Department getDemandDeptByBrandId(Long brandId) {
|
||
if (brandId == null) {
|
||
return null;
|
||
}
|
||
Long deptId = deptBrandRelationMapper.getDeptIdByBrandId(brandId);
|
||
if (deptId == null) {
|
||
return null;
|
||
}
|
||
return departmentMapper.selectById(deptId);
|
||
}
|
||
|
||
/**
|
||
* 设置部门负责的品牌
|
||
*/
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public void setDeptResponsibleBrands(Long deptId, List<Long> brandIds) {
|
||
Department department = getDepartmentById(deptId);
|
||
if (department == null) {
|
||
throw new BusinessException("部门不存在");
|
||
}
|
||
if (!"demand".equals(department.getDeptType())) {
|
||
throw new BusinessException("只有需求部门可以设置负责品牌");
|
||
}
|
||
|
||
// 检查品牌是否已被其他部门负责
|
||
if (!CollectionUtils.isEmpty(brandIds)) {
|
||
for (Long brandId : brandIds) {
|
||
Long existingDeptId = deptBrandRelationMapper.getDeptIdByBrandId(brandId);
|
||
if (existingDeptId != null && !existingDeptId.equals(deptId)) {
|
||
Brand brand = brandMapper.selectById(brandId);
|
||
Department existingDept = departmentMapper.selectById(existingDeptId);
|
||
throw new BusinessException("品牌 [" + (brand != null ? brand.getName() : brandId) +
|
||
"] 已被部门 [" + (existingDept != null ? existingDept.getDeptName() : existingDeptId) + "] 负责");
|
||
}
|
||
}
|
||
}
|
||
|
||
// 删除原有关联
|
||
deptBrandRelationMapper.deleteByDeptId(deptId);
|
||
|
||
// 批量插入新关联
|
||
if (!CollectionUtils.isEmpty(brandIds)) {
|
||
deptBrandRelationMapper.batchInsert(deptId, brandIds);
|
||
}
|
||
|
||
log.info("设置部门 {} 负责品牌: {}", deptId, brandIds);
|
||
}
|
||
|
||
/**
|
||
* 获取部门负责的品牌列表
|
||
*/
|
||
public List<Brand> getDeptResponsibleBrands(Long deptId) {
|
||
List<Long> brandIds = deptBrandRelationMapper.getBrandIdsByDeptId(deptId);
|
||
if (CollectionUtils.isEmpty(brandIds)) {
|
||
return Collections.emptyList();
|
||
}
|
||
return brandMapper.selectBatchIds(brandIds);
|
||
}
|
||
|
||
/**
|
||
* 获取部门负责的品牌ID列表
|
||
*/
|
||
public List<Long> getDeptResponsibleBrandIds(Long deptId) {
|
||
return deptBrandRelationMapper.getBrandIdsByDeptId(deptId);
|
||
}
|
||
|
||
/**
|
||
* 获取所有品牌-部门关联关系
|
||
*/
|
||
public List<DeptBrandRelation> getAllBrandDeptRelations() {
|
||
return deptBrandRelationMapper.getAllRelationsWithNames();
|
||
}
|
||
|
||
/**
|
||
* 检查部门是否为一级需求部门
|
||
*/
|
||
public boolean isPrimaryDemandDept(Long deptId) {
|
||
if (deptId == null) {
|
||
return false;
|
||
}
|
||
Department dept = getDepartmentById(deptId);
|
||
return dept != null && "primary_demand".equals(dept.getDeptType());
|
||
}
|
||
|
||
/**
|
||
* 检查部门是否可以发起任务(需求部门或一级需求部门)
|
||
*/
|
||
public boolean canPublishTask(Long deptId) {
|
||
if (deptId == null) {
|
||
return false;
|
||
}
|
||
Department dept = getDepartmentById(deptId);
|
||
if (dept == null) {
|
||
return false;
|
||
}
|
||
String deptType = dept.getDeptType();
|
||
return "demand".equals(deptType) || "primary_demand".equals(deptType);
|
||
}
|
||
|
||
/**
|
||
* 获取所有一级需求部门
|
||
*/
|
||
public List<Department> getPrimaryDemandDepartments() {
|
||
return departmentMapper.selectList(
|
||
new LambdaQueryWrapper<Department>()
|
||
.eq(Department::getDeptType, "primary_demand")
|
||
.eq(Department::getStatus, 1)
|
||
.orderByAsc(Department::getSortOrder)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 获取所有需求部门的ID列表(只包括 demand 类型,不包括 primary_demand)
|
||
* 用于跨部门成员分配功能
|
||
* 注意:一级需求部门(primary_demand)的成员不应该出现在下拉列表中
|
||
*/
|
||
public List<Long> getAllDemandDeptIds() {
|
||
List<Department> demandDepts = departmentMapper.selectList(
|
||
new LambdaQueryWrapper<Department>()
|
||
.eq(Department::getDeptType, "demand") // 只查询 demand 类型,不包括 primary_demand
|
||
.eq(Department::getStatus, 1)
|
||
.eq(Department::getDeleted, 0)
|
||
);
|
||
|
||
List<Long> allDeptIds = new java.util.ArrayList<>();
|
||
for (Department dept : demandDepts) {
|
||
allDeptIds.add(dept.getId());
|
||
// 递归获取所有子部门ID
|
||
allDeptIds.addAll(getAllChildDeptIds(dept.getId()));
|
||
}
|
||
|
||
return allDeptIds;
|
||
}
|
||
|
||
private Integer defaultLimitEnabled(Integer limitEnabled) {
|
||
return limitEnabled != null ? limitEnabled : 0;
|
||
}
|
||
|
||
private String defaultLimitPeriod(String limitPeriod) {
|
||
return StringUtils.hasText(limitPeriod) ? limitPeriod : "MONTHLY";
|
||
}
|
||
|
||
private String joinAllowedTypes(List<String> allowedTypes) {
|
||
if (CollectionUtils.isEmpty(allowedTypes)) {
|
||
return null;
|
||
}
|
||
return allowedTypes.stream()
|
||
.filter(StringUtils::hasText)
|
||
.collect(Collectors.joining(","));
|
||
}
|
||
|
||
private List<String> splitAllowedTypes(String allowedTypes) {
|
||
if (allowedTypes == null || allowedTypes.trim().isEmpty()) {
|
||
return Collections.emptyList();
|
||
}
|
||
return Arrays.stream(allowedTypes.split(","))
|
||
.map(String::trim)
|
||
.filter(StringUtils::hasText)
|
||
.collect(Collectors.toList());
|
||
}
|
||
|
||
private Map<Long, Long> loadMemberCountMap() {
|
||
// 只统计启用且未删除的用户
|
||
return userMapper.selectList(
|
||
new LambdaQueryWrapper<User>()
|
||
.eq(User::getStatus, 1)
|
||
.eq(User::getDeleted, 0)
|
||
).stream()
|
||
.filter(user -> user.getDeptId() != null)
|
||
.collect(Collectors.groupingBy(
|
||
User::getDeptId,
|
||
Collectors.counting()
|
||
));
|
||
}
|
||
|
||
private Map<Long, String> loadLeaderNames(List<Department> departments) {
|
||
List<Long> leaderIds = departments.stream()
|
||
.map(Department::getLeaderId)
|
||
.filter(Objects::nonNull)
|
||
.distinct()
|
||
.collect(Collectors.toList());
|
||
if (leaderIds.isEmpty()) {
|
||
return Collections.emptyMap();
|
||
}
|
||
return userMapper.selectBatchIds(leaderIds).stream()
|
||
.collect(Collectors.toMap(
|
||
User::getId,
|
||
user -> StringUtils.hasText(user.getRealName()) ? user.getRealName() : user.getUsername()
|
||
));
|
||
}
|
||
|
||
private DepartmentOverviewVO buildOverviewVO(Department department,
|
||
Map<Long, Long> memberCountMap,
|
||
Map<Long, String> leaderNameMap) {
|
||
DepartmentOverviewVO vo = new DepartmentOverviewVO();
|
||
vo.setId(department.getId());
|
||
vo.setDeptName(department.getDeptName());
|
||
vo.setDeptCode(department.getDeptCode());
|
||
vo.setDeptType(department.getDeptType());
|
||
vo.setParentId(department.getParentId());
|
||
vo.setLeaderId(department.getLeaderId());
|
||
if (department.getLeaderId() != null && leaderNameMap != null) {
|
||
vo.setLeaderName(leaderNameMap.get(department.getLeaderId()));
|
||
}
|
||
vo.setDescription(department.getDescription());
|
||
vo.setSortOrder(department.getSortOrder());
|
||
vo.setStatus(department.getStatus());
|
||
vo.setAllowedDemandTypes(splitAllowedTypes(department.getAllowedDemandTypes()));
|
||
|
||
var pool = teamScorePoolService.getByDeptId(department.getId());
|
||
if (pool != null) {
|
||
vo.setScoreBalance(pool.getBalance());
|
||
vo.setTotalRecharge(pool.getTotalRecharge());
|
||
vo.setTotalConsume(pool.getTotalConsume());
|
||
vo.setTotalEarn(pool.getTotalEarn());
|
||
vo.setLimitEnabled(pool.getLimitEnabled());
|
||
vo.setLimitPeriod(pool.getLimitPeriod());
|
||
vo.setPeriodLimit(pool.getPeriodLimit());
|
||
vo.setPeriodUsed(pool.getPeriodUsed());
|
||
vo.setAlertThreshold(pool.getAlertThreshold());
|
||
vo.setLimitAlert(teamScorePoolService.isAlert(department.getId()));
|
||
} else {
|
||
vo.setScoreBalance(department.getScoreBalance());
|
||
vo.setLimitEnabled(department.getLimitEnabled());
|
||
vo.setLimitPeriod(department.getLimitPeriod());
|
||
vo.setPeriodLimit(department.getPeriodLimit());
|
||
vo.setAlertThreshold(department.getAlertThreshold());
|
||
vo.setLimitAlert(false);
|
||
}
|
||
vo.setOverLimitAction(department.getOverLimitAction());
|
||
|
||
if (memberCountMap != null && memberCountMap.containsKey(department.getId())) {
|
||
vo.setMemberCount(memberCountMap.get(department.getId()).intValue());
|
||
} else {
|
||
vo.setMemberCount(0);
|
||
}
|
||
return vo;
|
||
}
|
||
|
||
/**
|
||
* 构建树形结构
|
||
*/
|
||
private List<Department> buildTree(List<Department> allDepts, Long parentId) {
|
||
List<Department> children = allDepts.stream()
|
||
.filter(dept -> {
|
||
Long deptParentId = dept.getParentId();
|
||
if (deptParentId == null) {
|
||
return parentId == null || parentId == 0L;
|
||
}
|
||
return deptParentId.equals(parentId);
|
||
})
|
||
.collect(Collectors.toList());
|
||
|
||
for (Department child : children) {
|
||
buildTree(allDepts, child.getId());
|
||
}
|
||
|
||
return children;
|
||
}
|
||
|
||
/**
|
||
* 获取部门的所有子部门ID(递归)
|
||
*/
|
||
public List<Long> getAllChildDeptIds(Long deptId) {
|
||
List<Long> result = new ArrayList<>();
|
||
if (deptId == null) {
|
||
return result;
|
||
}
|
||
|
||
// 查找直接子部门(只查询未删除且启用的部门)
|
||
List<Department> children = departmentMapper.selectList(
|
||
new LambdaQueryWrapper<Department>()
|
||
.eq(Department::getParentId, deptId)
|
||
.eq(Department::getDeleted, 0)
|
||
.eq(Department::getStatus, 1)
|
||
);
|
||
|
||
// 递归获取所有子部门
|
||
for (Department child : children) {
|
||
result.add(child.getId());
|
||
result.addAll(getAllChildDeptIds(child.getId()));
|
||
}
|
||
|
||
log.info("获取部门{}的所有子部门ID: {}", deptId, result);
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 检查用户是否为任何部门的负责人
|
||
*/
|
||
public boolean isUserDepartmentLeader(Long userId) {
|
||
if (userId == null) {
|
||
return false;
|
||
}
|
||
|
||
// 查询是否有部门的 leader_id 等于该用户ID
|
||
Long count = departmentMapper.selectCount(
|
||
new LambdaQueryWrapper<Department>()
|
||
.eq(Department::getLeaderId, userId)
|
||
.eq(Department::getStatus, 1)
|
||
);
|
||
|
||
return count != null && count > 0;
|
||
}
|
||
}
|
||
|