diff --git a/src/com/engine/salary/constant/HrmSalaryPayrollConf.java b/src/com/engine/salary/constant/HrmSalaryPayrollConf.java new file mode 100644 index 000000000..0b0139420 --- /dev/null +++ b/src/com/engine/salary/constant/HrmSalaryPayrollConf.java @@ -0,0 +1,15 @@ +package com.engine.salary.constant; + +import weaver.general.BaseBean; + +public class HrmSalaryPayrollConf { + + public static final BaseBean baseBean = new BaseBean(); + + public static final String GEN_PDF = baseBean.getPropValue("hrmSalaryPayroll", "genPdf"); + public static final String HAS_SIGN = baseBean.getPropValue("hrmSalaryPayroll", "hasSign"); + public static final String TO_PDF_TOOL_PATH = baseBean.getPropValue("hrmSalaryPayroll", "toPdfToolPath"); + public static final String GEN_PATH = baseBean.getPropValue("hrmSalaryPayroll", "genPath"); + + +} diff --git a/src/com/engine/salary/entity/salaryBill/bo/SalaryBillBO.java b/src/com/engine/salary/entity/salaryBill/bo/SalaryBillBO.java index c321cab31..cef9101a2 100644 --- a/src/com/engine/salary/entity/salaryBill/bo/SalaryBillBO.java +++ b/src/com/engine/salary/entity/salaryBill/bo/SalaryBillBO.java @@ -5,6 +5,7 @@ import com.cloudstore.dev.api.bean.MessageBean; import com.cloudstore.dev.api.bean.MessageType; import com.cloudstore.dev.api.util.Util_Message; import com.engine.salary.annotation.SalaryFormulaVar; +import com.engine.salary.constant.HrmSalaryPayrollConf; import com.engine.salary.constant.SalaryArchiveConstant; import com.engine.salary.constant.SalaryBillConstant; import com.engine.salary.constant.SalaryTemplateSalaryItemSetGroupConstant; @@ -26,6 +27,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.pdfbox.multipdf.PDFMergerUtility; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,14 +35,10 @@ import weaver.common.MessageUtil; import weaver.conn.RecordSet; import weaver.email.EmailWorkRunnable; import weaver.file.ImageFileManager; -import weaver.general.BaseBean; import weaver.hrm.company.SubCompanyComInfo; import weaver.hrm.resource.ResourceComInfo; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -268,7 +266,6 @@ public class SalaryBillBO { public static void sendEmail(Map e, SalaryBillSendDTO salaryBillSendParam) { String content = genPayrollHtmlContent(e, salaryBillSendParam); - genPdf(e, salaryBillSendParam); // 消息接收者 String receivers = Optional.ofNullable(e.get("email")).orElse("").toString(); String title = getBillTitle(salaryBillSendParam.getSalaryTemplate().getTheme(), salaryBillSendParam.getSalaryDate(), Long.valueOf(e.get("employeeId").toString())); @@ -280,18 +277,50 @@ public class SalaryBillBO { public static void genPdf(Map e, SalaryBillSendDTO salaryBillSendParam) { String content = genPayrollHtmlContent(e, salaryBillSendParam); - BaseBean baseBean = new BaseBean(); - boolean genPdf = "1".equals(baseBean.getPropValue("hrmSalaryPayroll", "genPdf")); - boolean hasSign = "1".equals(baseBean.getPropValue("hrmSalaryPayroll", "hasSign")); - String genPath = baseBean.getPropValue("hrmSalaryPayroll", "genPath"); - String toPdfTool = new BaseBean().getPropValue("hrmSalaryPayroll", "toPdfToolPath"); - //生成html + String yyyyMM = SalaryDateUtil.getFormatYearMonth(salaryBillSendParam.getSalaryDate()); + Object id = e.getOrDefault("id", 1L); - String htmlPath = genPath + id + ".html"; + String htmlPath = HrmSalaryPayrollConf.GEN_PATH + yyyyMM + File.separator + id + ".html"; + + FileUtil.del(htmlPath); File touch = FileUtil.touch(htmlPath); FileUtil.appendUtf8String(content, touch); - String pdfPath = genPath + id + ".pdf"; - HtmlToPdf.convert(toPdfTool, htmlPath, pdfPath); + + String pdfPath = HrmSalaryPayrollConf.GEN_PATH + yyyyMM + File.separator + id + ".pdf"; + FileUtil.del(pdfPath); + HtmlToPdf.convert(HrmSalaryPayrollConf.TO_PDF_TOOL_PATH, htmlPath, pdfPath); + } + + /** + * 合并pdff + * + * @param pdfPath 最终合并的pdf + * @param filesToMerge 待合并的pdf + */ + public static void mergePdf(String pdfPath, List filesToMerge) { + + // 创建PDF合并工具实例 + PDFMergerUtility merger = new PDFMergerUtility(); + + // 遍历要合并的PDF文件列表 + for (String file : filesToMerge) { + if (FileUtil.isFile(file)) { + try { + merger.addSource(file); // 将每个文件添加到合并工具 + } catch (FileNotFoundException e) { + log.error("PDF合并失败1", e); + } + } + } + // 设置合并后的目标文件 + merger.setDestinationFileName(pdfPath); + try { + // 执行合并操作 + FileUtil.del(pdfPath); + merger.mergeDocuments(); + } catch (IOException e) { + log.error("PDF合并失败2", e); + } } @@ -318,12 +347,14 @@ public class SalaryBillBO { } baos.flush(); } catch (IOException e) { + log.error(e.getMessage(), e); } byte[] data = baos.toByteArray(); try { is.close(); baos.close(); } catch (IOException e) { + log.error(e.getMessage(), e); } return data; } @@ -517,19 +548,22 @@ public class SalaryBillBO { } else { buildMailMain(emailContent, e, salaryBillSendParam); } - //签章 - RecordSet rs = new RecordSet(); - rs.execute("select * from DocSignature where hrmresid=" + e.getOrDefault("employeeId", "1") + " order by markid"); - if (rs.next()) { - int imagefileid = rs.getInt("imagefileid"); - InputStream imageInputStream = ImageFileManager.getInputStreamById(imagefileid); - byte[] data = readInputStream(imageInputStream); - String imageBase64 = "data:image/jpeg;base64," + Base64Utils.encodeToString(data); - emailContent.append("
\n" + - " " + - "
"); - } + //签章 + boolean hasSign = "1".equals(HrmSalaryPayrollConf.HAS_SIGN); + if (hasSign) { + RecordSet rs = new RecordSet(); + rs.execute("select * from DocSignature where hrmresid=" + e.getOrDefault("employeeId", "1") + " order by markid"); + if (rs.next()) { + int imagefileid = rs.getInt("imagefileid"); + InputStream imageInputStream = ImageFileManager.getInputStreamById(imagefileid); + byte[] data = readInputStream(imageInputStream); + String imageBase64 = "data:image/jpeg;base64," + Base64Utils.encodeToString(data); + emailContent.append("
\n" + + " " + + "
"); + } + } emailContent.append(""); } diff --git a/src/com/engine/salary/entity/salaryBill/param/SalaryExportPdfParam.java b/src/com/engine/salary/entity/salaryBill/param/SalaryExportPdfParam.java new file mode 100644 index 000000000..a7085efad --- /dev/null +++ b/src/com/engine/salary/entity/salaryBill/param/SalaryExportPdfParam.java @@ -0,0 +1,26 @@ +package com.engine.salary.entity.salaryBill.param; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 工资单导出pdf参数 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SalaryExportPdfParam { + + /** + * 工资单发放Id + */ + private Long salarySendId; + + /** + * 主键id + */ + private Long id; +} diff --git a/src/com/engine/salary/service/SalaryBillService.java b/src/com/engine/salary/service/SalaryBillService.java index 0f8b9030a..394b2994d 100644 --- a/src/com/engine/salary/service/SalaryBillService.java +++ b/src/com/engine/salary/service/SalaryBillService.java @@ -1,5 +1,6 @@ package com.engine.salary.service; +import com.engine.salary.entity.salaryBill.param.SalaryExportPdfParam; import com.engine.salary.entity.salaryBill.param.SalarySendGrantParam; import java.util.List; @@ -42,6 +43,9 @@ public interface SalaryBillService { */ void feedBackSalaryBill(Long salaryInfoId); + + String exportPdf(SalaryExportPdfParam param); + /** * 工资单撤回 * diff --git a/src/com/engine/salary/service/impl/SalaryBillServiceImpl.java b/src/com/engine/salary/service/impl/SalaryBillServiceImpl.java index e2af35851..821bec203 100644 --- a/src/com/engine/salary/service/impl/SalaryBillServiceImpl.java +++ b/src/com/engine/salary/service/impl/SalaryBillServiceImpl.java @@ -7,6 +7,7 @@ import com.engine.core.impl.Service; import com.engine.salary.biz.SalarySendBiz; import com.engine.salary.biz.SalarySendInfoBiz; import com.engine.salary.cache.SalaryCacheKey; +import com.engine.salary.constant.HrmSalaryPayrollConf; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.progress.ProgressDTO; import com.engine.salary.entity.salaryBill.bo.SalaryBillBO; @@ -15,6 +16,7 @@ import com.engine.salary.entity.salaryBill.dto.SalaryBillSendDTO; import com.engine.salary.entity.salaryBill.dto.SalaryBillWatermarkDTO; import com.engine.salary.entity.salaryBill.dto.SalarySendInfoListDTO; import com.engine.salary.entity.salaryBill.dto.SalaryTemplateSalaryItemSetListDTO; +import com.engine.salary.entity.salaryBill.param.SalaryExportPdfParam; import com.engine.salary.entity.salaryBill.param.SalarySendGrantParam; import com.engine.salary.entity.salaryBill.param.SalarySendInfoQueryParam; import com.engine.salary.entity.salaryBill.po.SalarySendInfoPO; @@ -31,6 +33,7 @@ import com.engine.salary.mapper.salarybill.SalarySendInfoMapper; import com.engine.salary.mapper.salarybill.SalarySendMapper; import com.engine.salary.service.*; import com.engine.salary.util.JsonUtil; +import com.engine.salary.util.SalaryDateUtil; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; import com.google.common.collect.Lists; @@ -45,6 +48,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import weaver.hrm.User; +import java.io.File; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.util.*; @@ -129,7 +133,7 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService * 工资单发放 start **********************************************************************/ @Override - public Map grant(SalarySendGrantParam param) { + public Map grant(SalarySendGrantParam param) { // 1.检查和获取工资单发放 SalarySendPO salarySend = checkAndGetSalarySend(param.getSalarySendId()); // // 已经冻结不能操作 @@ -219,6 +223,9 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService // 3.发送消息:先修改数据再发消息,避免出错后无法撤回 List successIds = sendMessage(enableSendList, salaryBillSendParam); + //生成pdf + genPdf(salaryBillSendParam, enableSendList); + // 4.发放 grantSendInfo(successIds, salarySend, salaryTemplate, salaryBillSendParam); @@ -232,8 +239,6 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService + SalaryI18nUtil.getI18nLabel(134808, "失败条数") + "[" + (total - successCount) + "]"; // 发送进度完成 getProgressService(user).finish(SalaryCacheKey.SALARY_GRANT_PROGRESS + "_" + salarySend.getId(), true, messsage); -// log.info("工资单发送组装耗时:{}毫秒;工资单发送消息中心耗时:{}毫秒;工资单数据更改总耗时:{}毫秒;工资单发送总耗时:{}毫秒;工资单云桥图片地址:{}", l3 - l2, l4 - l3, l5 - l4, System.currentTimeMillis() - l, -// salaryBillSendParam == null ? "" : salaryBillSendParam.getPicUrl()); } catch (Exception e) { log.info("发送出错:{}", e.getMessage(), e); // 发送进度失败 @@ -242,6 +247,32 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService } } + private void genPdf(SalaryBillSendDTO salaryBillSendParam, List> enableSendList) { + boolean genPdf = "1".equals(HrmSalaryPayrollConf.GEN_PDF); + if (genPdf) { + LocalRunnable localRunnable = new LocalRunnable() { + @Override + public void execute() { + //生成工资单pdf + enableSendList.forEach(e -> { + SalaryBillBO.genPdf(e, salaryBillSendParam); + }); + + //合并工资单pdf + //1、先获取所有工资单 + Long id = salaryBillSendParam.getSalarySend().getId(); + List salarySendInfos = getSalarySendInfoMapper().listSome(SalarySendInfoPO.builder().salarySendId(id).sendStatus(1).build()); + //2、工资单pdf转为路径 + String yyyyMM = SalaryDateUtil.getFormatYearMonth(salaryBillSendParam.getSalaryDate()); + List filesToMerge = salarySendInfos.stream().map(po -> HrmSalaryPayrollConf.GEN_PATH + yyyyMM + File.separator + po.getId() + ".pdf").collect(Collectors.toList()); + String pdfPath = HrmSalaryPayrollConf.GEN_PATH + yyyyMM + File.separator + id + ".pdf"; + SalaryBillBO.mergePdf(pdfPath, filesToMerge); + } + }; + ThreadPoolUtil.fixedPoolExecute(ModulePoolEnum.OTHER, "salaryBillGenPdf", localRunnable); + } + } + /** * 构建发送参数 * @@ -301,7 +332,7 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService // 工资单水印文本动态变量 List wmTextFieldIds = SalaryBillBO.getWmTextFieldIds(domain, salaryBillWatermark); // 邮件水印模板 - boolean isEnableEmail = salaryTemplate.getEmailStatus().equals(SalaryTemplateWhetherEnum.TRUE.getValue()); + boolean isEnableEmail = salaryTemplate.getEmailStatus().equals(SalaryTemplateWhetherEnum.TRUE.getValue()); String emailWmContentTemplate = SalaryBillBO.buildEmailWmContentTemplate(isEnableEmail, salaryBillWatermark); return SalaryBillSendDTO.builder() @@ -428,7 +459,7 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService @Override public void confirmSalaryBill(Long salaryInfoId) { SalarySendInfoPO sendInfoPO = getSalarySendInfoMapper().getById(salaryInfoId); - if(ObjectUtils.isEmpty(sendInfoPO)){ + if (ObjectUtils.isEmpty(sendInfoPO)) { throw new SalaryRunTimeException("工资单不存在或已被删除!"); } sendInfoPO.setBillConfirmStatus(BillConfimStatusEnum.CONFIRMED.getValue()); @@ -439,7 +470,7 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService @Override public void feedBackSalaryBill(Long salaryInfoId) { SalarySendInfoPO sendInfoPO = getSalarySendInfoMapper().getById(salaryInfoId); - if(ObjectUtils.isEmpty(sendInfoPO)){ + if (ObjectUtils.isEmpty(sendInfoPO)) { throw new SalaryRunTimeException("工资单不存在或已被删除!"); } sendInfoPO.setBillConfirmStatus(BillConfimStatusEnum.FEEDBACK.getValue()); @@ -447,6 +478,20 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService getSalarySendInfoMapper().updateIgnoreNull(sendInfoPO); } + @Override + public String exportPdf(SalaryExportPdfParam param) { + SalarySendPO salarySend = checkAndGetSalarySend(param.getSalarySendId()); + String yearMonth = SalaryDateUtil.getFormatYearMonth(salarySend.getSalaryMonth()); + String path = HrmSalaryPayrollConf.GEN_PATH + File.separator + yearMonth + File.separator + "%s" + ".pdf"; + Long id = param.getId(); + if (id == null) { + path = String.format(path, param.getSalarySendId()); + } else { + path = String.format(path, id); + } + return path; + } + public List> getSendInfoList(Long sendId, List ids) { SalarySendPO salarySend = getSalarySendMapper().getById(sendId); diff --git a/src/com/engine/salary/web/SalaryBillController.java b/src/com/engine/salary/web/SalaryBillController.java index f8a7ce21d..1fe1403c4 100644 --- a/src/com/engine/salary/web/SalaryBillController.java +++ b/src/com/engine/salary/web/SalaryBillController.java @@ -29,8 +29,11 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Paths; import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @@ -521,6 +524,47 @@ public class SalaryBillController { return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build(); } +// @GET +// @Path("/exportPdf") +// @Produces({"application/pdf"}) +// public Response getPDF(@Context HttpServletRequest request, @Context HttpServletResponse response) { +// +// File f = new File("D:\\gzd\\2023-02\\1695104948592.pdf"); +// return Response.ok(f, "application/pdf").build(); +// +// } + + @GET + @Path("/exportPdf") + public Response downloadPdfFile(@Context HttpServletRequest request, @Context HttpServletResponse response) { + User user = HrmUserVarify.getUser(request, response); + SalaryExportPdfParam salaryExportPdfParam = new SalaryExportPdfParam(); + String id = request.getParameter("id"); + if(StringUtils.isNotBlank(id)){ + salaryExportPdfParam.setId(Long.valueOf(id)); + } + String salarySendId = request.getParameter("salarySendId"); + if(StringUtils.isNotBlank(salarySendId)){ + salaryExportPdfParam.setSalarySendId(Long.valueOf(salarySendId)); + } + + StreamingOutput fileStream = new StreamingOutput() { + @Override + public void write(java.io.OutputStream output) throws IOException, WebApplicationException + { + String pdfPath = getSalarySendWrapper(user).exportPdf(salaryExportPdfParam); + java.nio.file.Path path = Paths.get(pdfPath); + byte[] data = Files.readAllBytes(path); + output.write(data); + output.flush(); + } + }; + return Response + .ok(fileStream, MediaType.APPLICATION_OCTET_STREAM) + .header("content-disposition","attachment; filename = myfile.pdf") + .build(); + } + /** * 我的工资单列表 * diff --git a/src/com/engine/salary/wrapper/SalarySendWrapper.java b/src/com/engine/salary/wrapper/SalarySendWrapper.java index 1d890905a..c1f84e730 100644 --- a/src/com/engine/salary/wrapper/SalarySendWrapper.java +++ b/src/com/engine/salary/wrapper/SalarySendWrapper.java @@ -14,7 +14,6 @@ import com.cloudstore.eccom.result.WeaResultMsg; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.salary.constant.SalaryItemConstant; -import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.salaryBill.dto.*; import com.engine.salary.entity.salaryBill.param.*; import com.engine.salary.entity.salaryBill.po.SalarySendPO; @@ -698,4 +697,8 @@ public class SalarySendWrapper extends Service implements SalarySendWrapperProxy } getSalaryBillService(user).feedBackSalaryBill(salaryInfoId); } + + public String exportPdf(SalaryExportPdfParam param) { + return getSalaryBillService(user).exportPdf(param); + } }