添加工资标准接口

This commit is contained in:
2024-03-19 10:46:23 +08:00
parent dd9ac66cce
commit 1e218baa84
12 changed files with 867 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
package cn.lihongjie.coal.empSalaryStandard.controller;
import cn.lihongjie.coal.annotation.OrgScope;
import cn.lihongjie.coal.annotation.SysLog;
import cn.lihongjie.coal.base.dto.CommonQuery;
import cn.lihongjie.coal.base.dto.IdRequest;
import cn.lihongjie.coal.empSalaryStandard.dto.CreateEmpSalaryStandardDto;
import cn.lihongjie.coal.empSalaryStandard.dto.EmpSalaryStandardDto;
import cn.lihongjie.coal.empSalaryStandard.dto.UpdateEmpSalaryStandardDto;
import cn.lihongjie.coal.empSalaryStandard.service.EmpSalaryStandardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/empSalaryStandard")
@SysLog(module = "工资标准")
@Slf4j
@OrgScope
public class EmpSalaryStandardController {
@Autowired private EmpSalaryStandardService service;
@PostMapping("/create")
public EmpSalaryStandardDto create(@RequestBody CreateEmpSalaryStandardDto request) {
return this.service.create(request);
}
@PostMapping("/update")
public EmpSalaryStandardDto update(@RequestBody UpdateEmpSalaryStandardDto request) {
return this.service.update(request);
}
@PostMapping("/delete")
public Object delete(@RequestBody IdRequest request) {
this.service.delete(request);
return true;
}
@PostMapping("/getById")
public EmpSalaryStandardDto getById(@RequestBody IdRequest request) {
return this.service.getById(request.getId());
}
@PostMapping("/list")
public Page<EmpSalaryStandardDto> list(@RequestBody CommonQuery request) {
return this.service.list(request);
}
}

View File

@@ -0,0 +1,18 @@
package cn.lihongjie.coal.empSalaryStandard.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
public class CreateEmpSalaryStandardDto extends OrgCommonDto {
@Comment("标准配置项 json")
private String config;
@Comment("标准内容 json")
private String content;
}

View File

@@ -0,0 +1,38 @@
package cn.lihongjie.coal.empSalaryStandard.dto;
import lombok.Data;
import org.hibernate.annotations.Comment;
import java.util.*;
@Data
public class EmpSalaryStandardConfig {
@Comment("编码 item1 item2 item3 ... item25 代表第几个配置项")
private String code;
@Comment("中文名称")
private String name;
@Comment("java字段")
private String field;
@Comment("类型 N 数字 S 字符串 D 日期 B 布尔 T 时间 E 实体对象")
private String type;
@Comment("关联数据字典")
private String dictCode;
@Comment("操作符 大于 小于 等于 大于等于 小于等于 不等于 包含 不包含 以...开始 以...结束")
private String operator;
//
// @Comment("默认值")
// private String defaultValue = "0";
}

View File

@@ -0,0 +1,18 @@
package cn.lihongjie.coal.empSalaryStandard.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
public class EmpSalaryStandardDto extends OrgCommonDto {
@Comment("标准配置项 json")
private String config;
@Comment("标准内容 json")
private String content;
}

View File

@@ -0,0 +1,103 @@
package cn.lihongjie.coal.empSalaryStandard.dto;
import lombok.Data;
/**
* 代表每一行的标准配置项
*/
@Data
public class EmpSalaryStandardItem {
private String item1;
private String item2;
private String item3;
private String item4;
private String item5;
private String item6;
private String item7;
private String item8;
private String item9;
private String item10;
private String item11;
private String item12;
private String item13;
private String item14;
private String item15;
private String item16;
private String item17;
private String item18;
private String item19;
private String item20;
private String item21;
private String item22;
private String item23;
private String item24;
private String item25;
private String value;
public String getByCode(String field) {
switch (field) {
case "item1":
return item1;
case "item2":
return item2;
case "item3":
return item3;
case "item4":
return item4;
case "item5":
return item5;
case "item6":
return item6;
case "item7":
return item7;
case "item8":
return item8;
case "item9":
return item9;
case "item10":
return item10;
case "item11":
return item11;
case "item12":
return item12;
case "item13":
return item13;
case "item14":
return item14;
case "item15":
return item15;
case "item16":
return item16;
case "item17":
return item17;
case "item18":
return item18;
case "item19":
return item19;
case "item20":
return item20;
case "item21":
return item21;
case "item22":
return item22;
case "item23":
return item23;
case "item24":
return item24;
case "item25":
return item25;
default:
return null;
}
}
}

