Просмотр исходного кода

同步奖惩记录,调薪单套打

qingwu 1 неделя назад
Родитель
Сommit
d40461b27f

+ 151 - 0
src/com/kingdee/shr/compensation/app/integrate/BatchSubmitShemeBillControllerBeanEx.java

@@ -0,0 +1,151 @@
+package com.kingdee.shr.compensation.app.integrate;
+
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.dao.IObjectPK;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.csinterface.biz.util.DBUtils;
+import com.kingdee.eas.framework.CoreBaseInfo;
+import com.kingdee.eas.hr.base.HRBillStateEnum;
+import com.kingdee.eas.hr.base.IRewardPunishType;
+import com.kingdee.eas.hr.base.RewardPunishTypeFactory;
+import com.kingdee.eas.hr.base.RewardPunishTypeInfo;
+import com.kingdee.eas.hr.emp.IPersonRewardPunish;
+import com.kingdee.eas.hr.emp.PersonRewardPunishFactory;
+import com.kingdee.eas.hr.emp.PersonRewardPunishInfo;
+import com.kingdee.eas.hr.state.IRewardPunishLevel;
+import com.kingdee.eas.hr.state.RewardPunishLevelFactory;
+import com.kingdee.eas.hr.state.RewardPunishLevelInfo;
+import com.kingdee.jdbc.rowset.IRowSet;
+import org.apache.log4j.Logger;
+
+import java.sql.SQLException;
+
+/**
+ * @Title: BatchSubmitShemeBillControllerBeanEx
+ * @Author 青梧
+ * @Package com.kingdee.shr.compensation.app.integrate
+ * @Date 2026/1/8 13:50
+ * @description: 审批通过后同步奖惩多行表
+ */
+public class BatchSubmitShemeBillControllerBeanEx extends BatchSubmitShemeBillControllerBean {
+    private static Logger logger = Logger.getLogger(BatchSubmitShemeBillControllerBeanEx.class);
+
+    @Override
+    protected void _setPassState(Context ctx, BOSUuid billId) throws BOSException, EASBizException {
+        super._setPassState(ctx, billId);
+        try {
+            syncPersonRewardPunish(ctx, new ObjectUuidPK(billId.toString()));
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public IObjectPK _submitEffect(Context ctx, CoreBaseInfo model) throws BOSException, EASBizException {
+        IObjectPK iObjectPK = super._submitEffect(ctx, model);
+        try {
+            syncPersonRewardPunish(ctx, iObjectPK);
+        } catch (SQLException e) {
+            throw new RuntimeException(e);
+        }
+        return iObjectPK;
+    }
+
+    /***
+     * 同步奖罚记录
+     * @param ctx
+     * @param iObjectPK
+     */
+    public void syncPersonRewardPunish(Context ctx, IObjectPK iObjectPK) throws BOSException, EASBizException, SQLException {
+        logger.error("syncPersonRewardPunish---start");
+        BatchSubmitShemeBillInfo batchSubmitShemeBillInfo = BatchSubmitShemeBillFactory.getLocalInstance(ctx).getBatchSubmitShemeBillInfo(iObjectPK);
+        //奖惩类型
+        IRewardPunishType iRewardPunishType = RewardPunishTypeFactory.getLocalInstance(ctx);
+        //奖惩级别
+        IRewardPunishLevel iRewardPunishLevel = RewardPunishLevelFactory.getLocalInstance(ctx);
+        //提报方案
+        CalSubmitSchemeInfo submitScheme = batchSubmitShemeBillInfo.getSubmitScheme();
+        ICalSubmitScheme iCalSubmitScheme = CalSubmitSchemeFactory.getLocalInstance(ctx);
+        CalSubmitSchemeInfo calSubmitSchemeInfo = iCalSubmitScheme.getCalSubmitSchemeInfo(new ObjectUuidPK(submitScheme.getId()));
+        logger.error("billstate----" + batchSubmitShemeBillInfo.getBillState());
+        logger.error("CalSubmitSchemeNumber----" + calSubmitSchemeInfo.getNumber());
+        //判断是否是审批通过并且提报方案是奖励或者惩戒
+        if (batchSubmitShemeBillInfo.getBillState().equals(HRBillStateEnum.AUDITED) && (calSubmitSchemeInfo.getNumber().equals("scy20") || calSubmitSchemeInfo.getNumber().equals("scy09"))) {
+            BatchSubmitShemeBillEntryCollection entry = batchSubmitShemeBillInfo.getEntry();
+            IPersonRewardPunish iPersonRewardPunish = PersonRewardPunishFactory.getLocalInstance(ctx);
+            for (int i = 0; i < entry.size(); i++) {
+                //奖惩记录表
+                PersonRewardPunishInfo personRewardPunishInfo = new PersonRewardPunishInfo();
+                BatchSubmitShemeBillEntryInfo batchSubmitShemeBillEntryInfo = entry.get(i);
+                //人员
+                personRewardPunishInfo.setPerson(batchSubmitShemeBillEntryInfo.getPerson());
+                //奖惩类型
+                if (calSubmitSchemeInfo.getNumber().equals("scy20")) {
+                    RewardPunishTypeInfo rewardPunishTypeInfo = iRewardPunishType.getRewardPunishTypeInfo("where number = '01'");
+                    personRewardPunishInfo.setType(rewardPunishTypeInfo);
+                    //测试环境sql  上生产需要改成生产表  测试环境表:惩戒:T_HR_SchemeBillEntry066cmp 奖励:T_HR_SchemeBillEntry064cmp
+                    //生产环境表
+                    String sql = "select s77,s84,s83 from T_HR_SchemeBillEntry064cmp where fbillId ='" + batchSubmitShemeBillInfo.getId() + "'";
+                    logger.error("sql--" + sql);
+                    IRowSet iRowSet = DBUtils.executeQuery(ctx, sql);
+                    if (iRowSet.next()) {
+                        //奖惩依据
+                        personRewardPunishInfo.setContent(iRowSet.getString("s83"));
+                        //奖惩事由
+                        personRewardPunishInfo.setDescription(iRowSet.getString("s84"));
+                        //奖惩金额
+                        personRewardPunishInfo.put("jcje", iRowSet.getString("s77"));
+                    }
+                    //奖惩级别
+                    String jlId = batchSubmitShemeBillInfo.getObjectValue("jl").get("id").toString();
+                    String jlSql = "select fnumber as number from CT_MP_Jljb where fid ='" + jlId + "'";
+                    iRowSet = DBUtils.executeQuery(ctx, jlSql);
+                    if (iRowSet.next()) {
+                        String number = iRowSet.getString("number");
+                        RewardPunishLevelInfo rewardPunishLevelInfo = iRewardPunishLevel.getRewardPunishLevelInfo("where number = '" + number + "'");
+                        personRewardPunishInfo.setRPLevel(rewardPunishLevelInfo);
+                    }
+                }
+                if (calSubmitSchemeInfo.getNumber().equals("scy09")) {
+                    RewardPunishTypeInfo rewardPunishTypeInfo = iRewardPunishType.getRewardPunishTypeInfo("where number = '02'");
+                    personRewardPunishInfo.setType(rewardPunishTypeInfo);
+                    //测试环境sql  上生产需要改成生产表  测试环境表:T_HR_SchemeBillEntry066cmp  生产环境表
+                    String sql = "select s69,s84,s83 from T_HR_SchemeBillEntry066cmp where fbillId ='" + batchSubmitShemeBillInfo.getId() + "'";
+                    logger.error("sql--" + sql);
+                    IRowSet iRowSet = DBUtils.executeQuery(ctx, sql);
+                    if (iRowSet.next()) {
+                        //奖惩依据
+                        personRewardPunishInfo.setContent(iRowSet.getString("s83"));
+                        //奖惩事由
+                        personRewardPunishInfo.setDescription(iRowSet.getString("s84"));
+                        //奖惩金额
+                        personRewardPunishInfo.put("jcje", iRowSet.getString("s69"));
+                    }
+                    //奖惩级别
+                    String cjId = batchSubmitShemeBillInfo.getObjectValue("cj").get("id").toString();
+                    String cjSql = "select fnumber as number from CT_MP_Cjjb where fid ='" + cjId + "'";
+                    iRowSet = DBUtils.executeQuery(ctx, cjSql);
+                    if (iRowSet.next()) {
+                        String number = iRowSet.getString("number");
+                        RewardPunishLevelInfo rewardPunishLevelInfo = iRewardPunishLevel.getRewardPunishLevelInfo("where number = '" + number + "'");
+                        personRewardPunishInfo.setRPLevel(rewardPunishLevelInfo);
+                    }
+                }
+
+                //奖惩时间
+                personRewardPunishInfo.setOccurDate(batchSubmitShemeBillEntryInfo.getEffectDate());
+                //单行显示
+                personRewardPunishInfo.setIsSingle(true);
+                iPersonRewardPunish.save(personRewardPunishInfo);
+//                iPersonRewardPunish.addnew(personRewardPunishInfo);
+            }
+        }
+        logger.error("syncPersonRewardPunish---end");
+    }
+
+
+}

+ 119 - 0
websrc/com/kingdee/eas/shr/cmpdesign/web/handler/utils/AdvancedZipUtils.java

@@ -0,0 +1,119 @@
+package com.kingdee.shr.cmpdesign.web.handler.utils;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * @Title: AdvancedZipUtils
+ * @Author ÇàÎà
+ * @Package com.kingdee.shr.cmpdesign.web.handler.utils
+ * @Date 2026/1/15 18:24
+ * @description:
+ */
+public class AdvancedZipUtils {
+    public static void createZipWithCompressionLevel(byte[] fileData, String fileName, String zipFilePath, int compressionLevel) {
+        try (FileOutputStream fos = new FileOutputStream(zipFilePath)) {
+            ZipOutputStream zos = new ZipOutputStream(fos);
+            Throwable var7 = null;
+
+            try {
+                zos.setLevel(compressionLevel);
+                zos.setComment("Created by Java Zip Utils");
+                ZipEntry entry = new ZipEntry(fileName);
+                zos.putNextEntry(entry);
+                zos.write(fileData);
+                zos.closeEntry();
+            } catch (Throwable var32) {
+                var7 = var32;
+                throw var32;
+            } finally {
+                if (zos != null) {
+                    if (var7 != null) {
+                        try {
+                            zos.close();
+                        } catch (Throwable var31) {
+                            var7.addSuppressed(var31);
+                        }
+                    } else {
+                        zos.close();
+                    }
+                }
+
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void createZipWithDirectory(byte[] fileData, String filePathInZip, String zipFilePath) {
+        try (FileOutputStream fos = new FileOutputStream(zipFilePath)) {
+            ZipOutputStream zos = new ZipOutputStream(fos);
+            Throwable var6 = null;
+
+            try {
+                ZipEntry entry = new ZipEntry(filePathInZip);
+                zos.putNextEntry(entry);
+                zos.write(fileData);
+                zos.closeEntry();
+            } catch (Throwable var31) {
+                var6 = var31;
+                throw var31;
+            } finally {
+                if (zos != null) {
+                    if (var6 != null) {
+                        try {
+                            zos.close();
+                        } catch (Throwable var30) {
+                            var6.addSuppressed(var30);
+                        }
+                    } else {
+                        zos.close();
+                    }
+                }
+
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void createZipFromMultipleFiles(Map<String, byte[]> files, String zipFilePath) {
+        try (FileOutputStream fos = new FileOutputStream(zipFilePath)) {
+            ZipOutputStream zos = new ZipOutputStream(fos);
+            Throwable var5 = null;
+
+            try {
+                for(Map.Entry<String, byte[]> file : files.entrySet()) {
+                    ZipEntry entry = new ZipEntry((String)file.getKey());
+                    zos.putNextEntry(entry);
+                    zos.write((byte[])file.getValue());
+                    zos.closeEntry();
+                }
+            } catch (Throwable var32) {
+                var5 = var32;
+                throw var32;
+            } finally {
+                if (zos != null) {
+                    if (var5 != null) {
+                        try {
+                            zos.close();
+                        } catch (Throwable var31) {
+                            var5.addSuppressed(var31);
+                        }
+                    } else {
+                        zos.close();
+                    }
+                }
+
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+}

+ 474 - 0
websrc/com/kingdee/eas/shr/cmpdesign/web/handler/v2/AdjustSalaryApplyListHandlerEx.java

@@ -0,0 +1,474 @@
+package com.kingdee.shr.cmpdesign.web.handler.v2;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.metadata.entity.*;
+import com.kingdee.bos.metadata.query.util.CompareType;
+import com.kingdee.eas.base.permission.UserInfo;
+import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
+import com.kingdee.eas.basedata.org.PositionInfo;
+import com.kingdee.eas.basedata.person.PersonInfo;
+import com.kingdee.eas.hr.ats.AtsUtil;
+import com.kingdee.eas.hr.ats.util.AtsDateUtils;
+import com.kingdee.eas.hr.emp.*;
+import com.kingdee.eas.util.app.ContextUtil;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.jdbc.rowset.IRowSet;
+import com.kingdee.shr.base.syssetting.context.SHRContext;
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
+import com.kingdee.shr.base.syssetting.web.dynamic.util.DynamicUtil;
+import com.kingdee.shr.base.syssetting.web.dynamic.util.MD5;
+import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
+import com.kingdee.shr.base.syssetting.web.util.UserUtil;
+import com.kingdee.shr.cmpdesign.app.v2.bill.*;
+import com.kingdee.shr.cmpdesign.web.handler.utils.AdvancedZipUtils;
+import com.kingdee.util.DateTimeUtils;
+import org.apache.log4j.Logger;
+import org.apache.poi.xwpf.usermodel.*;
+import org.springframework.ui.ModelMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.*;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.sql.SQLException;
+import java.text.MessageFormat;
+import java.util.*;
+;
+
+/**
+ * @Title: AdjustSalaryApplyListHandlerEx
+ * @Author 青梧
+ * @Package com.kingdee.shr.cmpdesign.web.handler.v2
+ * @Date 2026/1/14 15:37
+ * @description: 套打
+ */
+public class AdjustSalaryApplyListHandlerEx extends AdjustSalaryApplyListHandler {
+    private Context ctx = SHRContext.getInstance().getContext();
+    private static Logger logger = Logger.getLogger(AdjustSalaryApplyListHandlerEx.class);
+    // 定义薪资项编码常量
+    private static final String BASIC_SALARY = "SCY002";       // 基本工资标准
+    private static final String OVERTIME_SALARY = "SCY005";    // 加班工资标准
+    private static final String SKILL_SALARY = "SCY003";       // 技能工资标准
+    private static final String POST_ALLOWANCE = "SCY004";     // 岗位补助工资标准
+    private static final String EDU_ALLOWANCE = "SCY006";      // 学历补助标准
+    private static final String EXPENSE_ALLOWANCE = "SCY073";  // 费用补助标准
+    private static final String TOTAL_SALARY = "SCY001";       // 标准薪资合计
+    // 所有需要查询的薪资项编码
+    private static final String[] SALARY_ITEM_CODES = {BASIC_SALARY, OVERTIME_SALARY, SKILL_SALARY, POST_ALLOWANCE, EDU_ALLOWANCE, EXPENSE_ALLOWANCE, TOTAL_SALARY};
+
+    /**
+     * 定调薪申请单套打
+     *
+     * @param request
+     * @param response
+     * @param modelMap
+     * @throws SHRWebException
+     */
+    public void customPrintAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException, BOSException {
+        try {
+            String billId = this.getBillId(request);
+            //获取临时地址
+            HttpSession session = request.getSession();
+            String tempFilePath = UserUtil.getUserTempDirAbsolutePath(session); //存放
+            File tempFile = new File(tempFilePath);
+            if (!tempFile.exists()) {
+                tempFile.mkdirs();
+            }
+            Map map = new HashMap();
+            Map<String, byte[]> files = new HashMap();
+            //人员ID集合
+            Map<String, Object> PersonMap = getAdjustSalaryApplyPersonIds(billId);
+            Set personSet = (Set) PersonMap.get("personSet");
+            //查询定调薪申请单
+            SelectorItemCollection sic = new SelectorItemCollection();
+            sic.add("*");
+            sic.add("person.*");
+            sic.add("primaryPosition.*");
+            sic.add("personDep.*");
+            FilterInfo filterInfo = new FilterInfo();
+            FilterItemCollection filterItems = filterInfo.getFilterItems();
+            filterItems.add(new FilterItemInfo("person.id", personSet, CompareType.INCLUDE));
+            EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
+            //查询人员信息
+            IPersonPosition iPersonPosition = PersonPositionFactory.getLocalInstance(ctx);
+            PersonPositionCollection personPositionCollection = iPersonPosition.getPersonPositionCollection(entityViewInfo);
+            for (int i = 0; i < personPositionCollection.size(); i++) {
+                String fileName = "定调薪套打.docx";
+                String txtNameHash = MD5.md5Hash(fileName);
+                String realFileName = getEncryRealFileName(ctx, txtNameHash);
+                String txtPath = tempFilePath + File.separator + realFileName;
+                //  String fileStr = txtNameHash;
+                // 1. 配置文件路径
+                String templatePath = System.getProperty("EAS_HOME") + "/server/properties/templatePrint/dtxtdmb.docx";
+                String pdfOutputPath = txtPath + ".docx";
+                PersonPositionInfo personPositionInfo = personPositionCollection.get(i);
+                //人员
+                PersonInfo person = personPositionInfo.getPerson();
+                //职位
+                PositionInfo primaryPosition = personPositionInfo.getPrimaryPosition();
+                //部门
+                AdminOrgUnitInfo personDep = personPositionInfo.getPersonDep();
+                // 2. 定义占位符-实际数据映射(同之前方案,可动态获取)
+                Map<String, String> dataMap = new HashMap<>();
+                String personId = person.getId().toString();
+                //获取人员基本信息
+                Map<String, String> personBaseMap = getPersonBaseInfo(personId);
+                // 基础信息
+                //人员分类
+                dataMap.put("N", personBaseMap.getOrDefault("clName", "0"));         // 员工类型(表格标题)
+                //定调薪单据-单据来源
+                Map<String, String> data = (Map<String, String>) PersonMap.get(personId);
+                dataMap.put("T", data.get("billSource"));       // 异动类型
+                //定调薪单据编码
+                dataMap.put("X", "SCY-R-HR-262-A/0");          // 编码
+                // 员工个人信息
+                dataMap.put("q", person.getName());            // 员工姓名
+                dataMap.put("w", person.getNumber());      // 工号
+                dataMap.put("e", AtsDateUtils.dateShortFormatToStr(person.getHireDate())); // 入职日期
+                //教育经历
+                dataMap.put("r", personBaseMap.getOrDefault("diplomaName", "0"));            // 学历
+                dataMap.put("t", personBaseMap.getOrDefault("caName", "0"));          // 管理类别
+
+                dataMap.put("y", personDep.getName());        // 所属组织
+                dataMap.put("u", primaryPosition.getName());          // 职位
+                dataMap.put("i", personBaseMap.getOrDefault("rankName", "0"));              // 职级
+                dataMap.put("I", personBaseMap.get("schemeName")+"制"); // 工资类型
+                Map<String, BigDecimal> adjustSalaryInfo = getAdjustSalaryInfo(personId);
+                // 工资结构
+                dataMap.put("A", adjustSalaryInfo.get(BASIC_SALARY).toString());  // 基本工资
+                dataMap.put("B", adjustSalaryInfo.get(OVERTIME_SALARY).toString());// 加班工资
+                dataMap.put("C", adjustSalaryInfo.get(SKILL_SALARY).toString());  // 技能工资
+                dataMap.put("J", adjustSalaryInfo.get(POST_ALLOWANCE).toString());  // 岗位补贴
+                dataMap.put("E", adjustSalaryInfo.get(EDU_ALLOWANCE).toString());  // 学历补贴
+                dataMap.put("G", adjustSalaryInfo.get(TOTAL_SALARY).toString()); // 月薪合计
+                dataMap.put("F", adjustSalaryInfo.get(EXPENSE_ALLOWANCE).toString());// 费用补贴
+                // 生效日期
+                dataMap.put("YYYYHHDD", data.get("stateDate"));
+                // 执行流程:替换占位符 → 转 PDF
+                batchReplaceWordPlaceholders(templatePath, pdfOutputPath, dataMap);
+//            convertWordToPdf(pdfOutputPath, pdfOutputPath);
+
+                File file = new File(pdfOutputPath);
+                byte[] fileBytes = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
+                files.put(person.getName() + "_定调薪套打.docx", fileBytes);
+            }
+            UserInfo currentUserInfo = ContextUtil.getCurrentUserInfo(ctx);
+            String downloadZipName = System.currentTimeMillis() + "print.zip";
+            String zipName = downloadZipName + "_" + MD5.md5Hash(currentUserInfo.getId().toString());
+            File userPathFile = new File(tempFilePath);
+            if (!userPathFile.exists()) {
+                userPathFile.mkdirs();
+            }
+            String zipPath = tempFilePath + File.separator + zipName;
+            AdvancedZipUtils.createZipFromMultipleFiles(files, zipPath);
+            Map<String, String> param = new HashMap<String, String>();
+            param.put("method", "tmp");
+            param.put("file", downloadZipName);
+            param.put("filename", "AdjustSalaryApplyPrint.zip");
+            String link = DynamicUtil.assembleUrl("/shr/downloadfile.do", param).replaceAll("\\+", "%20");
+            map.put("msgType", "1");
+            map.put("link", link);
+            map.put("msg", "下载成功");
+            // 可选:删除临时 Word 文件(如需保留可注释)
+//            File tempWordFile = new File(pdfOutputPath);
+//            if (tempWordFile.exists()) {
+//                tempWordFile.delete();
+//                System.out.println("临时 Word 文件已删除");
+//            }
+            JSONUtils.SUCCESS(map);
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.err.println("执行失败:" + e.getMessage());
+        }
+    }
+
+
+    public Map<String, BigDecimal> getAdjustSalaryInfo(String personId) {
+        // 1. 初始化Map,预设所有薪资项的默认值为"0"
+        Map<String, BigDecimal> salaryMap = new HashMap<>();
+        for (String code : SALARY_ITEM_CODES) {
+            salaryMap.put(code, BigDecimal.ZERO);
+        }
+        // 2. 构建参数化SQL(避免SQL注入)
+        StringBuilder sb = new StringBuilder();
+        sb.append("select salary.FMoney as money ,item.fname_l2 as name ,item.fnumber as number\n");
+        sb.append("from T_HR_SFixAdjustSalary salary\n");
+        sb.append("left join T_HR_SCmpItem item on item.fid = salary.FCmpItemID\n");
+        sb.append("where FPersonID = ? and FLeffectDay = ?");
+        String sql = sb.toString();
+        logger.error("getAdjustSalaryInfo--sql---" + sql);
+        Object[] param = new Object[]{personId, "2199-12-31 00:00:00"};
+        logger.error("getAdjustSalaryInfo--param---" + param);
+        // 3. 执行查询(使用参数化方式,自动关闭资源)
+        IRowSet iRowSet = null;
+        try {
+            // 假设DbUtil支持参数化查询,传入参数数组(替换原有的字符串拼接)
+            iRowSet = DbUtil.executeQuery(ctx, sql, param);
+            while (iRowSet.next()) {
+                String number = iRowSet.getString("number");
+                BigDecimal money = iRowSet.getBigDecimal("money").setScale(2, RoundingMode.HALF_UP);
+                // 4. 只更新存在的薪资项,不存在的保持默认值0
+                if (salaryMap.containsKey(number)) {
+                    // 处理money为空的情况,确保不会存入null
+                    salaryMap.put(number, money == null ? BigDecimal.ZERO : money);
+                }
+            }
+        } catch (SQLException | BOSException e) {
+            logger.error("查询薪资信息失败", e);
+            // 异常时返回默认值(所有项都是0)
+            return salaryMap;
+        } finally {
+            // 确保资源关闭(根据实际的IRowSet实现,添加关闭逻辑)
+            if (iRowSet != null) {
+                try {
+                    iRowSet.close();
+                } catch (SQLException e) {
+                    logger.error("关闭IRowSet失败", e);
+                }
+            }
+        }
+        return salaryMap;
+    }
+
+    /**
+     * 获取人员基本信息
+     *
+     * @param personId
+     */
+    public Map getPersonBaseInfo(String personId) throws BOSException, SQLException {
+        Map baseMap = new HashMap();
+        StringBuilder sb = new StringBuilder();
+        sb.append("").append("\n");
+        sb.append("select").append("\n");
+        sb.append("    salaryScheme.fname_l2 as schemeName,").append("\n");
+        sb.append("    rank.fname_l2 as rankName,").append("\n");
+        sb.append("    degree.diplomaName as diplomaName ,").append("\n");
+        sb.append("    ca.fname_l2 as caName,").append("\n");
+        sb.append("cl.fname_l2 as clName").append("\n");
+        sb.append("from").append("\n");
+        sb.append("    T_BD_person person").append("\n");
+        sb.append("    left join CT_MP_SalaryScheme salaryScheme on salaryScheme.fid = person.CFSalarySchemeID").append("\n");
+        sb.append("    left join (").append("\n");
+        sb.append("        select").append("\n");
+        sb.append("            FPERSONID,").append("\n");
+        sb.append("            jonGrade.fname_l2").append("\n");
+        sb.append("        from").append("\n");
+        sb.append("            T_HR_EmpPostRank rank").append("\n");
+        sb.append("            left join T_HR_JobGrade jonGrade on rank.FJOBGRADEID = jonGrade.fid").append("\n");
+        sb.append("        where").append("\n");
+        sb.append("            FPERSONID = '" + personId + "'").append("\n");
+        sb.append("            and FIsLatest = 1").append("\n");
+        sb.append("    ) rank on rank.FPERSONID = person.fid").append("\n");
+        sb.append("    left join (").append("\n");
+        sb.append("        select").append("\n");
+        sb.append("            degree.FPERSONID personId,").append("\n");
+        sb.append("            diploma.FNAME_l2 as diplomaName").append("\n");
+        sb.append("        from").append("\n");
+        sb.append("            T_HR_PersonDegree degree").append("\n");
+        sb.append("            left join T_BD_HRDiploma diploma on degree.FDiploma = diploma.fid").append("\n");
+        sb.append("        where").append("\n");
+        sb.append("            degree.fpersonid = '" + personId + "'").append("\n");
+        sb.append("            and FIsSingle = 1").append("\n");
+        sb.append("    ) degree on degree.personId = person.fid").append("\n");
+        sb.append("    left join CT_MP_ManageCa ca on ca.fid = person.CFManageCaID").append("\n");
+        sb.append("left join CT_MP_PersonnelCl cl on cl.fid = person.CFPersonnelClID").append("\n");
+        sb.append("where").append("\n");
+        sb.append("    person.fid = '" + personId + "'").append("\n");
+        logger.error("getPersonBaseInfo--sql---" + sb.toString());
+        IRowSet iRowSet = DbUtil.executeQuery(ctx, sb.toString());
+        while (iRowSet.next()) {
+            //工作类型
+            baseMap.put("schemeName", iRowSet.getString("schemeName"));
+            //职级
+            baseMap.put("rankName", iRowSet.getString("rankName"));
+            //学历
+            baseMap.put("diplomaName", iRowSet.getString("diplomaName"));
+            //人员分类
+            baseMap.put("clName", iRowSet.getString("clName"));
+            //管理类别
+            baseMap.put("caName", iRowSet.getString("caName"));
+        }
+        return baseMap;
+    }
+
+
+    /******
+     * 获取定调薪申请人员ID
+     * @param billId
+     * @return
+     */
+    public Map<String, Object> getAdjustSalaryApplyPersonIds(String billId) throws BOSException, SQLException {
+        Map<String, Object> map = new HashMap<String, Object>();
+        //套打人员ID
+        Set set = new HashSet();
+        //查询定调薪申请单
+        FilterInfo filterInfo = new FilterInfo();
+        FilterItemCollection filterItems = filterInfo.getFilterItems();
+        filterItems.add(new FilterItemInfo("id", AtsUtil.toSet(billId), CompareType.INCLUDE));
+        EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, null, null);
+        IAdjustSalaryApply iAdjustSalaryApply = AdjustSalaryApplyFactory.getLocalInstance(ctx);
+        AdjustSalaryApplyCollection adjustSalaryApplyCollection = iAdjustSalaryApply.getAdjustSalaryApplyCollection(entityViewInfo);
+        for (int i = 0; i < adjustSalaryApplyCollection.size(); i++) {
+            AdjustSalaryApplyInfo adjustSalaryApplyInfo = adjustSalaryApplyCollection.get(i);
+            String sql = "SELECT FPersonID as personId,FEffectDate as stateDate FROM T_HR_SAdjApplyEntry02cmp where  FBillID = '" + adjustSalaryApplyInfo.getId() + "'";
+            IRowSet iRowSet = DbUtil.executeQuery(ctx, sql);
+            while (iRowSet.next()) {
+                String personId = iRowSet.getString("personId");
+                Date stateDate = iRowSet.getDate("stateDate");
+                set.add(personId);
+                Map dataMap = new HashMap();
+                dataMap.put("billSource", adjustSalaryApplyInfo.getBillSource().getAlias());
+                dataMap.put("stateDate", DateTimeUtils.format(stateDate, "yyyy年hh月dd日"));
+                map.put(personId, dataMap);
+                map.put("personSet", set);
+            }
+        }
+        return map;
+    }
+
+
+    // -------------- 第一步:批量替换 Word 占位符 --------------
+    public static void batchReplaceWordPlaceholders(String templatePath, String tempWordPath, Map<String, String> dataMap) throws IOException {
+        FileInputStream fis = new FileInputStream(templatePath);
+        XWPFDocument document = new XWPFDocument(fis);
+
+        // 替换段落和表格中的占位符
+        replaceAllParagraphs(document, dataMap);
+        replaceAllTables(document, dataMap);
+
+        // 保存临时 Word 文档(替换后的 Word)
+        FileOutputStream fos = new FileOutputStream(tempWordPath);
+        document.write(fos);
+
+        // 关闭资源
+        fos.close();
+        document.close();
+        fis.close();
+        System.out.println("Word 占位符替换完成,临时文件:" + tempWordPath);
+    }
+
+    // 替换文档中所有段落的占位符
+    private static void replaceAllParagraphs(XWPFDocument document, Map<String, String> dataMap) {
+        for (XWPFParagraph para : document.getParagraphs()) {
+            replacePlaceholdersInParagraph(para, dataMap);
+        }
+    }
+
+    // 替换文档中所有表格的占位符
+    private static void replaceAllTables(XWPFDocument document, Map<String, String> dataMap) {
+        for (XWPFTable table : document.getTables()) {
+            for (XWPFTableRow row : table.getRows()) {
+                for (XWPFTableCell cell : row.getTableCells()) {
+                    for (XWPFParagraph para : cell.getParagraphs()) {
+                        replacePlaceholdersInParagraph(para, dataMap);
+                    }
+                }
+            }
+        }
+    }
+
+    // 替换单个段落中的所有占位符
+    private static void replacePlaceholdersInParagraph(XWPFParagraph para, Map<String, String> dataMap) {
+        List<XWPFRun> runs = para.getRuns();
+        if (runs == null || runs.isEmpty()) return;
+
+        // 拼接段落文本
+        StringBuilder paraText = new StringBuilder();
+        for (XWPFRun run : runs) {
+            String text = run.getText(0);
+            if (text != null) paraText.append(text);
+        }
+
+        String original = paraText.toString();
+        String replaced = original;
+
+        // 批量替换所有占位符
+        for (Map.Entry<String, String> entry : dataMap.entrySet()) {
+            replaced = replaced.replace(entry.getKey(), entry.getValue());
+        }
+
+        // 更新段落内容(保留格式)
+        if (!replaced.equals(original)) {
+            for (XWPFRun run : runs) run.setText("", 0);
+            runs.get(0).setText(replaced, 0);
+        }
+    }
+
+    // -------------- 第二步:Word 转 PDF --------------
+//    public static void convertWordToPdf(String wordPath, String pdfPath) throws Exception {
+//        FileInputStream fis = new FileInputStream(pdfPath);
+//        // 加载 Word 文档
+//        com.aspose.words.Document doc = new com.aspose.words.Document();
+//        // 配置 PDF 保存选项(可选,优化格式)
+//        PdfSaveOptions saveOptions = new PdfSaveOptions();
+//        saveOptions.setCompliance(PdfCompliance.PDF_A_1_B); // 兼容 PDF 标准
+//        saveOptions.setExportGeneratorName(true); // 保留页眉页脚
+//        // 保存为 PDF
+//        doc.save(pdfPath, saveOptions);
+//        System.out.println("PDF 转换完成,输出文件:" + pdfPath);
+//    }
+
+    /**
+     * 9.9版本 下载url
+     *
+     * @param ctx
+     * @param realFileName
+     * @return
+     */
+    public static String getEncryRealFileName(Context ctx, String realFileName) {
+        UserInfo currentUserInfo = ContextUtil.getCurrentUserInfo(ctx);
+        return MessageFormat.format("{0}_{1}", realFileName, MD5.md5Hash(currentUserInfo.getId().toString()));
+    }
+    // -------------- 测试方法(一站式执行)--------------
+//    public static void main(String[] args) {
+//        // 1. 配置文件路径
+//        String templatePath = "F:\\test/定调薪套打模板.docx"; // 原模板路径
+//        String pdfOutputPath = "F:\\test/替换后的薪酬核定表PDF.pdf"; // 输出路径
+//        // 2. 定义占位符-实际数据映射(同之前方案,可动态获取)
+//        Map<String, String> dataMap = new HashMap<>();
+//        // 基础信息
+//        dataMap.put("T", "平级调薪");       // 异动类型
+//        dataMap.put("X", "45602");          // 编码
+//        dataMap.put("N", "技术岗");         // 员工类型(表格标题)
+//        // 员工个人信息
+//        dataMap.put("q", "李四");            // 员工姓名
+//        dataMap.put("w", "EMP2024002");      // 工号
+//        dataMap.put("e", "2024-02-20");      // 入职日期
+//        dataMap.put("r", "大专");            // 学历
+//        dataMap.put("t", "管理岗");          // 管理类别
+//        dataMap.put("y", "研发二部");        // 所属组织
+//        dataMap.put("u", "工程师");          // 职位
+//        dataMap.put("i", "P4");              // 职级
+//        // 工资结构
+//        dataMap.put("A", "4000");            // 基本工资
+//        dataMap.put("B", "1500");            // 加班工资
+//        dataMap.put("C", "900");             // 技能工资
+//        dataMap.put("J", "600");             // 岗位补贴
+//        dataMap.put("E", "350");             // 学历补贴
+//        dataMap.put("G", "10000");          // 月薪合计
+//        dataMap.put("I", "月薪制");          // 工资类型
+//        dataMap.put("F", "月薪制");          // 费用补贴
+//        // 生效日期
+//        dataMap.put("YYYYHHDD", "2024年08月15日");
+//        try {
+//            // 执行流程:替换占位符 → 转 PDF
+//            batchReplaceWordPlaceholders(templatePath, pdfOutputPath, dataMap);
+//            convertWordToPdf(pdfOutputPath, pdfOutputPath);
+//
+//            // 可选:删除临时 Word 文件(如需保留可注释)
+////            File tempWordFile = new File(pdfOutputPath);
+////            if (tempWordFile.exists()) {
+////                tempWordFile.delete();
+////                System.out.println("临时 Word 文件已删除");
+////            }
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//            System.err.println("执行失败:" + e.getMessage());
+//        }
+//    }
+}

+ 145 - 0
websrc/com/kingdee/eas/shr/compensation/web/handler/integrate/BatchSubmitShemeBillListHandlerEx.java

@@ -0,0 +1,145 @@
+package com.kingdee.shr.compensation.web.handler.integrate;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
+import com.kingdee.bos.metadata.entity.EntityViewInfo;
+import com.kingdee.bos.metadata.entity.FilterInfo;
+import com.kingdee.bos.metadata.entity.FilterItemCollection;
+import com.kingdee.bos.metadata.entity.FilterItemInfo;
+import com.kingdee.bos.util.BOSUuid;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.csinterface.biz.util.DBUtils;
+import com.kingdee.eas.hr.base.HRBillStateEnum;
+import com.kingdee.eas.hr.base.IRewardPunishType;
+import com.kingdee.eas.hr.base.RewardPunishTypeFactory;
+import com.kingdee.eas.hr.base.RewardPunishTypeInfo;
+import com.kingdee.eas.hr.emp.IPersonRewardPunish;
+import com.kingdee.eas.hr.emp.PersonRewardPunishCollection;
+import com.kingdee.eas.hr.emp.PersonRewardPunishFactory;
+import com.kingdee.eas.hr.emp.PersonRewardPunishInfo;
+import com.kingdee.eas.hr.state.IRewardPunishLevel;
+import com.kingdee.eas.hr.state.RewardPunishLevelFactory;
+import com.kingdee.eas.hr.state.RewardPunishLevelInfo;
+import com.kingdee.eas.util.app.ContextUtil;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.jdbc.rowset.IRowSet;
+import com.kingdee.shr.base.syssetting.context.SHRContext;
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
+import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
+import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
+import com.kingdee.shr.compensation.app.integrate.*;
+import com.kingdee.shr.compensation.app.integrate.multiinspire.StandingBookFacadeFactory;
+import com.kingdee.shr.compensation.util.integrate.CmpIntegrateEntryExtHelper;
+import com.kingdee.shr.compensation.util.integrate.CmpIntegrateUtils;
+import com.kingdee.shr.compensation.web.handler.integrate.helper.CmpIntegrateWebHelper;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.ui.ModelMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+
+/**
+ * @Title: BatchSubmitShemeBillListHandlerEx
+ * @Author 青梧
+ * @Package com.kingdee.shr.compensation.web.handler.integrate
+ * @Date 2026/1/12 13:59
+ * @description: 反审批撤回奖惩信息
+ */
+public class BatchSubmitShemeBillListHandlerEx extends BatchSubmitShemeBillListHandler {
+
+    public void antiApprovalAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
+        String billId = this.getBillId(request);
+        if (!StringUtils.isEmpty(billId)) {
+            Context ctx = SHRContext.getInstance().getContext();
+            BatchSubmitShemeBillInfo info = CmpIntegrateWebHelper.getBatchSubmitShemeBillInfo(ctx, "where id = '" + billId + "'");
+            info.setLastUpdateUser(ContextUtil.getCurrentUserInfo(ctx));
+            String submitSchemeId = info.getSubmitScheme().getId().toString();
+            String calShemeTableName = CmpIntegrateWebHelper.getEntryTableName(ctx, submitSchemeId);
+            this.checkBillIsLegalForDelete(ctx, calShemeTableName, billId);
+            if (this.isCycleScheme(ctx, submitSchemeId)) {
+                this.antiApprovalControl(ctx, submitSchemeId, calShemeTableName, billId);
+            }
+
+            try {
+                BatchSubmitShemeBillInfo billInfo = new BatchSubmitShemeBillInfo();
+                billInfo.setId(BOSUuid.read(billId));
+                this.callDeductOfSubmitScheme(ctx, billInfo);
+                CmpIntegrateUtils.updateEntryBillState(ctx, billId, HRBillStateEnum.SAVED, calShemeTableName);
+                String updateBillSql = "update T_HR_SBatchSubmitShemeBill set FAUDITORID='',FBillState=?,FLastUpdateTime=? where fid=?";
+                Object[] param = new Object[]{HRBillStateEnum.SAVED.getValue(), new Timestamp(System.currentTimeMillis()), billId};
+                DbUtil.execute(ctx, updateBillSql, param);
+                CmpIntegrateEntryExtHelper.convertExchangeRateAndSaveEntryExtInSpireBill(ctx, billId, HRBillStateEnum.SAVED);
+                StandingBookFacadeFactory.getLocalInstance(ctx).statistics(billId);
+                this.reverseJob(ctx, billId);
+                this.deleteCjjbInfo(ctx, info);
+            } catch (Exception e) {
+                throw new ShrWebBizException(e.getMessage(), e);
+            }
+            JSONUtils.SUCCESS(billId);
+        }
+    }
+
+    /**
+     * 删除奖惩记录
+     *
+     * @param info
+     */
+    public void deleteCjjbInfo(Context ctx, BatchSubmitShemeBillInfo info) throws BOSException, EASBizException, SQLException {
+
+        BatchSubmitShemeBillEntryCollection entry = info.getEntry();
+        IPersonRewardPunish iPersonRewardPunish = PersonRewardPunishFactory.getLocalInstance(ctx);
+        //奖惩类型
+        IRewardPunishType iRewardPunishType = RewardPunishTypeFactory.getLocalInstance(ctx);
+        //奖惩级别
+        IRewardPunishLevel iRewardPunishLevel = RewardPunishLevelFactory.getLocalInstance(ctx);
+        //提报方案
+        CalSubmitSchemeInfo submitScheme = info.getSubmitScheme();
+        ICalSubmitScheme iCalSubmitScheme = CalSubmitSchemeFactory.getLocalInstance(ctx);
+        CalSubmitSchemeInfo calSubmitSchemeInfo = iCalSubmitScheme.getCalSubmitSchemeInfo(new ObjectUuidPK(submitScheme.getId()));
+        for (int i = 0; i < entry.size(); i++) {
+            BatchSubmitShemeBillEntryInfo batchSubmitShemeBillEntryInfo = entry.get(i);
+            FilterInfo filterInfo = new FilterInfo();
+            FilterItemCollection filterItems = filterInfo.getFilterItems();
+            filterItems.add(new FilterItemInfo("person", batchSubmitShemeBillEntryInfo.getPerson().getId()));
+            //奖惩类型
+            if (calSubmitSchemeInfo.getNumber().equals("scy20")) {
+                RewardPunishTypeInfo rewardPunishTypeInfo = iRewardPunishType.getRewardPunishTypeInfo("where number = '01'");
+                filterItems.add(new FilterItemInfo("type.id", rewardPunishTypeInfo.getId()));
+                //奖惩级别
+                String jlId = info.getObjectValue("jl").get("id").toString();
+                String jlSql = "select fnumber as number from CT_MP_Jljb where fid ='" + jlId + "'";
+                IRowSet iRowSet = DBUtils.executeQuery(ctx, jlSql);
+                if (iRowSet.next()) {
+                    String number = iRowSet.getString("number");
+                    RewardPunishLevelInfo rewardPunishLevelInfo = iRewardPunishLevel.getRewardPunishLevelInfo("where number = '" + number + "'");
+                    filterItems.add(new FilterItemInfo("rPLevel", rewardPunishLevelInfo.getId()));
+                }
+            }
+            if (calSubmitSchemeInfo.getNumber().equals("scy09")) {
+                RewardPunishTypeInfo rewardPunishTypeInfo = iRewardPunishType.getRewardPunishTypeInfo("where number = '02'");
+                filterItems.add(new FilterItemInfo("type.id", rewardPunishTypeInfo.getId()));
+                //奖惩级别
+                String cjId = info.getObjectValue("cj").get("id").toString();
+                String cjSql = "select fnumber as number from CT_MP_Cjjb where fid ='" + cjId + "'";
+                IRowSet iRowSet = DBUtils.executeQuery(ctx, cjSql);
+                if (iRowSet.next()) {
+                    String number = iRowSet.getString("number");
+                    RewardPunishLevelInfo rewardPunishLevelInfo = iRewardPunishLevel.getRewardPunishLevelInfo("where number = '" + number + "'");
+                    filterItems.add(new FilterItemInfo("rPLevel", rewardPunishLevelInfo.getId()));
+                }
+            }
+            //奖罚时间
+            filterItems.add(new FilterItemInfo("occurDate", batchSubmitShemeBillEntryInfo.getEffectDate()));
+            EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, null, null);
+            PersonRewardPunishCollection personRewardPunishCollection = iPersonRewardPunish.getPersonRewardPunishCollection(entityViewInfo);
+            for (int j = 0; j < personRewardPunishCollection.size(); j++) {
+                PersonRewardPunishInfo personRewardPunishInfo = personRewardPunishCollection.get(j);
+                iPersonRewardPunish.delete(new ObjectUuidPK(personRewardPunishInfo.getId().toString()));
+            }
+        }
+    }
+
+}