欧姆龙,月度薪资环比统计报表

This commit is contained in:
Harryxzy 2024-12-17 14:17:19 +08:00
parent ec88fc5b10
commit 77c311df32
6 changed files with 274 additions and 9 deletions

View File

@ -73,6 +73,9 @@ public class SalaryAcctResultQueryParam extends BaseQueryParam {
//其他条件
private List<OtherCondition> otherConditions;
// 年度
private String year;
@Data
@NoArgsConstructor

View File

@ -7,6 +7,7 @@ import com.engine.salary.entity.salaryacct.dto.SalaryAcctResultListColumnDTO;
import com.engine.salary.entity.salaryacct.param.*;
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
import com.engine.salary.util.page.PageInfo;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.util.Collection;
import java.util.List;
@ -217,4 +218,13 @@ public interface SalaryAcctResultService {
* @param param
*/
void batchUpdate(SalaryAcctResultBatchUpdateParam param);
/**
* 月度薪资环比统计报表本月上月维度比较
* @param year
* @return
*/
Map<String, Object> ydxzhbReportList(String year);
XSSFWorkbook exportYdxzhbReport(String year);
}

View File

@ -1,5 +1,6 @@
package com.engine.salary.service.impl;
import com.cloudstore.eccom.pc.table.WeaTableColumn;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.hrmelog.entity.dto.LoggerContext;
@ -51,6 +52,7 @@ import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.excel.ExcelUtilPlus;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.util.valid.ValidUtil;
@ -64,12 +66,15 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.StopWatch;
import weaver.general.BaseBean;
import weaver.hrm.User;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.CountDownLatch;
@ -1245,4 +1250,108 @@ public class SalaryAcctResultServiceImpl extends Service implements SalaryAcctRe
}
}
@Override
public Map<String, Object> ydxzhbReportList(String year) {
if (!NumberUtils.isCreatable(year)) {
throw new SalaryRunTimeException("请输入年份");
}
Map<String, Object> resultMap = new HashMap<>();
// 获取能够管理的义务人
Collection<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listAllTaxAgentsAsAdmin(Long.valueOf(user.getUID()));
List<Long> canManageTaxAgentIds = taxAgentPOS.stream().map(TaxAgentPO::getId).collect(Collectors.toList());
List<SalarySobPO> salarySobPOS = getSalarySobService(user).listByTaxAgentIds(canManageTaxAgentIds);
List<Long> salarySobIds = salarySobPOS.stream().map(SalarySobPO::getId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(salarySobIds)) {
return resultMap;
}
// 获取已归档的核算记录
LocalDateRange dateRange = LocalDateRange.builder().fromDate(SalaryDateUtil.stringToDate(year + "-01-01")).endDate(SalaryDateUtil.stringToDate(year + "-12-01")).build();
List<SalaryAcctRecordPO> salaryAcctRecordPOS = getSalaryAcctRecordService(user).listBySalarySobIdsAndSalaryMonth(salarySobIds, dateRange);
salaryAcctRecordPOS = salaryAcctRecordPOS.stream().filter(record -> record.getStatus() > SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue()).collect(Collectors.toList());
List<Long> salaryAcctRecordIds = salaryAcctRecordPOS.stream().map(SalaryAcctRecordPO::getId).collect(Collectors.toList());
// 获取需要统计哪些薪资项目
List<SalaryItemPO> salaryItemList = getSalaryItemService(user).listAll();
Map<String, SalaryItemPO> salaryItemMap = SalaryEntityUtil.convert2Map(salaryItemList, SalaryItemPO::getName);
BaseBean baseBean = new BaseBean();
String itemStr = baseBean.getPropValue("omlSalaryReport", "ydxzhbtj_item");
List<SalaryItemPO> itemList = new ArrayList<>();
try {
itemList = Arrays.stream(new String(itemStr.getBytes("ISO-8859-1"), "utf-8").split(","))
.map(itemName -> salaryItemMap.get(itemName))
.filter(item -> item != null)
.collect(Collectors.toList());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// 查询薪资核算结果
List<Long> itemIdList = itemList.stream().map(SalaryItemPO::getId).collect(Collectors.toList());
List<SalaryAcctResultPO> resultPOList = getSalaryAcctResultService(user).listBySalaryAcctRecordIdsAndSalaryItemIds(salaryAcctRecordIds, itemIdList);
Map<Long, List<SalaryAcctResultPO>> resultGroupByAcctItemId = SalaryEntityUtil.group2Map(resultPOList, SalaryAcctResultPO::getSalaryItemId);
// 核算记录id根据薪资所属月份分组
Map<String, Set<Long>> salaryAcctRecordMapByMonth = SalaryEntityUtil.group2Map(salaryAcctRecordPOS, record -> SalaryDateUtil.getFormatYearMonth(record.getSalaryMonth()), SalaryAcctRecordPO::getId);
List<String> sortedDateList = salaryAcctRecordMapByMonth.keySet().stream().sorted((k1, k2) -> k1.compareTo(k2)).collect(Collectors.toList());
// 构建表头
List<WeaTableColumn> columns = new ArrayList<>();
columns.add(new WeaTableColumn("150px", "项目(单位-万元)", "salaryItemName"));
for (String dateStr : sortedDateList) {
columns.add(new WeaTableColumn("150px", dateStr.substring(5) + "", dateStr));
}
columns.add(new WeaTableColumn("150px", "上月对比", "compareWithLastMonth"));
resultMap.put("columns", columns);
List<Map<String, Object>> dataList = new ArrayList<>();
Map<String, Object> rjfhjMap = new HashMap<>();
rjfhjMap.put("salaryItemName", "人件费合计");
for (String salaryMonthStr : sortedDateList) {
rjfhjMap.put(salaryMonthStr, "");
}
dataList.add(rjfhjMap);
for (SalaryItemPO item : itemList) {
List<SalaryAcctResultPO> resultList = resultGroupByAcctItemId.getOrDefault(item.getId(), Collections.emptyList());
Map<String, Object> monthResult = new HashMap<>();
for (String salaryMonthStr : sortedDateList) {
// 获取该月份下有哪些核算记录id
Set<Long> recordIds = salaryAcctRecordMapByMonth.getOrDefault(salaryMonthStr, Collections.emptySet());
BigDecimal resultValue = resultList.stream().filter(result -> recordIds.contains(result.getSalaryAcctRecordId()))
.map(resultPO -> SalaryEntityUtil.empty2Zero(resultPO.getResultValue()))
.reduce(new BigDecimal("0"), BigDecimal::add);
// 存储该薪资项目每个月的合计值
monthResult.put(salaryMonthStr, resultValue);
}
// 计算上月对比
if (CollectionUtils.isNotEmpty(sortedDateList) && sortedDateList.size() > 2) {
BigDecimal thisMonthValue = (BigDecimal) monthResult.get(sortedDateList.get(sortedDateList.size() - 1));
BigDecimal lastMonthValue = (BigDecimal) monthResult.get(sortedDateList.get(sortedDateList.size() - 2));
BigDecimal compareValue = (thisMonthValue.subtract(lastMonthValue)).divide(lastMonthValue, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
monthResult.put("compareWithLastMonth", compareValue.toString() + "%");
}
monthResult.put("salaryItemName", item.getName());
dataList.add(monthResult);
}
resultMap.put("data", dataList);
return resultMap;
}
@Override
public XSSFWorkbook exportYdxzhbReport(String year) {
Map<String, Object> resultMap = ydxzhbReportList(year);
List<Map<String, Object>> dataList = (List<Map<String, Object>>) resultMap.get("data");
List<WeaTableColumn> columns = (List<WeaTableColumn>) resultMap.get("columns");
List<List<Object>> list = new ArrayList<>();
// 表头
list.add(columns.stream().map(WeaTableColumn::getText).collect(Collectors.toList()));
for (Map<String, Object> dataMap : dataList) {
List<Object> row = new ArrayList<>();
for (WeaTableColumn column : columns) {
row.add(dataMap.getOrDefault(column.getColumn(), ""));
}
list.add(row);
}
return ExcelUtilPlus.genWorkbookV24oml(list, year + "年月度薪资环比统计报表");
}
}

View File

@ -304,6 +304,92 @@ public class ExcelUtilPlus {
}
return workbook;
}
public static XSSFWorkbook genWorkbookV24oml(List<List<Object>> rowList, String sheetName) {
XSSFWorkbook workbook = new XSSFWorkbook();
// 设置title样式
XSSFCellStyle titleCellStyle = workbook.createCellStyle();
XSSFFont titleFont = workbook.createFont();
titleFont.setBold(true);
titleFont.setFontName("仿宋");
titleFont.setFontHeightInPoints((short) 15);
titleCellStyle.setFont(titleFont);
titleCellStyle.setAlignment(HorizontalAlignment.CENTER);
titleCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());//背景色
titleCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
titleCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
titleCellStyle.setBorderLeft(BorderStyle.THIN);
titleCellStyle.setBorderRight(BorderStyle.THIN);
titleCellStyle.setBorderTop(BorderStyle.THIN);
titleCellStyle.setBorderBottom(BorderStyle.THIN);
// 设置主体样式
XSSFCellStyle cellStyle = workbook.createCellStyle();
XSSFFont font = workbook.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short) 10);// 设置字体大小
cellStyle.setFont(font);// 选择需要用到的字体格式
cellStyle.setWrapText(true);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setBorderRight(BorderStyle.THIN);
cellStyle.setBorderTop(BorderStyle.THIN);
cellStyle.setBorderBottom(BorderStyle.THIN);
XSSFSheet sheet = workbook.createSheet(sheetName);
//自适应宽度
sheet.autoSizeColumn(0, true);
//默认列宽
sheet.setDefaultColumnWidth(20);
//默认行高
sheet.setDefaultRowHeightInPoints(18);
//遍历设置列宽
List<Object> header = rowList.get(0);
for (int i = 0; i < header.size(); i++) {
sheet.setColumnWidth(i, Math.min(255, Math.max(12, header.get(i).toString().length() * 4)) * 256);
}
for (int rowIndex = 0; rowIndex < rowList.size(); rowIndex++) {
List<Object> infoList = rowList.get(rowIndex);
XSSFRow row = sheet.createRow(rowIndex);
float height = 18;
float finalHeight = 18;
for (int cellIndex = 0; cellIndex < infoList.size(); cellIndex++) {
XSSFCell cell = row.createCell(cellIndex);
if (rowIndex == 0) {
cell.setCellStyle(titleCellStyle);
} else {
cell.setCellStyle(cellStyle);
}
Object o = infoList.get(cellIndex);
if (o instanceof String) {
cell.setCellType(CellType.STRING);
cell.setCellValue(String.valueOf(o));
} else if (o instanceof BigDecimal) {
cell.setCellType(CellType.NUMERIC);
cell.setCellValue(o == null ? 0 : ((BigDecimal) o).doubleValue());
} else if (o instanceof Boolean) {
cell.setCellType(CellType.BOOLEAN);
cell.setCellValue(String.valueOf(o));
} else if (o instanceof Date) {
cell.setCellType(CellType.STRING);
cell.setCellValue(SalaryDateUtil.getFormatLocalDate((Date) o));
} else {
cell.setCellType(CellType.STRING);
cell.setCellValue(o == null ? "" : o.toString());
}
//判断是否要调整高度
int width = sheet.getColumnWidth(cellIndex) / 256;
finalHeight = getFinalHeight(o, width, finalHeight, height);
}
if (rowIndex == 1) {
sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, header.size()-1));
}
row.setHeightInPoints(finalHeight);
}
return workbook;
}
public static XSSFWorkbook genWorkbookV2(List<List<Object>> rowList, String sheetName, List<ExcelComment> comments) {

View File

@ -36,6 +36,8 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
/**
* 薪资核算
* <p>Copyright: Copyright (c) 2022</p>
@ -270,7 +272,7 @@ public class SalaryAcctController {
*/
@GET
@Path("/acctemployee/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportSalaryAcctEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
SalaryAcctEmployeeQueryParam param = buildSalaryAcctEmployeeQueryParam(request);
@ -340,7 +342,7 @@ public class SalaryAcctController {
*/
@GET
@Path("/reducedemployee/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportReducedEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
SalaryAcctEmployeeQueryParam param = buildSalaryAcctEmployeeQueryParam(request);
@ -371,7 +373,7 @@ public class SalaryAcctController {
*/
@GET
@Path("/addedemployee/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportAddedEmployee(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
SalaryAcctEmployeeQueryParam param = buildSalaryAcctEmployeeQueryParam(request);
@ -510,7 +512,7 @@ public class SalaryAcctController {
//导出核算结果
@GET
@Path("/acctresult/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportSalaryAcctResult(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
SalaryAcctResultQueryParam param = new SalaryAcctResultQueryParam();
@ -538,7 +540,7 @@ public class SalaryAcctController {
//导出核算结果(自定义导出字段)
@GET
@Path("/acctresult/exportWithCustomFields")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportSalaryAcctResultWithCustomFields(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
SalaryAcctResultQueryParam param = new SalaryAcctResultQueryParam();
@ -645,7 +647,7 @@ public class SalaryAcctController {
//导出导入模板
@GET
@Path("/acctresult/importtemplate/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportImportTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
SalaryAcctImportTemplateParam param = new SalaryAcctImportTemplateParam();
@ -790,7 +792,7 @@ public class SalaryAcctController {
//导出线上线下对比结果
@GET
@Path("/comparisonresult/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportComparisonResult(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
SalaryComparisonResultQueryParam param = new SalaryComparisonResultQueryParam();
@ -879,7 +881,7 @@ public class SalaryAcctController {
//线下对比结果导入模板导出
@GET
@Path("/comparisonresult/importtemplate/export")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Produces(APPLICATION_OCTET_STREAM)
public Response exportComparisonResultTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
@ -928,4 +930,45 @@ public class SalaryAcctController {
}
/**********************************线下对比 end*********************************/
}
/**********************************欧姆龙月度薪资环比统计报表 start ********/
// 欧姆龙月度薪资环比统计报表
@POST
@Path("/oml/ydxzhbReportList")
@Produces(MediaType.APPLICATION_JSON)
public String ydxzhbReportList(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryAcctResultQueryParam param) {
User user = HrmUserVarify.getUser(request, response);
return new ResponseResult<String, Map<String, Object>>(user).run(getSalaryAcctResultWrapper(user)::ydxzhbReportList, param.getYear());
}
// 导出欧姆龙月度薪资环比统计报表
@GET
@Path("/oml/exportYdxzhbReport")
@Produces(APPLICATION_OCTET_STREAM)
public Response exportYdxzhbReport(@Context HttpServletRequest request, @Context HttpServletResponse response) {
try {
String year = request.getParameter("year");
User user = HrmUserVarify.getUser(request, response);
XSSFWorkbook workbook = getSalaryAcctResultWrapper(user).exportYdxzhbReport(year);
String time = LocalDate.now().toString();
String fileName = year + "年度月度薪资环比统计报表" + time;
try {
fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
StreamingOutput output = outputStream -> {
workbook.write(outputStream);
outputStream.flush();
};
response.setContentType("application/octet-stream");
return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
} catch (Exception e) {
log.error("欧姆龙月度薪资环比统计报表导出异常", e);
throw e;
}
}
/**********************************欧姆龙月度薪资环比统计报表 end ********/
}

View File

@ -23,6 +23,7 @@ import com.engine.salary.wrapper.proxy.SalaryAcctResultWrapperProxy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.hrm.User;
import java.math.BigDecimal;
@ -278,6 +279,19 @@ public class SalaryAcctResultWrapper extends Service implements SalaryAcctResult
getSalaryAcctResultService(user).batchUpdate(param);
}
/**
* 月度薪资环比统计报表本月上月维度比较
* @param year
* @return
*/
public Map<String, Object> ydxzhbReportList(String year) {
return getSalaryAcctResultService(user).ydxzhbReportList(year);
}
public XSSFWorkbook exportYdxzhbReport(String year) {
return getSalaryAcctResultService(user).exportYdxzhbReport(year);
}
/**
* 薪资核算-校验
*