View File

@@ -0,0 +1,20 @@
package cn.lihongjie.coal.empSalaryStandard.dto;
import lombok.Data;
import java.util.*;
@Data
public class EmpSalaryStandardResult {
private String name;
private String code;
private String empId;
private Double value;
private String explain;
}

View File

@@ -0,0 +1,18 @@
package cn.lihongjie.coal.empSalaryStandard.dto;
import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
public class UpdateEmpSalaryStandardDto extends OrgCommonDto {
@Comment("标准配置项 json")
private String config;
@Comment("标准内容 json")
private String content;
}

View File

@@ -0,0 +1,29 @@
package cn.lihongjie.coal.empSalaryStandard.entity;
import cn.lihongjie.coal.base.entity.OrgCommonEntity;
import jakarta.persistence.Entity;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
@Entity
public class EmpSalaryStandardEntity extends OrgCommonEntity {
@Comment("标准配置项 json")
private String config;
@Comment("标准内容 json")
private String content;
@Comment("默认值")
private String defaultValue = "0";
}

View File

@@ -0,0 +1,23 @@
package cn.lihongjie.coal.empSalaryStandard.mapper;
import cn.lihongjie.coal.base.mapper.BaseMapper;
import cn.lihongjie.coal.base.mapper.CommonEntityMapper;
import cn.lihongjie.coal.base.mapper.CommonMapper;
import cn.lihongjie.coal.empSalaryStandard.dto.CreateEmpSalaryStandardDto;
import cn.lihongjie.coal.empSalaryStandard.dto.EmpSalaryStandardDto;
import cn.lihongjie.coal.empSalaryStandard.dto.UpdateEmpSalaryStandardDto;
import cn.lihongjie.coal.empSalaryStandard.entity.EmpSalaryStandardEntity;
import org.mapstruct.Mapper;
import org.mapstruct.control.DeepClone;
@Mapper(
componentModel = org.mapstruct.MappingConstants.ComponentModel.SPRING,
uses = {CommonMapper.class, CommonEntityMapper.class},
mappingControl = DeepClone.class)
public interface EmpSalaryStandardMapper
extends BaseMapper<
EmpSalaryStandardEntity,
EmpSalaryStandardDto,
CreateEmpSalaryStandardDto,
UpdateEmpSalaryStandardDto> {}

View File

@@ -0,0 +1,9 @@
package cn.lihongjie.coal.empSalaryStandard.repository;
import cn.lihongjie.coal.base.dao.BaseRepository;
import cn.lihongjie.coal.empSalaryStandard.entity.EmpSalaryStandardEntity;
import org.springframework.stereotype.Repository;
@Repository
public interface EmpSalaryStandardRepository extends BaseRepository<EmpSalaryStandardEntity> {}

View File

