完善部门信息

This commit is contained in:
2024-03-18 09:04:44 +08:00
parent 559be98b29
commit e25c22ecbb
14 changed files with 290 additions and 22 deletions

View File

@@ -16,6 +16,8 @@ public interface BaseRepository<T> extends JpaRepository<T, String>, JpaSpecific
return findById(id).orElseThrow(() -> new RuntimeException("数据不存在: " + id));
}
default List<T> findByOrganizationId(String organizationId) {
return findAll(
(root, query, cb) -> {

View File

@@ -15,6 +15,31 @@ import java.util.function.Function;
@UtilityClass
public class TreeUtils {
public static <T> Iterable<T> buildTreeFromList(Iterable<T> src, Function<T, String> idGetter, Function<T, String> parentIdGetter, Function2<T, T, Void> childrenAppender) {
Map<String, T> map = new HashMap<>();
List<T> roots = new ArrayList<>();
for (T t : src) {
map.put(idGetter.apply(t), t);
}
for (T t : src) {
String parentId = parentIdGetter.apply(t);
if (parentId == null || parentId.isEmpty()) {
roots.add(t);
} else {
T parent = map.get(parentId);
if (parent == null) {
throw new BizException("父节点不存在 " + parentId);
}
childrenAppender.apply(parent, t);
}
}
return roots;
}
public static <T> Iterable<T> allChildren(T src, Function<T, Iterable<T>> childrenGetter) {
ArrayList<T> ans = new ArrayList<>();

View File

@@ -0,0 +1,70 @@
package cn.lihongjie.coal.dbFunctions;
import io.hypersistence.utils.hibernate.type.array.StringArrayType;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import org.hibernate.query.TypedParameterValue;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class DbFunctionService {
@PersistenceContext
EntityManager entityManager;
public List<String> selfAndChildrenIds(String tableName, List<String> ids) {
return selfAndChildrenIds(tableName, ids, true);
}
public List<String> selfAndChildrenIds(String tableName, List<String> ids, Boolean includeSelf){
Query nativeQuery = entityManager.createNativeQuery("""
select self_and_children_ids(:tableName, :ids, :includeSelf)
""");
nativeQuery.setParameter("tableName", tableName);
nativeQuery.unwrap(org.hibernate.query.Query.class).setParameter("ids", new TypedParameterValue(StringArrayType.INSTANCE, ids.toArray()));
nativeQuery.setParameter("includeSelf", includeSelf);
List resultList = nativeQuery.getResultList();
if (resultList.isEmpty()){
return Collections.emptyList();
}
return Arrays.stream(((String[]) resultList.get(0))).toList();
}
public List<String> selfAndParentIds(String tableName, List<String> ids) {
return selfAndParentIds(tableName, ids, true);
}
public List<String> selfAndParentIds(String tableName, List<String> ids, Boolean includeSelf){
Query nativeQuery = entityManager.createNativeQuery("""
select self_and_parent_ids(:tableName, :ids, :includeSelf)
""");
nativeQuery.setParameter("tableName", tableName);
nativeQuery.unwrap(org.hibernate.query.Query.class).setParameter("ids", new TypedParameterValue(StringArrayType.INSTANCE, ids.toArray()));
nativeQuery.setParameter("includeSelf", includeSelf);
List resultList = nativeQuery.getResultList();
if (resultList.isEmpty()){
return Collections.emptyList();
}
return Arrays.stream(((String[]) resultList.get(0))).toList();
}
}

View File

@@ -58,8 +58,8 @@ public class DepartmentController {
@PostMapping("/roots")
public List<DepartmentTreeDto> roots() {
return this.service.getRoots();
public List<DepartmentTreeDto> roots(@RequestBody CommonQuery request) {
return this.service.getRoots(request);
}
@PostMapping("/treeByIds")

View File

@@ -4,9 +4,15 @@ import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import java.util.List;
@Data
public class DepartmentDto extends OrgCommonDto {
private String parent;
private Integer empCount;
private List<String> allEmpIds;
private List<String> childrenEmpIds;
private List<String> selfEmpIds;
}

View File

@@ -8,7 +8,11 @@ import java.util.List;
@Data
public class DepartmentTreeDto extends OrgCommonDto {
private Integer empCount;
private List<String> allEmpIds;
private List<String> childrenEmpIds;
private List<String> selfEmpIds;
private String parent;
private List<DepartmentTreeDto> children;
}

View File

@@ -2,16 +2,16 @@ package cn.lihongjie.coal.department.entity;
import cn.lihongjie.coal.base.entity.OrgCommonEntity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import io.hypersistence.utils.hibernate.type.array.ListArrayType;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.Type;
import java.util.List;
@@ -21,8 +21,21 @@ import java.util.List;
@Setter
public class DepartmentEntity extends OrgCommonEntity {
@Formula("(select count(*) from t_employee e where e.department_id = any(self_and_children_ids('t_department', id)))")
private Integer empCount;
@Type(ListArrayType.class)
@Formula("(select array_agg(e.id) from t_employee e where e.department_id = any(self_and_children_ids('t_department', id, true)))")
private List<String> allEmpIds;
@Type(ListArrayType.class)
@Formula("(select array_agg(e.id) from t_employee e where e.department_id = any(self_and_children_ids('t_department', id, false)))")
private List<String> childrenEmpIds;
@Type(ListArrayType.class)
@Formula("(select array_agg(e.id) from t_employee e where e.department_id = id)")
private List<String> selfEmpIds;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<DepartmentEntity> children;

View File

@@ -7,17 +7,28 @@ import cn.lihongjie.coal.department.dto.DepartmentTreeDto;
import cn.lihongjie.coal.department.dto.UpdateDepartmentDto;
import cn.lihongjie.coal.department.entity.DepartmentEntity;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.*;
import org.mapstruct.control.DeepClone;
@Mapper(
componentModel = MappingConstants.ComponentModel.SPRING,
uses = {cn.lihongjie.coal.base.mapper.CommonMapper.class, cn.lihongjie.coal.base.mapper.CommonEntityMapper.class},
uses = {
cn.lihongjie.coal.base.mapper.CommonMapper.class,
cn.lihongjie.coal.base.mapper.CommonEntityMapper.class
},
mappingControl = DeepClone.class)
public interface DepartmentMapper
extends BaseMapper<
DepartmentEntity, DepartmentDto, CreateDepartmentDto, UpdateDepartmentDto> {
@Mappings({
@Mapping(target = "children", qualifiedByName = "toTreeDto")
})
@Named("toTreeDto")
DepartmentTreeDto toTreeDto(DepartmentEntity departmentEntity);
@Mappings({
@Mapping(target = "children", ignore = true)
})
DepartmentTreeDto toTreeDtoExcludeChildren(DepartmentEntity departmentEntity);
}

View File

@@ -6,4 +6,6 @@ import cn.lihongjie.coal.department.entity.DepartmentEntity;
import org.springframework.stereotype.Repository;
@Repository
public interface DepartmentRepository extends BaseRepository<DepartmentEntity> {}
public interface DepartmentRepository extends BaseRepository<DepartmentEntity> {
}

View File

@@ -3,6 +3,8 @@ package cn.lihongjie.coal.department.service;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.common.TreeUtils;
import cn.lihongjie.coal.dbFunctions.DbFunctionService;
import cn.lihongjie.coal.department.dto.CreateDepartmentDto;
import cn.lihongjie.coal.department.dto.DepartmentDto;
import cn.lihongjie.coal.department.dto.DepartmentTreeDto;
@@ -15,6 +17,7 @@ import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
@@ -26,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@Service
@Slf4j
@@ -70,10 +74,48 @@ class DepartmentService extends BaseService<DepartmentEntity, DepartmentReposito
return mapper.toDto(entity);
}
public List<DepartmentTreeDto> getRoots() {
@Autowired DbFunctionService dbFunctionService;
public List<DepartmentTreeDto> getRoots(CommonQuery request) {
if (CollectionUtils.isEmpty(request.getItems())){
List<DepartmentEntity> roots = this.repository.findAll( (root, query, criteriaBuilder) -> criteriaBuilder.isNull(root.get("parent")));
return roots.stream().map(de -> this.mapper.toTreeDto(de)).collect(Collectors.toList());
}else {
Page<DepartmentEntity> page =
repository.findAll(
request.specification(conversionService),
PageRequest.of(
request.getPageNo(),
request.getPageSize(),
Sort.by(request.getOrders())));
List<String> selfAndParentIds =
this.dbFunctionService.selfAndParentIds("t_department",
page.stream().map(x -> x.getId()).collect(Collectors.toList()), true);
List<DepartmentTreeDto> selfAndParent = this.findAllByIds(selfAndParentIds).stream().map(x -> (this.mapper.toTreeDtoExcludeChildren(x))).collect(Collectors.toList());
return StreamSupport.stream(
TreeUtils.buildTreeFromList(
selfAndParent,
DepartmentTreeDto::getId,
x -> x.getParent(),
(x, y) -> {
if (x.getChildren() == null) {
x.setChildren(new ArrayList<>());
}
x.getChildren().add(y);
return null;
})
.spliterator(),
false)
.collect(Collectors.toList());
}
List<DepartmentEntity> roots = this.repository.findAll( (root, query, criteriaBuilder) -> criteriaBuilder.isNull(root.get("parent")));
return roots.stream().map(de -> this.mapper.toTreeDto(de)).collect(Collectors.toList());
}

View File

@@ -205,7 +205,7 @@ class DictionaryService extends BaseService<DictionaryEntity, DictionaryReposito
dictionary.setCode(scriptEntity.getCode());
dictionary.setDictType("2");
dictionary.setComponentType(scriptEntity.getScriptPath().contains("tree") ? "2" : "1");
dictionary.setComponentType(scriptEntity.getCode().contains("tree") ? "2" : "1");
dictionary.setScript(scriptEntity);
dictionary.setStatus(1);

View File

@@ -1,7 +1,7 @@
package cn.lihongjie.coal.employee.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import cn.lihongjie.coal.department.entity.DepartmentEntity;
import cn.lihongjie.coal.department.dto.DepartmentDto;
import cn.lihongjie.coal.employee.entity.EmpCarVO;
import cn.lihongjie.coal.employee.entity.EmpCertVO;
import cn.lihongjie.coal.employee.entity.EmpFamilyMemberVO;
@@ -77,7 +77,7 @@ public class EmployeeDto extends OrgCommonDto {
@Comment("部门")
@ManyToOne
private DepartmentEntity department;
private DepartmentDto department;
@Comment("岗位")
@ManyToOne

View File

@@ -0,0 +1,93 @@
create or replace function self_and_children_ids(tb text, id text[], includeSelf bool = true) returns text[] AS
$$
declare
ans text[];
sql text;
text1 text;
begin
-- logic
if includeSelf then
text1 = 'id' ;
else
text1 = 'parent_id' ;
end if;
sql = 'with recursive tmp as (select id
from ' ||
tb ||
'
where ' ||
text1 ||
' = any($1)
union all
select ' ||
tb ||
'.id
from ' ||
tb ||
'
inner join tmp on ' ||
tb ||
'.parent_id = tmp.id)
select array_agg(id)
from tmp';
execute sql into ans using id;
return ans;
end
$$ language plpgsql
;
create or replace function self_and_parent_ids(tb text, id text[], includeSelf bool = true) returns text[] AS
$$
declare
ans text[];
sql text;
begin
-- logic
sql = 'with recursive tmp as (select id,parent_id
from ' ||
tb ||
'
where ' ||
'id = any($1)
union all
select ' ||
tb ||
'.id, ' || tb || '.parent_id
from ' ||
tb ||
'
inner join tmp on ' ||
tb ||
'.id = tmp.parent_id)
select array_agg(id)
from tmp ';
if not includeSelf
then
sql = sql || ' where id != any($1)';
end if;
execute sql into ans using id;
return ans;
end
$$ language plpgsql
;

View File

@@ -1,6 +1,6 @@
package scripts.dict
import cn.lihongjie.coal.base.dto.CommonQuery
import cn.lihongjie.coal.department.controller.DepartmentController
import org.springframework.context.ApplicationContext
@@ -10,6 +10,6 @@ def controller = ioc.getBean(DepartmentController.class)
return controller.roots()
return controller.roots(new CommonQuery())