添加工资项目

This commit is contained in:
2023-11-15 20:31:14 +08:00
parent ddfdd05923
commit a081bdc313
7 changed files with 197 additions and 3 deletions

View File

@@ -17,11 +17,36 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@UtilityClass
@Slf4j
public class GroovyScriptUtils {
public String replaceVariable(
String patternstr, String script, Function<String, String> mapper) {
Pattern pattern = Pattern.compile(patternstr);
// 创建 Matcher 对象
Matcher matcher = pattern.matcher(script);
// 使用 Map 进行映射和替换
StringBuffer resultString = new StringBuffer();
while (matcher.find()) {
String replacement = mapper.apply(matcher.group(matcher.groupCount()));
matcher.appendReplacement(
resultString,
replacement != null ? Matcher.quoteReplacement(replacement) : matcher.group());
}
matcher.appendTail(resultString);
return resultString.toString();
}
public static void validate(String formula) {
if (StringUtils.isEmpty(formula)) {
return;

View File

@@ -10,6 +10,7 @@ import cn.lihongjie.coal.organization.dto.UpdateOrganizationDto;
import cn.lihongjie.coal.organization.entity.OrganizationEntity;
import cn.lihongjie.coal.organization.mapper.OrganizationMapper;
import cn.lihongjie.coal.organization.repository.OrganizationRepository;
import cn.lihongjie.coal.salaryItem.service.SalaryItemService;
import cn.lihongjie.coal.user.dto.CreateOrgAdminDto;
import cn.lihongjie.coal.user.service.UserService;
@@ -37,7 +38,7 @@ public class OrganizationService extends BaseService<OrganizationEntity, Organiz
@Autowired CoalParameterDefService coalParameterDefService;
@Autowired SalaryItemService salaryItemService;
@PostConstruct
public void init() {}
@@ -54,7 +55,7 @@ public class OrganizationService extends BaseService<OrganizationEntity, Organiz
dto.setPassword(request.getOrgAdminPassword());
userService.createOrgAdmin(dto);
coalParameterDefService.initDefault(entity.getId());
salaryItemService.initOrgDefault(entity.getId());
return getById(entity.getId());
}

View File

@@ -14,6 +14,8 @@ public class SalaryItemDto extends OrgCommonDto {
@Comment("上级名称")
private String parentName;
private String fullName;
@Comment("工资项目类型")
private String itemType;

View File

@@ -18,6 +18,9 @@ public class SalaryItemEntity extends OrgCommonEntity {
@Comment("上级名称")
private String parentName;
@Formula("(CONCAT(parentName,'-' ,name))")
private String fullName;
@Comment("工资项目类型")
private String itemType;
@@ -52,4 +55,7 @@ public class SalaryItemEntity extends OrgCommonEntity {
@Comment("依赖项目")
private List<String> dependOn;
@Comment("优先级")
private Integer priority;
}

View File

@@ -5,5 +5,9 @@ import cn.lihongjie.coal.salaryItem.entity.SalaryItemEntity;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface SalaryItemRepository extends BaseRepository<SalaryItemEntity> {}
public interface SalaryItemRepository extends BaseRepository<SalaryItemEntity> {
List<SalaryItemEntity> findByOrganizationIdAndStatus(String organizationId, Integer status);
}

View File

@@ -2,7 +2,10 @@ package cn.lihongjie.coal.salaryItem.service;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.base.entity.CommonEntity;
import cn.lihongjie.coal.base.service.BaseService;
import cn.lihongjie.coal.common.GroovyScriptUtils;
import cn.lihongjie.coal.exception.BizException;
import cn.lihongjie.coal.salaryItem.dto.CreateSalaryItemDto;
import cn.lihongjie.coal.salaryItem.dto.SalaryItemDto;
import cn.lihongjie.coal.salaryItem.dto.UpdateSalaryItemDto;
@@ -12,6 +15,10 @@ import cn.lihongjie.coal.salaryItem.repository.SalaryItemRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.traverse.TopologicalOrderIterator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
@@ -19,6 +26,13 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SalaryItemService extends BaseService<SalaryItemEntity, SalaryItemRepository> {
@@ -31,16 +45,122 @@ public class SalaryItemService extends BaseService<SalaryItemEntity, SalaryItemR
public SalaryItemDto create(CreateSalaryItemDto request) {
SalaryItemEntity entity = mapper.toEntity(request);
updateField(entity);
// 校验公式
this.repository.save(entity);
syncFormula(entity);
return getById(entity.getId());
}
private void updateField(SalaryItemEntity entity) {
List<SalaryItemEntity> allItems =
repository.findByOrganizationIdAndStatus(entity.getOrganizationId(), 1);
Map<String, SalaryItemEntity> nameMap =
allItems.stream()
.collect(
Collectors.toMap(
e -> String.format("【%s】", e.getFullName()), e -> e));
Set<String> dependsOn = new HashSet<>();
Function<String, String> mapper =
(String s) -> {
if (nameMap.containsKey(s)) {
String code = nameMap.get(s).getCode();
dependsOn.add(code);
return code;
}
throw new BizException("公式中的依赖项 {} 不存在", s);
};
// 生成公式
String formula =
GroovyScriptUtils.replaceVariable("【(.*?)】", entity.getFormulaShow(), mapper);
entity.setDependOn(dependsOn.stream().toList());
entity.setFormula(formula);
try {
GroovyScriptUtils.variables(formula);
} catch (Exception e) {
throw new BizException("无效的公式");
}
}
private void syncFormula(SalaryItemEntity entity) {
DefaultDirectedGraph<Object, DefaultEdge> graph =
new DefaultDirectedGraph<>(DefaultEdge.class);
List<SalaryItemEntity> all =
repository.findByOrganizationIdAndStatus(entity.getOrganizationId(), 1);
Set<String> enabledCode =
all.stream().map(sie -> sie.getCode()).collect(Collectors.toSet());
for (SalaryItemEntity def : all) {
if (StringUtils.equalsIgnoreCase(def.getInputType(), "1")) {
Iterable<String> dependents = def.getDependOn();
for (String d : dependents) {
if (!enabledCode.contains(d)) {
throw new BizException("公式中的依赖项 {} 不存在", d);
}
graph.addVertex(def.getCode());
graph.addVertex(d);
graph.addEdge(d, def.getCode());
}
}
}
Map<String, SalaryItemEntity> codeMap =
all.stream().collect(Collectors.toMap(CommonEntity::getCode, e -> e));
Function<String, String> mapper =
(String s) -> {
if (codeMap.containsKey(s)) {
return "" + codeMap.get(s).getFullName() + "";
}
throw new BizException("公式中的依赖项 {} 不存在", s);
};
// 生成公式
TopologicalOrderIterator<Object, DefaultEdge> iterator =
new TopologicalOrderIterator<>(graph);
int order = 0;
while (iterator.hasNext()) {
Object next = iterator.next();
for (var item : all) {
if (StringUtils.equalsIgnoreCase(item.getCode(), next + "")) {
item.setPriority(order++);
item.setFormulaShow(
GroovyScriptUtils.replaceVariable(
"item\\d+", entity.getFormula(), mapper));
break;
}
}
}
this.repository.saveAll(all);
}
public SalaryItemDto update(UpdateSalaryItemDto request) {
SalaryItemEntity entity = this.repository.get(request.getId());
this.mapper.updateEntity(entity, request);
updateField(entity);
this.repository.save(entity);
syncFormula(entity);
return getById(entity.getId());
}
@@ -65,4 +185,20 @@ public class SalaryItemService extends BaseService<SalaryItemEntity, SalaryItemR
return page.map(this.mapper::toDto);
}
public void initOrgDefault(String organizationId) {
for (int i = 0; i < 50; i++) {
SalaryItemEntity item = new SalaryItemEntity();
item.setCode("item" + i);
item.setInputType("1");
item.setItemType("1");
item.setStatus(0);
item.setOrganizationId(organizationId);
this.repository.save(item);
}
}
}

View File

@@ -0,0 +1,20 @@
package cn.lihongjie.coal.common;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import java.util.*;
class GroovyScriptUtilsTest {
@Test
void test() {
assertEquals("1", GroovyScriptUtils.replaceVariable("\\【(.+?)\\", "【a】", (s) -> "1"));
assertEquals(
"1 + 1", GroovyScriptUtils.replaceVariable("\\【(.+?)\\", "【a】 + 【b】", (s) -> "1"));
assertEquals(
"1 + 1", GroovyScriptUtils.replaceVariable("\\【(.+?)\\", "1 + 1", (s) -> "1"));
}
}