@@ -0,0 +1,520 @@
package cn.lihongjie.coal.empSalaryStandard.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.dbFunctions.DbFunctionService;
import cn.lihongjie.coal.empSalaryStandard.dto.*;
import cn.lihongjie.coal.empSalaryStandard.entity.EmpSalaryStandardEntity;
import cn.lihongjie.coal.empSalaryStandard.mapper.EmpSalaryStandardMapper;
import cn.lihongjie.coal.empSalaryStandard.repository.EmpSalaryStandardRepository;
import cn.lihongjie.coal.employee.entity.EmployeeEntity;
import cn.lihongjie.coal.exception.BizException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import groovy.lang.GroovyClassLoader;
import groovy.lang.Script;
import jakarta.annotation.PostConstruct;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
@Transactional
public class EmpSalaryStandardService
extends BaseService<EmpSalaryStandardEntity, EmpSalaryStandardRepository> {
@Autowired ObjectMapper objectMapper;
@Autowired private EmpSalaryStandardRepository repository;
@Autowired private EmpSalaryStandardMapper mapper;
@Autowired private ConversionService conversionService;
@Autowired private DbFunctionService dbFunctionService;
private GroovyClassLoader groovyClassLoader;
public EmpSalaryStandardDto create(CreateEmpSalaryStandardDto request) {
EmpSalaryStandardEntity entity = mapper.toEntity(request);
this.repository.save(entity);
return getById(entity.getId());
}
public EmpSalaryStandardDto update(UpdateEmpSalaryStandardDto request) {
EmpSalaryStandardEntity entity = this.repository.get(request.getId());
this.mapper.updateEntity(entity, request);
this.repository.save(entity);
return getById(entity.getId());
}
public void delete(IdRequest request) {
this.repository.deleteAllById(request.getIds());
}
public EmpSalaryStandardDto getById(String id) {
EmpSalaryStandardEntity entity = repository.get(id);
return mapper.toDto(entity);
}
public Page<EmpSalaryStandardDto> list(CommonQuery query) {
Page<EmpSalaryStandardEntity> page =
repository.findAll(
query.specification(conversionService),
PageRequest.of(
query.getPageNo(),
query.getPageSize(),
Sort.by(query.getOrders())));
return page.map(this.mapper::toDto);
}
public List<EmpSalaryStandardResult> calculateSalaryStandard(EmployeeEntity employee) {
List<EmpSalaryStandardEntity> standards =
this.repository.findByOrganizationId(employee.getOrganizationId());
return standards.stream()
.map(esse -> doCalculate(employee, esse))
.collect(Collectors.toList());
}
@PostConstruct
public void init() {
CompilerConfiguration config = new CompilerConfiguration();
groovyClassLoader = new GroovyClassLoader(this.getClass().getClassLoader(), config);
}
@SneakyThrows
private EmpSalaryStandardResult doCalculate(
EmployeeEntity employee, EmpSalaryStandardEntity standard) {
String script = genScript(standard);
Class scriptClass = groovyClassLoader.parseClass(script);
Script scriptInstance = (Script) scriptClass.newInstance();
setScriptProperties(employee, standard, scriptInstance);
Object value = null;
try {
value = scriptInstance.run();
} catch (Exception e) {
log.error("script error", e);
throw new BizException("脚本执行错误");
}
EmpSalaryStandardResult result = new EmpSalaryStandardResult();
result.setCode(standard.getCode());
result.setName(standard.getName());
result.setEmpId(employee.getId());
result.setValue(value == null ? null : conversionService.convert(value, Double.class));
result.setExplain("");
log.info("script {}\n result {}", script, result);
return result;
}
@SneakyThrows
private void setScriptProperties(
EmployeeEntity employee, EmpSalaryStandardEntity standard, Script scriptInstance) {
List<EmpSalaryStandardConfig> configs =
objectMapper
.readerForListOf(EmpSalaryStandardConfig.class)
.readValue(standard.getConfig());
List<EmpSalaryStandardItem> items =
objectMapper
.readerForListOf(EmpSalaryStandardItem.class)
.readValue(standard.getContent());
for (int i = 0; i < items.size(); i++) {
EmpSalaryStandardItem item = items.get(i);
scriptInstance.setProperty("row" + i + "Value", item.getValue());
}
for (int i = 0; i < items.size(); i++) {
EmpSalaryStandardItem item = items.get(i);
for (int j = 0; j < configs.size(); j++) {
EmpSalaryStandardConfig config = configs.get(j);
String value = item.getByCode(config.getCode());
switch (config.getType()) {
case "S":
scriptInstance.setProperty("row" + i + config.getCode(), value);
break;
case "N":
scriptInstance.setProperty(
"row" + i + config.getCode(),
conversionService.convert(value, Double.class));
break;
case "D":
scriptInstance.setProperty(
"row" + i + config.getCode(),
conversionService.convert(value, LocalDate.class));
break;
case "T":
scriptInstance.setProperty(
"row" + i + config.getCode(),
conversionService.convert(value, LocalTime.class));
break;
case "B":
scriptInstance.setProperty(
"row" + i + config.getCode(),
conversionService.convert(value, Boolean.class));
break;
case "E":
scriptInstance.setProperty(
"row" + i + config.getCode(),
conversionService.convert(value, String.class));
break;
default:
throw new RuntimeException("不支持的类型 " + config.getType());
}
}
}
scriptInstance.setProperty("defaultValue", standard.getDefaultValue());
}
private String genScript(EmpSalaryStandardEntity standard) throws JsonProcessingException {
List<EmpSalaryStandardConfig> configs =
objectMapper
.readerForListOf(EmpSalaryStandardConfig.class)
.readValue(standard.getConfig());
List<EmpSalaryStandardItem> items =
objectMapper
.readerForListOf(EmpSalaryStandardItem.class)
.readValue(standard.getContent());
Map<String, EmpSalaryStandardConfig> configMap =
configs.stream().collect(Collectors.toMap(e -> e.getCode(), e -> e));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < items.size(); i++) {
EmpSalaryStandardItem item = items.get(i);
sb.append(" if (");
for (int j = 0; j < configs.size(); j++) {
EmpSalaryStandardConfig config = configs.get(j);
if (j != 0) {
sb.append(" && ");
}
sb.append("( ");
if (StringUtils.equalsIgnoreCase(config.getType(), "S")) {
// 大于 小于 等于 大于等于 小于等于 不等于 包含 不包含 以...开始 以...结束 为空 不为空 为真 为假
if (StringUtils.equalsIgnoreCase(config.getOperator(), "大于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" > ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "小于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" < ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" == ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "大于等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" >= ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "小于等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" <= ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "不等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" != ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "包含")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(".contains(")
.append("row")
.append(i)
.append(config.getCode())
.append(")");
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "不包含")) {
sb.append(config.getField())
.append(" != null && !")
.append(config.getField())
.append(".contains(")
.append("row")
.append(i)
.append(config.getCode())
.append(")");
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "以...开始")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(".startsWith(")
.append("row")
.append(i)
.append(config.getCode())
.append(")");
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "以...结束")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(".endsWith(")
.append("row")
.append(i)
.append(config.getCode())
.append(")");
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "为空")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(".endsWith(")
.append("row")
.append(i)
.append(config.getCode())
.append(")");
} else {
throw new RuntimeException("不支持的操作符 " + config.getOperator());
}
} else if (StringUtils.equalsIgnoreCase(config.getType(), "N")) {
if (StringUtils.equalsIgnoreCase(config.getOperator(), "大于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" > ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "小于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" < ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" == ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "大于等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" >= ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "小于等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" <= ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "不等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" != ")
.append("row")
.append(i)
.append(config.getCode());
} else {
throw new RuntimeException("不支持的操作符 " + config.getOperator());
}
} else if (StringUtils.equalsIgnoreCase(config.getType(), "D")
|| StringUtils.equalsIgnoreCase(config.getType(), "T")) {
if (StringUtils.equalsIgnoreCase(config.getOperator(), "大于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" > ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "小于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" < ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" == ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "大于等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" >= ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "小于等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" <= ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "不等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" != ")
.append("row")
.append(i)
.append(config.getCode());
} else {
throw new RuntimeException("不支持的操作符 " + config.getOperator());
}
} else if (StringUtils.equalsIgnoreCase(config.getType(), "B")) {
if (StringUtils.equalsIgnoreCase(config.getOperator(), "等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" == ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "不等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append(" != ")
.append("row")
.append(i)
.append(config.getCode());
} else {
throw new RuntimeException("不支持的操作符 " + config.getOperator());
}
}else if (StringUtils.equalsIgnoreCase(config.getType(), "E")) {
if (StringUtils.equalsIgnoreCase(config.getOperator(), "等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append("?.id")
.append(" == ")
.append("row")
.append(i)
.append(config.getCode());
} else if (StringUtils.equalsIgnoreCase(config.getOperator(), "不等于")) {
sb.append(config.getField())
.append(" != null && ")
.append(config.getField())
.append("?.id")
.append(" != ")
.append("row")
.append(i)
.append(config.getCode());
} else {
throw new RuntimeException("不支持的操作符 " + config.getOperator());
}
}
sb.append(" ) ");
}
sb.append(" )\n {\n value = row").append(i).append("Value").append("; \n} ");
}
sb.append(" else { value = ").append("default").append("Value").append("; } \n");
sb.append(" return value; ");
String script = sb.toString();
return script;
}
}

View File

@@ -0,0 +1,17 @@
package scripts.dict
import cn.lihongjie.coal.base.dto.CommonQuery
import cn.lihongjie.coal.empSalaryStandard.controller.EmpSalaryStandardController
import org.springframework.context.ApplicationContext
ApplicationContext ioc = ioc
def controller = ioc.getBean(EmpSalaryStandardController.class)
return controller.list(new CommonQuery())