package com.kingdee.customer.salary.handler; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.SQLException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.springframework.ui.ModelMap; 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.eas.common.EASBizException; import com.kingdee.eas.custom.bill.salary.ISalaryBag; import com.kingdee.eas.custom.bill.salary.SalaryBagEntryCollection; import com.kingdee.eas.custom.bill.salary.SalaryBagEntryInfo; import com.kingdee.eas.custom.bill.salary.SalaryBagFactory; import com.kingdee.eas.custom.bill.salary.SalaryBagInfo; import com.kingdee.eas.framework.CoreBaseInfo; import com.kingdee.eas.hr.affair.EmpEnrollBizBillEntryInfo; import com.kingdee.eas.hr.base.HRBillStateEnum; import com.kingdee.eas.util.app.DbUtil; import com.kingdee.jdbc.rowset.IRowSet; import com.kingdee.shr.base.syssetting.app.io.fileImport.ImportException; 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.util.MetaDataUtil; import com.kingdee.shr.base.syssetting.web.handler.EditHandler; import com.kingdee.shr.base.syssetting.web.json.JSONUtils; import com.kingdee.shr.compensation.CmpItemInfo; /** * 工资包编辑处理器 * @author issuser * */ public class SalaryBag2EditHandler extends EditHandler { private static Logger logger = Logger.getLogger("com.kingdee.customer.salary.handler.SalaryBagEditHandler"); /** * 生成工资包的数据明细 * @param request HTTP请求对象,包含前端传来的工资包信息 * @param response HTTP响应对象,用于向前端返回结果 * @param modelMap ModelMap对象,用于在请求处理过程中传递数据 */ public void createEntryDetailAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) { // 从HTTP请求中获取开始日期、结束日期、补发日期、总金额、工资包ID等参数 String startDateStr = request.getParameter("startDate"); String endDateStr = request.getParameter("endDate"); String reissueDateStr = request.getParameter("reissueDate"); String money = request.getParameter("money"); String billId = request.getParameter("billId"); // 获取业务上下文 Context ctx = SHRContext.getInstance().getContext(); try { // 构建查询SQL语句,用于获取指定工资包ID的相关信息 String selectSql = "SELECT b.fid as personId,b.FNAME_l2 as personName," + " c.FID as cmpItemId ,c.FNAME_l2 as cmpItemName,a.CFPaycurrency,a.CFendDate " + " FROM CT_SAL_SalaryBag a " + " left join t_bd_person b on a.CFPersonID = b.FID " + " left join T_HR_SCmpItem c on a.CFCmpItemID = c.fid " + " where a.fid = '" + billId + "'"; System.out.println("工资包变更sql=========" + selectSql); // 执行查询操作 IRowSet rs = DbUtil.executeQuery(ctx, selectSql.toString()); String cmpItemId = null; String cmpItemName = null; String paycurrency = null; Date soureEndDate = null; if (rs.next()) { // 从查询结果中取出相关信息 cmpItemId = rs.getString("cmpItemId"); cmpItemName = rs.getString("cmpItemName"); paycurrency = rs.getString("CFPaycurrency"); soureEndDate = rs.getDate("CFendDate"); } // 创建日期格式化对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 解析前端传来的结束日期和补发日期 Date endDate = sdf.parse(endDateStr); Date reissueDate = sdf.parse(reissueDateStr); // 验证结束日期是否早于原始文档的过期日期 if (soureEndDate.after(endDate)) { throw new ImportException("新的过期日期不能早于原始文档的过期日期"); } // 获取月份明细列表,即从开始日期到结束日期之间的所有月份 List monthList = getMonthDetail(startDateStr, endDateStr); System.out.println("月份=========" + monthList.size()); // 创建结果列表,用于存储每个月份的工资包明细 List> resultList = new ArrayList>(); // 创建总金额对象,并将其转换为BigDecimal类型 BigDecimal moneyAmount = new BigDecimal(money); // 设置保留的小数位数为两位,并根据金额大小选择合适的取整模式 int scale = 2; // 保留两位小数 RoundingMode roundingMode = (moneyAmount.compareTo(BigDecimal.ZERO) < 0) ? RoundingMode.HALF_DOWN // 负数时向下取整 : RoundingMode.HALF_UP; // 正数时四舍五入 // 计算平均分配到每个月的金额 BigDecimal avgAmount = moneyAmount.divide(BigDecimal.valueOf(monthList.size()), scale, roundingMode); // 初始化已生成额度的金额和补发月应发金额 BigDecimal remainder = new BigDecimal(0); BigDecimal amountPayable = new BigDecimal(0); // 遍历每个月份,生成相应的工资包明细 for (int i = 0; i < monthList.size(); i++) { Map entryMap = new HashMap(); // 获取当前月份 Date months = monthList.get(i); // 将月份信息和其他相关数据放入entryMap中 entryMap.put("months", months); entryMap.put("paycurrency", paycurrency); entryMap.put("cmpItemId", cmpItemId); entryMap.put("cmpItemName", cmpItemName); // 如果不是最后一个月,则将平均金额加到已生成额度的金额中 if (monthList.size() - i > 1) { remainder = remainder.add(avgAmount); } else { // 如果是最后一个月,则计算最后一个月的实际金额 avgAmount = moneyAmount.subtract(remainder); } // 将平均金额放入entryMap中 entryMap.put("moneys", avgAmount); // 获取变更前的金额 BigDecimal beforeAmount = getBeforeAmount(billId, sdf.format(months)); // 将变更前的金额放入entryMap中 entryMap.put("beforeAmount", beforeAmount); // 根据当前月份与补发日期的关系,计算应发金额和补发金额 if (monthList.get(i).equals(reissueDate)) { // 如果当前月份等于补发日期,不应发补发金额,应发金额为平均金额 entryMap.put("reissueAmount", 0); entryMap.put("amountPayable", amountPayable.add(avgAmount)); } else if (monthList.get(i).after(reissueDate)) { // 如果当前月份晚于补发日期,不应发补发金额,应发金额为平均金额 entryMap.put("amountPayable", avgAmount); entryMap.put("reissueAmount", 0); } else { // 如果当前月份早于补发日期,应发金额为0,补发金额为平均金额减去变更前金额 entryMap.put("amountPayable", 0); entryMap.put("reissueAmount", avgAmount.subtract(beforeAmount)); // 更新总应发差额 amountPayable = amountPayable.add(avgAmount.subtract(beforeAmount)); } // 输出当前月份的工资包明细 System.out.println("月份result=========" + entryMap); // 将entryMap添加到结果列表中 resultList.add(entryMap); } // 将结果列表以JSON格式写入HTTP响应中,返回给前端 JSONUtils.writeJson(response, resultList); } catch (BOSException e) { // 捕获并打印业务异常信息 e.printStackTrace(); } catch (ParseException e) { // 捕获并打印日期解析异常信息 e.printStackTrace(); } catch (SHRWebException e) { // 捕获并打印Web异常信息 e.printStackTrace(); } catch (SQLException e) { // 捕获并打印SQL异常信息 e.printStackTrace(); } } /** * 获取指定工资包ID和月份的变更前金额 * @param billId 工资包ID * @param months 指定月份 * @return 变更前的金额 * @throws BOSException 业务异常 * @throws SQLException SQL异常 */ private BigDecimal getBeforeAmount(String billId, String months) throws BOSException, SQLException { // 获取业务上下文 Context ctx = SHRContext.getInstance().getContext(); // 初始化变更前的金额为0 BigDecimal beforeAmount = new BigDecimal(0); // 构建查询SQL语句,用于获取指定工资包ID和月份的变更前金额 String selectSql = "SELECT CFMoneys FROM CT_SAL_SalaryBagEntry where FBillID = '" + billId + "' and to_char(CFMonths,'yyyy-MM-dd') = '" + months + "'"; System.out.println("查找变更前金额=========" + selectSql); // 执行查询操作 IRowSet rs = DbUtil.executeQuery(ctx, selectSql.toString()); if (rs.next()) { // 从查询结果中取出变更前的金额 beforeAmount = rs.getBigDecimal("CFMoneys"); } // 返回变更前的金额 return beforeAmount; } /** * 根据开始日期和结束日期,生成月份明细列表 * @param startDateStr 开始日期字符串 * @param endDateStr 结束日期字符串 * @return 月份明细列表 * @throws ParseException 日期解析异常 */ private List getMonthDetail(String startDateStr, String endDateStr) throws ParseException { // 创建日期格式化对象,只提取年月信息 SimpleDateFormat sdfMonth = new SimpleDateFormat("yyyy-MM"); // 解析开始日期和结束日期 Date startDate = sdfMonth.parse(startDateStr); Date endDate = sdfMonth.parse(endDateStr); Date currentDate = startDate; // 创建月份列表 List monthList = new ArrayList(); // 创建Calendar实例,用于月份计算 Calendar calendar = Calendar.getInstance(); // 当前日期小于等于结束日期时,继续循环 while (endDate.after(currentDate) || currentDate.equals(endDate)) { // 将当前日期添加到月份列表中 monthList.add(currentDate); // 设置Calendar的时间为当前日期 calendar.setTime(currentDate); // 将Calendar的时间增加一个月 calendar.add(Calendar.MONTH, 1); // 更新当前日期为增加一个月后的日期 currentDate = calendar.getTime(); } // 返回月份明细列表 return monthList; } }