diff --git a/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/operate/ReimburseBillSubmitOpExt.java b/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/operate/ReimburseBillSubmitOpExt.java new file mode 100644 index 0000000..75b9c33 --- /dev/null +++ b/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/operate/ReimburseBillSubmitOpExt.java @@ -0,0 +1,57 @@ +package zcgj.zcdev.zcdev.fs.plugin.operate; + +import kd.bos.context.RequestContext; +import kd.bos.entity.plugin.AddValidatorsEventArgs; +import kd.bos.entity.validate.AbstractValidator; +import kd.bos.servicehelper.user.UserServiceHelper; +import kd.fi.er.common.field.writeoffmoney.DailyReimburseWriteOffFields; +import kd.fi.er.common.field.writeoffmoney.WithholdingWriteFields; +import kd.fi.er.opplugin.daily.web.ReimSubmitCheckAmountValidator; +import kd.fi.er.opplugin.daily.web.ReimSubmitCheckProxyTaxValidator; +import kd.fi.er.opplugin.daily.web.ReimburseBillSubmitOp; +import kd.fi.er.validator.*; +import org.apache.commons.lang3.StringUtils; +import zcgj.zcdev.zcdev.fs.plugin.validator.ReimSubmitCheckInvoiceValidatorExt; +import zcgj.zcdev.zcdev.fs.utils.OrgCheckUtils; + +import java.util.List; + +/** + * 费用报销单发票金额精确调整插件 + * 对公报销单发票金额精确调整插件 + */ +public class ReimburseBillSubmitOpExt extends ReimburseBillSubmitOp { + + + public void onAddValidators(AddValidatorsEventArgs e) { + Long currentUserId = UserServiceHelper.getCurrentUserId(); + // 当前用户所属组织 + Long mainOrgId = UserServiceHelper.getUserMainOrgId(currentUserId); + //当前切换选择的组织 + Long currentOrgId = RequestContext.get().getOrgId(); + //当前所在的组织是属于矿山下的 + if(OrgCheckUtils.isKS(currentOrgId)){ + e.addValidator(new ReimburseBillSubmitValidator()); + if (StringUtils.equalsIgnoreCase((String)this.operateMeta.get("key"), "submit")) { + e.addValidator(new ReimSubmitCheckInvoiceValidatorExt()); + e.addValidator(new ReimSubmitCheckProxyTaxValidator()); + e.addValidator(new ReimBillOverApplySubmitValidator()); + e.addValidator(new LoanClearAmountSubmitValidator(DailyReimburseWriteOffFields.getInstance())); + e.addValidator(new LoanAndAccountCurrencyUniqueValidator()); + e.addValidator(new ReimSubmitCheckAmountValidator()); + List validators = e.getValidators(); + if (validators.stream().noneMatch((validator) -> validator.getClass() == ErBillCheckExpItemCanUseValidator.class)) { + e.addValidator(new ErBillCheckExpItemCanUseValidator()); + } + } + + if (StringUtils.equalsIgnoreCase((String)this.operateMeta.get("key"), "saveapprove")) { + e.addValidator(new LoanClearAmountSubmitValidator(WithholdingWriteFields.getInstance())); + } + }else{ + super.onAddValidators(e); + } + + + } +} diff --git a/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/validator/InvoiceUtilsExt.java b/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/validator/InvoiceUtilsExt.java new file mode 100644 index 0000000..d136861 --- /dev/null +++ b/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/validator/InvoiceUtilsExt.java @@ -0,0 +1,75 @@ +package zcgj.zcdev.zcdev.fs.plugin.validator; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.resource.ResManager; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.fi.er.business.utils.InvoiceUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class InvoiceUtilsExt extends InvoiceUtils { + private static final Log log = LogFactory.getLog(InvoiceUtilsExt.class); + + // 定义容差范围 + private static final BigDecimal TOLERANCE = new BigDecimal("0.05"); + + public static List checkAmount(T bill, BillEntityType type) { + if (bill instanceof IDataModel) { + return checkKeyAmountDiff((IDataModel)bill, type, type.getAmountKey(), ResManager.loadKDString("报销金额", "InvoiceUtils_2", "fi-er-business", new Object[0])); + } else { + return (List)(bill instanceof DynamicObject ? checkKeyAmountDiff((DynamicObject)bill, type, type.getAmountKey(), ResManager.loadKDString("报销金额", "InvoiceUtils_2", "fi-er-business", new Object[0])) : new ArrayList()); + } + } + + public static List checkKeyAmountDiff(DynamicObject bill, BillEntityType type, String key, String keyName) { + List resultList = Lists.newArrayList(); + Map itemMap = itemOfInvoice((DynamicObject)bill, type, Sets.newHashSet(new String[]{key})); + Map invoiceMap = invoiceInfo((DynamicObject)bill, type, Sets.newHashSet(new String[]{"totalamount"})); + BigDecimal itemAmout = (BigDecimal)itemMap.get(key); + BigDecimal invoiceAmout = (BigDecimal)invoiceMap.get("totalamount"); + log.info("单据编号:" + bill.getString("billno") + ", 费用" + key + "总和: " + itemAmout + ", 发票报销金额总和:" + invoiceAmout); + BigDecimal differAmount = itemAmout.subtract(invoiceAmout).abs(); + QFilter queryFilter = new QFilter("id", "=", 1); + String selectPropties = "id,sign,amtprecision"; + DynamicObject currency = BusinessDataServiceHelper.loadSingleFromCache("bd_currency", selectPropties, new QFilter[]{queryFilter}); + String sign = currency.getString("sign"); + int amtprecision = currency.getInt("amtprecision"); + StringBuilder sb = (new StringBuilder(keyName)).append(ResManager.loadKDString("超出发票金额%s", "InvoiceUtils_1", "fi-er-business", new Object[0])); + if (differAmount.compareTo(TOLERANCE) > 0) { + resultList.add(String.format(sb.toString(), sign + differAmount.setScale(amtprecision, RoundingMode.HALF_EVEN))); + } + + return resultList; + } + + public static List checkKeyAmountDiff(IDataModel model, BillEntityType type, String key, String keyName) { + List resultList = Lists.newArrayList(); + Map itemMap = itemOfInvoice((IDataModel)model, type, Sets.newHashSet(new String[]{key})); + Map invoiceMap = invoiceInfo((IDataModel)model, type, Sets.newHashSet(new String[]{"totalamount"})); + BigDecimal itemAmout = (BigDecimal)itemMap.get(key); + BigDecimal invoiceAmout = (BigDecimal)invoiceMap.get("totalamount"); + log.info("单据编号:" + model.getValue("billno") + ", 费用" + key + "总和: " + itemAmout + ", 发票报销金额总和:" + invoiceAmout); + BigDecimal differAmount = itemAmout.subtract(invoiceAmout).abs(); + QFilter queryFilter = new QFilter("id", "=", 1); + String selectPropties = "id,sign,amtprecision"; + DynamicObject currency = BusinessDataServiceHelper.loadSingleFromCache("bd_currency", selectPropties, new QFilter[]{queryFilter}); + String sign = currency.getString("sign"); + int amtprecision = currency.getInt("amtprecision"); + StringBuilder sb = (new StringBuilder(keyName)).append(ResManager.loadKDString("超出发票金额%s", "InvoiceUtils_1", "fi-er-business", new Object[0])); + if (differAmount.compareTo(TOLERANCE) > 0) { + resultList.add(String.format(sb.toString(), sign + differAmount.setScale(amtprecision, RoundingMode.HALF_EVEN))); + } + + return resultList; + } +} diff --git a/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/validator/ReimSubmitCheckInvoiceValidatorExt.java b/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/validator/ReimSubmitCheckInvoiceValidatorExt.java new file mode 100644 index 0000000..594eefc --- /dev/null +++ b/code/zcdev/zcgj-zcdev-zcdev-fs/src/main/java/zcgj/zcdev/zcdev/fs/plugin/validator/ReimSubmitCheckInvoiceValidatorExt.java @@ -0,0 +1,137 @@ +package zcgj.zcdev.zcdev.fs.plugin.validator; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.resource.ResManager; +import kd.bos.entity.ExtendedDataEntity; +import kd.bos.entity.validate.AbstractValidator; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.fi.er.business.image.ImageServiceHelper; +import kd.fi.er.business.utils.*; +import org.apache.commons.lang3.StringUtils; +import zcgj.zcdev.zcdev.fs.utils.OrgCheckUtils; + +import java.math.BigDecimal; +import java.util.Objects; + +public class ReimSubmitCheckInvoiceValidatorExt extends AbstractValidator { + private static final Log log = LogFactory.getLog(ReimSubmitCheckInvoiceValidatorExt.class); + + public void validate() { + ExtendedDataEntity[] dataEntities = this.getDataEntities(); + + for(ExtendedDataEntity dataEntity : dataEntities) { + DynamicObject bill = dataEntity.getDataEntity(); + DynamicObject company = bill.getDynamicObject("company"); + DynamicObject costcompany = bill.getDynamicObject("costcompany"); + if (company == null || costcompany == null) { + return; + } + + Long companyId = (Long)company.getPkValue(); + this.chechInvoiceImageTemp(bill, dataEntity); + this.checkNoInvoice(bill, dataEntity); + if (ErStdConfig.getInvoiceMustWithExpense()) { + for(String result : InvoiceUtils.checkUnbindInvoice(bill, dataEntity)) { + this.addErrorMessage(dataEntity, result); + } + } + + DynamicObjectCollection invoiceItemEntryDOs = bill.getDynamicObjectCollection("invoiceitementry"); + if (!invoiceItemEntryDOs.isEmpty()) { + Boolean mustCheck = SystemParamterUtil.isAmountOverInvoice(companyId); + if (!mustCheck) { + //如果是矿山下面的组织 + long costcompanyId = costcompany.getLong("id"); + if(OrgCheckUtils.isKS(costcompanyId)){ + for(String result : InvoiceUtilsExt.checkAmount(bill, InvoiceUtils.BillEntityType.DailyReimburse)) { + this.addErrorMessage(dataEntity, result); + } + }else{ + for(String result : InvoiceUtils.checkAmount(bill, InvoiceUtils.BillEntityType.DailyReimburse)) { + this.addErrorMessage(dataEntity, result); + } + } + + } + + DynamicObject invoicOrgDO = bill.getDynamicObject("costcompany"); + + for(String result : InvoiceUtils.checkBuyerNameAndTaxNo(bill, ErCommonUtils.getPk(invoicOrgDO), false)) { + this.addErrorMessage(dataEntity, result); + } + } + } + + } + + private void checkNoInvoice(DynamicObject bill, ExtendedDataEntity dataEntity) { + DynamicObject company = bill.getDynamicObject("company"); + if (company != null) { + Long companyId = (Long)company.getPkValue(); + Boolean invoiceIsMust = ReimburseControlUtils.invoiceIsMust(companyId); + if (invoiceIsMust) { + boolean supplementinvoice = bill.getBoolean("needsuppleinvoice"); + if (!supplementinvoice) { + Boolean billHeadNoInvocie = bill.getBoolean("noinvoice"); + if (!billHeadNoInvocie) { + Long invoiceCurrency = SystemParamterUtil.getInvoiceEntryCurrency(companyId); + DynamicObjectCollection expenseEntrys = bill.getDynamicObjectCollection("expenseentryentity"); + int length = expenseEntrys.size(); + + for(int entryIndex = 0; entryIndex < length; ++entryIndex) { + DynamicObject expenseEntry = (DynamicObject)expenseEntrys.get(entryIndex); + BigDecimal expeAmount = expenseEntry.getBigDecimal("expenseamount"); + if (expeAmount.compareTo(BigDecimal.ZERO) != 0) { + DynamicObject expense = expenseEntry.getDynamicObject("expenseitem"); + if (expense != null && Objects.equals(invoiceCurrency, ErCommonUtils.getPk(expenseEntry.getDynamicObject("entrycurrency")))) { + boolean bool = expense.getDynamicObjectType().getProperty("noinvoice") != null; + if (bool) { + Boolean noinvoice = expense.getBoolean("noinvoice"); + if (noinvoice) { + continue; + } + } + + String invoiceno_entry = expenseEntry.getString("invoiceno_entry"); + if (StringUtils.isBlank(invoiceno_entry)) { + String fmt = ResManager.loadKDString("第%s行费用明细分录需要导入发票或关联发票。", "ReimSubmitCheckInvoiceValidator_1", "fi-er-opplugin", new Object[0]); + this.addErrorMessage(dataEntity, String.format(fmt, entryIndex + 1)); + } + } + } + } + + } + } + } + } + } + + private void chechInvoiceImageTemp(DynamicObject bill, ExtendedDataEntity dataEntity) { + DynamicObjectCollection invoiceEntrys = bill.getDynamicObjectCollection("invoiceentry"); + if (invoiceEntrys.size() <= 0) { + log.info("发票分录没有发票,不进行校验"); + } else { + DynamicObject company = bill.getDynamicObject("company"); + String mainEntityId = bill.getDataEntityType().getName(); + Long companyId = 0L; + if (company == null) { + log.info("申请人公司为空,不进行校验"); + } else { + companyId = (Long)company.getPkValue(); + boolean isImageTemp = SystemParamterUtil.isMapInvoiceCloudImage(companyId); + if (isImageTemp) { + String configedPrintTemplateFormId = ImageServiceHelper.getConfigedPrintTplFormNumber(bill, mainEntityId, companyId); + if (StringUtils.isBlank(configedPrintTemplateFormId)) { + this.addErrorMessage(dataEntity, ResManager.loadKDString("未设置单据影像模板,请联系管理员设置!", "ReimSubmitCheckInvoiceValidator_2", "fi-er-opplugin", new Object[0])); + } + } else { + log.info("没有集成发票云影像,不进行校验"); + } + + } + } + } +}