diff --git a/resource/WEB-INF/prop/hrmSalaryPayroll.properties b/resource/WEB-INF/prop/hrmSalaryPayroll.properties new file mode 100644 index 000000000..ac20aedaa --- /dev/null +++ b/resource/WEB-INF/prop/hrmSalaryPayroll.properties @@ -0,0 +1,4 @@ +genPdf=1 +hasSign=1 +toPdfToolPath=H:\\tools\\wkhtmltox\\bin\\wkhtmltopdf.exe +genPath=D:\\ diff --git a/src/com/engine/salary/constant/HrmSalaryPayrollConf.java b/src/com/engine/salary/constant/HrmSalaryPayrollConf.java new file mode 100644 index 000000000..e8bc9e341 --- /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 boolean GEN_PDF = "1".equals(baseBean.getPropValue("hrmSalaryPayroll", "genPdf")); + public static final boolean HAS_SIGN = "1".equals(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 c298b33fd..13d873527 100644 --- a/src/com/engine/salary/entity/salaryBill/bo/SalaryBillBO.java +++ b/src/com/engine/salary/entity/salaryBill/bo/SalaryBillBO.java @@ -1,9 +1,11 @@ package com.engine.salary.entity.salaryBill.bo; +import cn.hutool.core.io.FileUtil; 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; @@ -19,17 +21,24 @@ import com.engine.salary.enums.salarybill.SalaryTemplateTextContentPositionEnum; import com.engine.salary.enums.salarybill.SalaryTemplateWhetherEnum; import com.engine.salary.util.SalaryDateUtil; import com.engine.salary.util.SalaryI18nUtil; +import com.engine.salary.util.pdf.HtmlToPdf; +import com.fapiao.neon.util.Base64Utils; +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; import weaver.common.MessageUtil; +import weaver.conn.RecordSet; import weaver.email.EmailWorkRunnable; +import weaver.file.ImageFileManager; import weaver.hrm.company.SubCompanyComInfo; import weaver.hrm.resource.ResourceComInfo; -import java.io.IOException; +import java.io.*; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -38,6 +47,8 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; +import static com.engine.salary.constant.HrmSalaryPayrollConf.HAS_SIGN; + public class SalaryBillBO { private static final Logger log = LoggerFactory.getLogger(SalaryBillBO.class); @@ -255,23 +266,101 @@ public class SalaryBillBO { } } - public static void sendEmail(Map e, Map allEmployeeMap, SalaryBillSendDTO salaryBillSendParam) { - StringBuilder emailContent = new StringBuilder(); - emailContent.append("
"); + public static void sendEmail(Map e, SalaryBillSendDTO salaryBillSendParam) { + String content = genPayrollHtmlContent(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())); - SalaryBillBO.buildEmailContent(emailContent, e, salaryBillSendParam); - // 构建水印内容 - buildEmailWatermarkContent(emailContent, e, salaryBillSendParam); - emailContent.append("
"); + if (StringUtils.isNotBlank(receivers)) { -// MessageUtil.sendEmail(receivers, title, emailContent.toString()); - EmailWorkRunnable.threadModeReminder(receivers, title, emailContent.toString()); + EmailWorkRunnable.threadModeReminder(receivers, title, content); + } + } + + public static void genPdf(Map e, SalaryBillSendDTO salaryBillSendParam) { + String content = genPayrollHtmlContent(e, salaryBillSendParam); + String yyyyMM = SalaryDateUtil.getFormatYearMonth(salaryBillSendParam.getSalaryDate()); + + Long sendId = salaryBillSendParam.getSalarySend().getId(); + Object id = e.getOrDefault("id", 1L); + String htmlPath = HrmSalaryPayrollConf.GEN_PATH + yyyyMM + File.separator + sendId + File.separator + id + ".html"; + + FileUtil.del(htmlPath); + File touch = FileUtil.touch(htmlPath); + FileUtil.appendUtf8String(content, touch); + + String pdfPath = HrmSalaryPayrollConf.GEN_PATH + yyyyMM + File.separator+ sendId + 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); } } + @NotNull + private static String genPayrollHtmlContent(Map e, SalaryBillSendDTO salaryBillSendParam) { + StringBuilder emailContent = new StringBuilder(); + emailContent.append(""); + emailContent.append("
"); + SalaryBillBO.buildEmailContent(emailContent, e, salaryBillSendParam); + // 构建水印内容 + buildEmailWatermarkContent(emailContent, e, salaryBillSendParam); + emailContent.append("
"); + return emailContent.toString(); + } + + + public static byte[] readInputStream(InputStream is) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length = 0; + try { + while ((length = is.read(buffer)) != -1) { + baos.write(buffer, 0, length); + } + 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; + } public static void sendSMS(SalaryBillSendDTO salaryBillSendParam, Long id, Long employeeId) { @@ -432,7 +521,7 @@ public class SalaryBillBO { * @return */ public static void buildEmailContent(StringBuilder emailContent, Map e, SalaryBillSendDTO salaryBillSendParam) { - emailContent.append("
"); + emailContent.append("
"); // 1.标题 emailContent.append("
"); // emailContent.append(salaryBillSendParam.getTitle()); @@ -463,6 +552,20 @@ public class SalaryBillBO { buildMailMain(emailContent, e, salaryBillSendParam); } + //签章 + if (HAS_SIGN) { + 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("
"); } @@ -489,56 +592,53 @@ public class SalaryBillBO { if (CollectionUtils.isEmpty(salaryItemSet.getItems())) { continue; } - emailContent.append("
"); + emailContent.append("
"); if (!salaryItemSet.getGroupId().equals(SalaryTemplateSalaryItemSetGroupConstant.NO_TYPE_GROUP_ID)) { - emailContent.append("
"); + emailContent.append("
"); // 4.1.薪资项目组名 emailContent.append(salaryItemSet.getGroupName()); emailContent.append("
"); } - emailContent.append("
"); - for (int i = 0; i < salaryItemSet.getItems().size(); i++) { - SalaryTemplateSalaryItemListDTO salaryItem = salaryItemSet.getItems().get(i); - // 员工基本信息 - if (salaryItemSet.getGroupId().equals(SalaryTemplateSalaryItemSetGroupConstant.EMPLOYEE_INFO_GROUP_ID) && salaryBillSendParam.getEmployeeInformation() != null) { - Optional optionalEmpItem = salaryBillSendParam.getEmployeeInformation().getItems().stream().filter(f -> f.getId().equals(salaryItem.getId())).findFirst(); - // 4.2.员工信息 - emailContent.append("
"); - emailContent.append("
"); - emailContent.append(""); - emailContent.append((optionalEmpItem.isPresent() ? optionalEmpItem.get().getName() : "")); - emailContent.append(""); - emailContent.append("
"); - emailContent.append("
"); - emailContent.append((optionalEmpItem.isPresent() ? optionalEmpItem.get().getSalaryItemValue() : "")); - emailContent.append("
"); - emailContent.append("
"); - } else { - for (Object keyName : e.keySet()) { - if ((salaryItem.getId() + SalaryArchiveConstant.DYNAMIC_SUFFIX).equals(keyName.toString())) { - boolean isHide = (isHideNull && e.get(keyName.toString()) != null) || (isHideZero && "0.00".equals(e.get(keyName.toString()))); - // 4.2.薪资项目 - emailContent.append("
"); - emailContent.append("
"); - emailContent.append(""); - emailContent.append(salaryItem.getName()); - emailContent.append(""); - emailContent.append("
"); - emailContent.append("
"); - emailContent.append(e.get(keyName.toString())); - emailContent.append("
"); - emailContent.append("
"); - break; + emailContent.append(""); + emailContent.append(""); + List items = salaryItemSet.getItems(); + List> itemsPartition = Lists.partition(items, 3); + itemsPartition.forEach(itemPartition -> { + emailContent.append(""); + for (int i = 0; i < itemPartition.size(); i++) { + SalaryTemplateSalaryItemListDTO salaryItem = itemPartition.get(i); + // 员工基本信息 + if (salaryItemSet.getGroupId().equals(SalaryTemplateSalaryItemSetGroupConstant.EMPLOYEE_INFO_GROUP_ID) && salaryBillSendParam.getEmployeeInformation() != null) { + Optional optionalEmpItem = salaryBillSendParam.getEmployeeInformation().getItems().stream().filter(f -> f.getId().equals(salaryItem.getId())).findFirst(); + // 4.2.员工信息 + emailContent.append(""); + + emailContent.append(""); + } else { + for (Object keyName : e.keySet()) { + if ((salaryItem.getId() + SalaryArchiveConstant.DYNAMIC_SUFFIX).equals(keyName.toString())) { + boolean isHide = (isHideNull && e.get(keyName.toString()) != null) || (isHideZero && "0.00".equals(e.get(keyName.toString()))); + // 4.2.薪资项目 + emailContent.append(""); + + emailContent.append(""); + break; + } } } } - } - emailContent.append(""); + emailContent.append(""); + }); + emailContent.append(""); + emailContent.append("
"); + emailContent.append((optionalEmpItem.isPresent() ? optionalEmpItem.get().getName() : "")); + emailContent.append(""); + emailContent.append((optionalEmpItem.isPresent() ? optionalEmpItem.get().getSalaryItemValue() : "")); + emailContent.append(""); + emailContent.append(salaryItem.getName()); + emailContent.append(""); + emailContent.append(e.get(keyName.toString())); + emailContent.append("
"); emailContent.append("
"); } emailContent.append("
"); @@ -586,29 +686,36 @@ public class SalaryBillBO { emailContent.append("
"); emailContent.append("
"); - for (int i = 0; i < salaryItemSet.getItems().size(); i++) { - SalaryTemplateSalaryItemListDTO salaryItem = salaryItemSet.getItems().get(i); - for (Object keyName : e.keySet()) { - if ((salaryItem.getId() + SalaryArchiveConstant.DYNAMIC_SUFFIX).equals(keyName.toString())) { - boolean isHide = (isHideNull && e.get(keyName.toString()) != null) || (isHideZero && "0.00".equals(e.get(keyName.toString()))); - // 4.2.薪资项目 - emailContent.append("
"); - emailContent.append("
"); - emailContent.append(""); - emailContent.append(salaryItem.getName()); - emailContent.append(""); - emailContent.append("
"); - emailContent.append("
"); - emailContent.append(e.get(keyName.toString())); - emailContent.append("
"); - emailContent.append("
"); - break; + emailContent.append(""); + emailContent.append(""); + List items = salaryItemSet.getItems(); + List> itemsPartition = Lists.partition(items, 3); + itemsPartition.forEach(itemPartition -> { + emailContent.append(""); + for (int i = 0; i < itemPartition.size(); i++) { + SalaryTemplateSalaryItemListDTO salaryItem = itemPartition.get(i); + for (Object keyName : e.keySet()) { + if ((salaryItem.getId() + SalaryArchiveConstant.DYNAMIC_SUFFIX).equals(keyName.toString())) { + boolean isHide = (isHideNull && e.get(keyName.toString()) != null) || (isHideZero && "0.00".equals(e.get(keyName.toString()))); + // 4.2.薪资项目 + emailContent.append(""); + + emailContent.append(""); + break; + } } } - } + emailContent.append(""); + }); + + + emailContent.append(""); + emailContent.append("
"); + emailContent.append(salaryItem.getName()); + emailContent.append(""); + emailContent.append(e.get(keyName.toString())); + emailContent.append("
"); + // 5.文本内容-如果在薪资项目后 emailContent.append("
"); for (int j = 0; j < 8; j++) { - emailWmContentTemp.append("
"); + emailWmContentTemp.append("
"); // 赋值 emailWmContentTemp.append(variable); emailWmContentTemp.append("
"); @@ -801,7 +908,7 @@ public class SalaryBillBO { return emailWmContentTemp.toString(); } - public static String handleWmText(String wmText, List wmTextFieldIds, DataCollectionEmployee simpleEmployee){ + public static String handleWmText(String wmText, List wmTextFieldIds, DataCollectionEmployee simpleEmployee) { for (String wmTextFieldId : wmTextFieldIds) { // 当前操作者姓名 if (SalaryBillConstant.HRM_Name.equals(wmTextFieldId)) { @@ -820,10 +927,10 @@ public class SalaryBillBO { wmText = wmText.replace(SalaryBillConstant.HRM_prefix + SalaryBillConstant.HRM_CurrentOperatorId, Objects.isNull(simpleEmployee) ? StringUtils.EMPTY : simpleEmployee.getEmployeeId().toString()); // 当前操作者部门 } else if (SalaryBillConstant.HRM_Department.equals(wmTextFieldId)) { - wmText = wmText.replace(SalaryBillConstant.HRM_prefix + SalaryBillConstant.HRM_Department, Objects.isNull(simpleEmployee) || Objects.isNull(simpleEmployee.getDepartmentName()) ? StringUtils.EMPTY : simpleEmployee.getDepartmentName()); + wmText = wmText.replace(SalaryBillConstant.HRM_prefix + SalaryBillConstant.HRM_Department, Objects.isNull(simpleEmployee) || Objects.isNull(simpleEmployee.getDepartmentName()) ? StringUtils.EMPTY : simpleEmployee.getDepartmentName()); // 当前操作者分部 } else if (SalaryBillConstant.HRM_SecondDepartment.equals(wmTextFieldId)) { - wmText = wmText.replace(SalaryBillConstant.HRM_prefix + SalaryBillConstant.HRM_SecondDepartment, Objects.isNull(simpleEmployee) || Objects.isNull(simpleEmployee.getSubcompanyName()) ? StringUtils.EMPTY : simpleEmployee.getSubcompanyName()); + wmText = wmText.replace(SalaryBillConstant.HRM_prefix + SalaryBillConstant.HRM_SecondDepartment, Objects.isNull(simpleEmployee) || Objects.isNull(simpleEmployee.getSubcompanyName()) ? StringUtils.EMPTY : simpleEmployee.getSubcompanyName()); // 当前日期 } else if (SalaryBillConstant.HRM_CurrentDate.equals(wmTextFieldId)) { wmText = wmText.replace(SalaryBillConstant.HRM_prefix + SalaryBillConstant.HRM_CurrentDate, SalaryDateUtil.getFormatLocalDate(LocalDate.now())); 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 6b438b564..ca8b344e7 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,12 +48,15 @@ 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.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import static com.engine.salary.constant.HrmSalaryPayrollConf.GEN_PDF; + /** * 工资单发放 *

Copyright: Copyright (c) 2022

@@ -129,7 +135,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 +225,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 +241,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 +249,31 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService } } + private void genPdf(SalaryBillSendDTO salaryBillSendParam, List> enableSendList) { + if (GEN_PDF) { + 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 + id + File.separator + po.getId() + ".pdf").collect(Collectors.toList()); + String pdfPath = HrmSalaryPayrollConf.GEN_PATH + yyyyMM + File.separator + id + File.separator + id + ".pdf"; + SalaryBillBO.mergePdf(pdfPath, filesToMerge); + } + }; + ThreadPoolUtil.fixedPoolExecute(ModulePoolEnum.OTHER, "salaryBillGenPdf", localRunnable); + } + } + /** * 构建发送参数 * @@ -301,7 +333,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() @@ -406,7 +438,7 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService // 更新进度 getProgressService(user).getAndAddCalculatedQty(SalaryCacheKey.SALARY_GRANT_PROGRESS + "_" + salarySend.getId(), part.size()); /** 注意只有邮件才需要加密的核算数据 */ - if (isEnableEmail) { + if (isEnableEmail || GEN_PDF) { List acctEmployees = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordIdsAndEmployeeIds(Collections.singletonList(salarySend.getSalaryAccountingId()), part); salaryAcctEmployees.addAll(acctEmployees); salaryAcctResultValues.addAll(getSalaryAcctResultService(user).listBySalaryAcctEmployeeIds(SalaryEntityUtil.properties(acctEmployees, SalaryAcctEmployeePO::getId, Collectors.toList()))); @@ -414,7 +446,7 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService } } else { /** 注意只有邮件才需要加密的核算数据 */ - if (isEnableEmail) { + if (isEnableEmail || GEN_PDF) { salaryAcctEmployees = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(salarySend.getSalaryAccountingId()); salaryAcctResultValues = getSalaryAcctResultService(user).listBySalaryAcctRecordIds(Collections.singletonList(salarySend.getSalaryAccountingId())); } @@ -428,7 +460,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 +471,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 +479,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 + salarySend.getId() + 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); @@ -525,10 +571,10 @@ public class SalaryBillServiceImpl extends Service implements SalaryBillService SalaryBillBO.sendMsg(salaryBillSendParam, Long.valueOf(e.get("id").toString()), Long.valueOf(e.get("employeeId").toString())); } - if (sendChannels.contains(MessageChannelEnum.EMAIL)) { + if (sendChannels.contains(MessageChannelEnum.EMAIL) || GEN_PDF) { // 构建发送消息 SalaryBillBO.buildEmployeeInfo(salaryBillSendParam, allEmployeeMap.get(e.get("employeeId").toString())); - SalaryBillBO.sendEmail(e, allEmployeeMap, salaryBillSendParam); + SalaryBillBO.sendEmail(e, salaryBillSendParam); } diff --git a/src/com/engine/salary/util/pdf/HtmlToPdf.java b/src/com/engine/salary/util/pdf/HtmlToPdf.java new file mode 100644 index 000000000..35e23da49 --- /dev/null +++ b/src/com/engine/salary/util/pdf/HtmlToPdf.java @@ -0,0 +1,57 @@ +package com.engine.salary.util.pdf; + +import com.engine.workflow.biz.requestForm.HtmlToPdfInterceptor; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; + +@Slf4j +public class HtmlToPdf { + + /** + * html转pdf + * + * @param toPdfTool 工具路径 + * @param srcPath html路径,可以是硬盘上的路径,也可以是网络路径 + * @param destPath pdf保存路径 + * @return 转换成功返回true + */ + public static boolean convert(String toPdfTool, String srcPath, String destPath) { + File file = new File(destPath); + File parent = file.getParentFile(); + //如果pdf保存路径不存在,则创建路径 + if (!parent.exists()) { + parent.mkdirs(); + } + StringBuilder cmd = new StringBuilder(); + cmd.append(toPdfTool); + cmd.append(" "); + cmd.append(" --header-line");//页眉下面的线 + cmd.append(" --margin-top 3cm ");//设置页面上边距 (default 10mm) + // cmd.append(" --header-html file:///"+WebUtil.getServletContext().getRealPath("")+FileUtil.convertSystemFilePath("\\style\\pdf\\head.html"));// (添加一个HTML页眉,后面是网址) + cmd.append(" --header-spacing 5 --orientation Portrait ");// (设置页眉和内容的距离,默认0) + //cmd.append(" --footer-center (设置在中心位置的页脚内容)");//设置在中心位置的页脚内容 + //cmd.append(" --footer-html file:///"+WebUtil.getServletContext().getRealPath("")+FileUtil.convertSystemFilePath("\\style\\pdf\\foter.html"));// (添加一个HTML页脚,后面是网址) + cmd.append(" --footer-line");//* 显示一条线在页脚内容上) + cmd.append(" --footer-spacing 5 ");// (设置页脚和内容的距离) + //--orientation Portrait --footer-center [page]/[topage] --footer-line + cmd.append(srcPath); + cmd.append(" "); + cmd.append(destPath); + boolean result = true; + try { + Process proc = Runtime.getRuntime().exec(cmd.toString()); + HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream()); + HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream()); + error.start(); + output.start(); + proc.waitFor(); + } catch (Exception e) { + result = false; + e.printStackTrace(); + } + + return result; + } + +} diff --git a/src/com/engine/salary/web/SalaryBillController.java b/src/com/engine/salary/web/SalaryBillController.java index 0985cfc64..382f93636 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,53 @@ 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(); + } + }; + + String fileName = "工资单"; + try { + fileName = URLEncoder.encode(fileName + ".pdf", "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return Response + .ok(fileStream, MediaType.APPLICATION_OCTET_STREAM) + .header("content-disposition", "attachment; filename =" + fileName) + .build(); + } + /** * 我的工资单列表 * @@ -637,6 +687,7 @@ public class SalaryBillController { /** * 校验验证码 + * * @param request * @param response * @param param @@ -660,7 +711,8 @@ public class SalaryBillController { @GET @Path("/baseSet/getForm") @Produces(MediaType.APPLICATION_JSON) - public String getBaseSetForm( @Context HttpServletRequest request, @Context HttpServletResponse response ) { +// @ApiOperation("获取工资单基础设置表单") + public String getBaseSetForm(@Context HttpServletRequest request, @Context HttpServletResponse response) { User user = HrmUserVarify.getUser(request, response); return new ResponseResult(user).run(getSalaryBillBaseSetWrapper(user)::getBaseSetForm); } @@ -673,7 +725,7 @@ public class SalaryBillController { @POST @Path("/baseSet/previewWaterMark") @Produces(MediaType.APPLICATION_JSON) - public String getBaseSetForm( @Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryBaseSetSaveParam saveParam ) { + public String getBaseSetForm(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryBaseSetSaveParam saveParam) { User user = HrmUserVarify.getUser(request, response); return new ResponseResult(user).run(getSalaryBillBaseSetWrapper(user)::previewWaterMark, saveParam); } @@ -687,7 +739,8 @@ public class SalaryBillController { @POST @Path("/baseSet/save") @Produces(MediaType.APPLICATION_JSON) - public String saveBaseSet( @Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryBaseSetSaveParam saveParam) { +// @ApiOperation("保存工资单基础设置") + public String saveBaseSet(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalaryBaseSetSaveParam saveParam) { User user = HrmUserVarify.getUser(request, response); return new ResponseResult(user).run(getSalaryBillBaseSetWrapper(user)::saveBaseSet, saveParam); } 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); + } }