package com.changhong.epc.form.service.budget.tool.impl; import com.changhong.epc.bean.form.FormType; import com.changhong.epc.bean.form.budget.PersionBackMoney; import com.changhong.epc.bean.tenant.cost.CostFromMapping; import com.changhong.epc.bean.tenant.system.SystemForm; import com.changhong.epc.constter.base.BaseConst; import com.changhong.epc.form.mapper.tenant.FormDataMapper; import com.changhong.epc.form.mapper.tenant.log.PersionBackMoneyMapper; import com.changhong.epc.form.service.budget.impl.GetConstant; import com.changhong.epc.form.service.budget.tool.UpdateBudgetFactory; import com.changhong.epc.form.service.budget.tool.entity.UpdateBudgetEntity; import com.changhong.epc.form.service.field.FormFieldService; import com.codingapi.tx.annotation.TxTransaction; import com.iemsoft.framework.cloud.core.thread.Keys; import com.iemsoft.framework.cloud.core.thread.ThreadData; import com.iemsoft.framework.cloud.core.tools.Assert; import com.iemsoft.framework.cloud.core.tools.JSONTool; import com.iemsoft.framework.cloud.core.tools.ObjectUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.ModelMap; import javax.annotation.Resource; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; /** * 报销扣减预算 */ @Service(UpdateBudgetFactory.BX_TYPE) @Slf4j @Scope("prototype") public class ExpendBudgetUpdate extends AbstractUpdateBudget implements BaseConst { private UpdateBudgetEntity applyEntity; private Map applyInfo; // 主表数据集合 private Map expendInfo; private Map budgetChildInfo; private double budgetMoney; @Resource private PersionBackMoneyMapper persionBackMoneyMapper; @Resource private FormDataMapper formDataMapper; @Resource(name = "formFieldService") private FormFieldService formFieldService; // 子表单后缀 private static String PAYINFO = "_payinfo"; // 本次报销数据集合 private List> list; // 对应报销人的借款记录 private List> borrowList; //判断是否有子表单 private Integer count; @Override public void checkBudget(UpdateBudgetEntity updateBudgetEntity) { this.expendInfo = getFormInfo(updateBudgetEntity); this.applyEntity = getApplyInfo( NumberUtils.createInteger(Objects.toString(this.expendInfo.get(EXPEND_COST_TYPE), "0"))); if (this.applyEntity == null) { // 报销-预算 Integer budgetId = getParentId(this.expendInfo); if (budgetId == null) { log.warn("{}, 关联预算单id为空!", updateBudgetEntity); return; } addLock(budgetId); this.budgetChildInfo = getFormInfo(getFormId(SystemForm.BUDGET_FORM_ID), BUDGET_SUB_FROM, budgetId); Assert.condition(budgetChildInfo == null, BUDGET_INVALID); if (this.expendInfo.get(EXPEND_USE_MONEY) == null || this.budgetChildInfo.get(BUDGET_ITEM_BALANCE) == null) { log.warn("{}, 报销金额:{}, 预算余额:{}" , updateBudgetEntity , this.expendInfo.get(EXPEND_USE_MONEY) , this.budgetChildInfo.get(BUDGET_ITEM_BALANCE)); return; } this.budgetMoney = toDouble(this.budgetChildInfo.get(BUDGET_ITEM_BALANCE)) - toDouble(this.expendInfo.get(EXPEND_USE_MONEY)); Assert.condition(this.budgetMoney < 0, BUDGET_MONEY_NOT_ENOUGH); } else { // 报销-申请-预算 Integer applyId = getParentId(this.expendInfo); if (applyId == null) { log.warn("{}, 关联申请单id为空!", updateBudgetEntity); return; } this.applyEntity.setDataRowNum(applyId); this.applyInfo = getFormInfo(this.applyEntity); Assert.condition(applyInfo == null, APPLY_INVALID); Integer budgetId = getParentId(this.applyInfo); if (budgetId == null) { log.warn("{}, 关联预算单id为空!", updateBudgetEntity); return; } addLock(budgetId); this.budgetChildInfo = getFormInfo(getFormId(SystemForm.BUDGET_FORM_ID), BUDGET_SUB_FROM, budgetId); Assert.condition(budgetChildInfo == null, BUDGET_INVALID); if (this.expendInfo.get(EXPEND_USE_MONEY) == null || this.budgetChildInfo.get(BUDGET_ITEM_BALANCE) == null || this.applyInfo.get(APPLY_USE_MONEY) == null) { log.warn("{}, 报销金额:{}, 预算余额:{}, 申请金额:{}" , updateBudgetEntity , this.expendInfo.get(EXPEND_USE_MONEY) , this.budgetChildInfo.get(BUDGET_ITEM_BALANCE) , this.applyInfo.get(APPLY_USE_MONEY)); return; } Assert.condition((this.budgetMoney = (toDouble(this.budgetChildInfo.get(BUDGET_ITEM_BALANCE)) + toDouble(this.applyInfo.get(APPLY_USE_MONEY)) - toDouble(this.expendInfo.get(EXPEND_USE_MONEY)))) < 0, BUDGET_MONEY_NOT_ENOUGH); //申请状态回写,只能被占用一次 updateData(this.applyEntity.getFormId(), null , this.applyEntity.getDataRowNum() , new ModelMap(PROCESS_FLAG, 1)); } String childForm = updateBudgetEntity.getFormId() + PAYINFO; count = formDataMapper.selectTableExist(childForm); //如果有子表单 if (count > 0) { // 判断金额是否合适 // 冲抵金额 Double money = this.persionMoney(updateBudgetEntity); // 借款金额 Double borowMoney = this.allBorrowMoney(); //如果冲抵金额大于0,并且借款金额等于0或者冲抵金额大于了借款金额报错 if (money > 0) { log.debug("本次冲抵金额为:" + money.toString()); Assert.condition(BigDecimal.valueOf(borowMoney).compareTo(BigDecimal.valueOf(0)) == 0 || money > borowMoney, PERSION_COST_OUT); } } } @Override @TxTransaction @Transactional public void updateBudget(UpdateBudgetEntity updateBudgetEntity) { super.updateBudget(updateBudgetEntity); checkBudget(updateBudgetEntity); if (ObjectUtil.empty(this.budgetChildInfo) || this.expendInfo.get(EXPEND_USE_MONEY) == null || this.budgetChildInfo.get(BUDGET_ITEM_BALANCE) == null || (this.applyInfo != null && this.applyInfo.get(APPLY_USE_MONEY) == null)) { // account(updateBudgetEntity.getFormId(), ThreadData.get(Keys.TENANT_ID), Objects.toString(updateBudgetEntity.getDataRowNum(), "")); return; } checkMoney(this.budgetMoney); if (ObjectUtil.empty(applyInfo)) { addBudgetLogMoney(this.budgetChildInfo, budgetMoney, updateBudgetEntity.getFormId(), this.expendInfo, toDouble(expendInfo.get(EXPEND_USE_MONEY))); } else { addBudgetLogMoney(this.budgetChildInfo, budgetMoney , updateBudgetEntity.getFormId(), this.expendInfo, toDouble(expendInfo.get(EXPEND_USE_MONEY)) , applyEntity.getFormId(), this.applyInfo, toDouble(this.applyInfo.get(APPLY_USE_MONEY))); //回写借款金额 Object amountMoney = this.expendInfo.get(AMOUNTREPAYMENTS); log.debug("当前报销单:" + JSONTool.toJson(this.expendInfo)); log.debug("还款金额为:" + amountMoney); if (amountMoney != null && !Objects.equals("", amountMoney)) { log.debug("报销还款金额回写-------->"); updateData(applyEntity.getFormId(), null, applyEntity.getDataRowNum() , new ModelMap(ALREADYREPAID, amountMoney)); } } //formatDouble(formBaseEntity); updateData(getFormId(SystemForm.BUDGET_FORM_ID), BUDGET_SUB_FROM, getDataRowNum(this.budgetChildInfo), new ModelMap(BUDGET_ITEM_BALANCE, format(this.budgetMoney, getFormBase(getFormId(SystemForm.BUDGET_FORM_ID)), BUDGET_ITEM_BALANCE))); } @Override public void flowAfterCall(UpdateBudgetEntity updateBudgetEntity) { this.expendInfo = getFormInfo(updateBudgetEntity); this.applyEntity = getApplyInfo( NumberUtils.createInteger(Objects.toString(this.expendInfo.get(EXPEND_COST_TYPE), "0"))); if (this.applyEntity == null) { // 报销-预算 Integer budgetId = getParentId(this.expendInfo); if (budgetId == null) { return; } delLock(budgetId); } else { // 报销-申请-预算 Integer applyId = getParentId(this.expendInfo); if (applyId == null) { return; } this.applyEntity.setDataRowNum(applyId); this.applyInfo = getFormInfo(this.applyEntity); Integer budgetId = getParentId(this.applyInfo); if (budgetId == null) { return; } delLock(budgetId); } account(updateBudgetEntity.getFormId(), ThreadData.get(Keys.TENANT_ID), Objects.toString(updateBudgetEntity.getDataRowNum(), "")); // 调用报销单个人冲抵的方法判断 this.getPersionCostById(updateBudgetEntity); } @Override public void rollback(UpdateBudgetEntity updateBudgetEntity) { super.rollback(updateBudgetEntity); this.expendInfo = getFormInfo(updateBudgetEntity); this.applyEntity = getApplyInfo( NumberUtils.createInteger(Objects.toString(this.expendInfo.get(EXPEND_COST_TYPE), "0"))); if (this.applyEntity == null) { // 报销-预算 Integer budgetId = getParentId(this.expendInfo); if (budgetId == null) { log.warn("{}, 关联预算单id为空!", updateBudgetEntity); return; } addLock(budgetId); this.budgetChildInfo = getFormInfo(getFormId(SystemForm.BUDGET_FORM_ID), BUDGET_SUB_FROM, budgetId); Assert.condition(budgetChildInfo == null, BUDGET_INVALID); if (this.expendInfo.get(EXPEND_USE_MONEY) == null || this.budgetChildInfo.get(BUDGET_ITEM_BALANCE) == null) { log.warn("{}, 报销金额:{}, 预算余额:{}" , updateBudgetEntity , this.expendInfo.get(EXPEND_USE_MONEY) , this.budgetChildInfo.get(BUDGET_ITEM_BALANCE)); return; } this.budgetMoney = toDouble(this.budgetChildInfo.get(BUDGET_ITEM_BALANCE)) + toDouble(this.expendInfo.get(EXPEND_USE_MONEY)); addBudgetLogMoney(this.budgetChildInfo, budgetMoney, updateBudgetEntity.getFormId(), this.expendInfo, toDouble(expendInfo.get(EXPEND_USE_MONEY))); } else { // 报销-申请-预算 Integer applyId = getParentId(this.expendInfo); if (applyId == null) { log.warn("{}, 关联申请单id为空!", updateBudgetEntity); return; } this.applyEntity.setDataRowNum(applyId); this.applyInfo = getFormInfo(this.applyEntity); Assert.condition(applyInfo == null, APPLY_INVALID); Integer budgetId = getParentId(this.applyInfo); if (budgetId == null) { log.warn("{}, 关联预算单id为空!", updateBudgetEntity); return; } addLock(budgetId); this.budgetChildInfo = getFormInfo(getFormId(SystemForm.BUDGET_FORM_ID), BUDGET_SUB_FROM, budgetId); Assert.condition(budgetChildInfo == null, BUDGET_INVALID); if (this.expendInfo.get(EXPEND_USE_MONEY) == null || this.budgetChildInfo.get(BUDGET_ITEM_BALANCE) == null || this.applyInfo.get(APPLY_USE_MONEY) == null) { log.warn("{}, 报销金额:{}, 预算余额:{}, 申请金额:{}" , updateBudgetEntity , this.expendInfo.get(EXPEND_USE_MONEY) , this.budgetChildInfo.get(BUDGET_ITEM_BALANCE) , this.applyInfo.get(APPLY_USE_MONEY)); return; } this.budgetMoney = (toDouble(this.budgetChildInfo.get(BUDGET_ITEM_BALANCE)) - toDouble(this.expendInfo.get(EXPEND_USE_MONEY)) + toDouble(this.applyInfo.get(APPLY_USE_MONEY))); addBudgetLogMoney(this.budgetChildInfo, budgetMoney , updateBudgetEntity.getFormId(), this.expendInfo, toDouble(expendInfo.get(EXPEND_USE_MONEY)) , applyEntity.getFormId(), this.applyInfo, toDouble(this.applyInfo.get(APPLY_USE_MONEY))); //回写借款金额 Object amountMoney = this.expendInfo.get(AMOUNTREPAYMENTS); // log.debug("当前报销单:"+ JSONTool.toJson(this.expendInfo)); // log.debug("还款金额为:"+amountMoney); if (amountMoney != null && !Objects.equals("", amountMoney)) { // log.debug("报销还款金额回写-------->"); updateData(applyEntity.getFormId(), null, applyEntity.getDataRowNum() , new ModelMap(ALREADYREPAID, 0)); // ,new ModelMap(ALREADYREPAID,amountMoney)); } } updateData(getFormId(SystemForm.BUDGET_FORM_ID), BUDGET_SUB_FROM, getDataRowNum(this.budgetChildInfo), new ModelMap(BUDGET_ITEM_BALANCE, format(this.budgetMoney, getFormBase(getFormId(SystemForm.BUDGET_FORM_ID)), BUDGET_ITEM_BALANCE))); } @Override public FormType getFormType() { return FormType.BX; } public UpdateBudgetEntity getApplyInfo(Integer cType) { String formId = null; for (CostFromMapping costFromMapping : this.costFromMappings) { if (Objects.equals(costFromMapping.getType(), FormType.SQ.toString()) && Objects.equals(costFromMapping.getCtId(), cType)) { formId = costFromMapping.getFId(); break; } } if (formId == null) { return null; } UpdateBudgetEntity updateBudgetEntity = new UpdateBudgetEntity(); updateBudgetEntity.setFormId(formId); return updateBudgetEntity; } /** * 如果为个人抵扣报销进入此方法 */ public void getPersionCostById(UpdateBudgetEntity updateBudgetEntity) { // 本次冲抵的所有的金额 Double money = this.persionMoney(updateBudgetEntity); if (count > 0 && money > 0) { // 借款单Id String formId = getFormId(SystemForm.LOAN_FORM_ID); if (ObjectUtil.empty(formId)) { return; } // 不为空说明此人有借款 if (Objects.nonNull(borrowList) && borrowList.size() > 0) { Double price = 0.0; for (Map pb : borrowList) { // 未还金额- 个人冲抵金额=判断借款单是否还完 price = Double.parseDouble(Objects.toString(pb.get(OUTSTANDING_AMOUNT), "0")) - money; // 情况1 .本次抵扣正好还清借款 if (price >= 0) { // 已还款金额=冲抵金额+已还金额 Double price2 = Double.parseDouble(Objects.toString(pb.get(ALREADY_REPAID), "0")) + money; this.crudBorrowAndPersion(formId, money, price2, pb); break; } // 冲抵还死第一条记录 if (price < 0) { // 本条记录的冲抵金额 money = Double.parseDouble(Objects.toString(pb.get(OUTSTANDING_AMOUNT), "0")); // 已还款金额=借款总金额 Double price2 = Double.parseDouble(Objects.toString(pb.get(APPLICATION_AMOUNT), "0")); this.crudBorrowAndPersion(formId, money, price2, pb); money = -price; } } } } } /** * @param money 当前冲抵金额 * @param price 已还款金额 * @param pb 借款单数据 更新借款表 */ public void crudBorrowAndPersion(String formId, Double money, Double price, Map pb) { // 借款数据行号 Integer dataNum = Integer.parseInt(Objects.toString(pb.get(DATAROWNUMBER), "0")); PersionBackMoney persionBackMoney = new PersionBackMoney(); persionBackMoney.initParam(); // 当前还款金额 persionBackMoney.setPayMoney(money); persionBackMoney.setDataRowNum(dataNum); persionBackMoney.setFormId(formId); // 借款单没有币种 // persionBackMoney.setMoneyType(); persionBackMoney.setTendantId(Objects.toString(ThreadData.get(TENANT_ID))); persionBackMoney.setDepartment(Objects.toString(pb.get(DEPARTMENT))); String borrowTime = pb.get(CREATEDATETIME).toString(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { persionBackMoney.setBorrowDate(formatter.parse(borrowTime)); } catch (ParseException e) { // System.err.println(e.getMessage()); } String openId = Objects.toString(pb.get(LOANPEOPLE)); persionBackMoney.setStaffId(openId); persionBackMoney.setPosition(Objects.toString(pb.get(EMPLOYEE_POSITION))); persionBackMoney.setPayDate(new Date()); // 未还总金额 persionBackMoney.setPayAllmoney(Double.parseDouble(Objects.toString(pb.get(APPLICATION_AMOUNT), "0")) - price); persionBackMoney.setBorrowMoney(Double.parseDouble(Objects.toString(pb.get(APPLICATION_AMOUNT), "0"))); // 支付方式(1000000.个人抵扣2.其他的方式) persionBackMoney.setPaymentMethod(GetConstant.getConstant(PERSION_COST_RETURN)); persionBackMoney.setOpenId(openId); // 更新操作 persionBackMoneyMapper.insert(persionBackMoney); /** * 冲抵的日志 * 日志对象还款单 * 原始内容:未还款总金额 * 变更来源内容:冲抵金额 money * */ if (ObjectUtil.empty(applyInfo)) { addBudgetLogMoney(this.budgetChildInfo, budgetMoney, formId, this.expendInfo, toDouble(expendInfo.get(EXPEND_USE_MONEY))); } else { addBudgetLogMoney(this.budgetChildInfo, budgetMoney , formId, this.expendInfo, money , applyEntity.getFormId(), this.applyInfo, toDouble(this.applyInfo.get(APPLY_USE_MONEY))); } // 更新借款单 updateData(formId, null, dataNum, // 已还金额 new ModelMap(ALREADY_REPAID, format(price, getFormBase(formId), ALREADY_REPAID)).addAttribute(OUTSTANDING_AMOUNT, // 未还金额 format((Double.parseDouble(Objects.toString(pb.get(APPLICATION_AMOUNT), "0")) - price), getFormBase(formId), OUTSTANDING_AMOUNT))); } /** * 返回个人冲抵的金额 */ public Double persionMoney(UpdateBudgetEntity updateBudgetEntity) { // 个人冲抵金额 Double money = 0.0; // 个人冲抵判断值 String keys = GetConstant.getConstant(PERSION_COST_RETURN); // 报销子表单表名 String formName2 = updateBudgetEntity.getFormId() + PAYINFO; // 主表表名 String formName = updateBudgetEntity.getFormId(); // 查询对应的报销单数据 list = formDataMapper.getPersionCostReturn(updateBudgetEntity.getDataRowNum(), formName, formName2); for (Map m : list) { // 个人冲抵暂定为“10000000”(页面显示现金) if (Objects.equals(m.get(PAYWAY), keys) && StringUtils.isNotBlank(m.get(NETMONEY).toString())) { // NETMONEY,支付金额key值 money += Double.parseDouble(Objects.toString(m.get(NETMONEY), "0")); } } return money; } /** * 全部借款金额 */ public Double allBorrowMoney() { String formId = getFormId(SystemForm.LOAN_FORM_ID); Double borrowMoney = 0.0; if (ObjectUtil.empty(formId)) { return borrowMoney; } String openId = list.get(0).get(REIMBURSE_MAN).toString(); // 借款数据 borrowList = formDataMapper.getBorrowMoney(openId, formId); for (Map m : borrowList) { borrowMoney += Double.parseDouble(Objects.toString(m.get(OUTSTANDING_AMOUNT), "0")); } log.debug("当前借款金额为:" + borrowMoney.toString()); return borrowMoney; } }