From 5caf4c7eea1d8fda08cc7e49c0d26823c45f8f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E8=B4=B5=E5=BC=BA?= Date: Thu, 30 Oct 2025 10:11:39 +0800 Subject: [PATCH] =?UTF-8?q?SAP=E5=BA=94=E4=BB=98=E5=87=AD=E8=AF=81?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E6=8B=89=E5=8F=96=E4=BB=BB=E5=8A=A1=E6=89=A9?= =?UTF-8?q?=E5=B1=95=EF=BC=88=E7=89=B9=E5=AE=9A=E5=8D=95=E6=8D=AE=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/QuerySapCreatePayApplyExtTask.java | 697 ++++++++++++++++++ .../task/QuerySapCreatePayApplyTask.java | 39 +- 2 files changed, 730 insertions(+), 6 deletions(-) create mode 100644 main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyExtTask.java diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyExtTask.java b/main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyExtTask.java new file mode 100644 index 0000000..55c4f35 --- /dev/null +++ b/main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyExtTask.java @@ -0,0 +1,697 @@ +package shjh.jhzj7.fi.fi.plugin.task; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import kd.bos.context.RequestContext; +import kd.bos.dataentity.OperateOption; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.utils.StringUtils; +import kd.bos.entity.operate.OperateOptionConst; +import kd.bos.entity.operate.result.OperationResult; +import kd.bos.exception.KDException; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.schedule.executor.AbstractTask; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.operation.OperationServiceHelper; +import kd.sdk.plugin.Plugin; +import shjh.jhzj7.fi.fi.utils.EsbUtils; +import shjh.jhzj7.fi.fi.utils.JhzjUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.*; + +import static shjh.jhzj7.fi.fi.plugin.form.SappzFormPlugin.*; +import static shjh.jhzj7.fi.fi.utils.SapUtils.vouchers_payable; +import static shjh.jhzj7.fi.fi.webapi.ApplyBillControler.*; + +/** + * 后台任务插件 + */ +public class QuerySapCreatePayApplyExtTask extends AbstractTask implements Plugin { + + public static final String apimenthod = "定时调用SAP应付凭证接口生成付款申请单(临期)";//bd_accountview + + private final static Log logger = LogFactory.getLog(QuerySapCreatePayApplyExtTask.class); + + @Override + public void execute(RequestContext requestContext, Map map) throws KDException { + // 获取临期天数并转换 + String lqBefore = (String) map.get("临期_前"); + String lqAfter = (String) map.get("临期_后"); + Set filterSet = new HashSet<>(); + String filterType = (String) map.get("执行类型"); + + if (filterType != null && !filterType.trim().isEmpty()) { + // 按分号分割,并去除前后空格 + String[] types = filterType.split(";"); + for (String type : types) { + String trimmedType = type.trim(); + if (!trimmedType.isEmpty()) { + filterSet.add(trimmedType); + } + } + } + + // 检查是否有有效的临期数据 + if (StringUtils.isEmpty(lqBefore) || StringUtils.isEmpty(lqAfter)) { + return; + } + //获取当前日期 + LocalDate currentDate = LocalDate.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + int daysBefore = Integer.parseInt(lqBefore);//临期_前 + int daysAfter = Integer.parseInt(lqAfter);//临期_后 + int totalDays = daysBefore + daysAfter;//总天数 + int callInterval = 20; // 调用间隔天数 + // 根据总天数和间隔天数计算调用次数(向上取整) + int callCount = (int) Math.ceil((double) totalDays / callInterval); + + // 计算开始日期(临期_前表示今天之前的天数) + LocalDate startDate = currentDate.minusDays(daysBefore); + // 计算结束日期(临期_后表示今天之后的天数) + LocalDate endDate = currentDate.plusDays(daysAfter); + JSONArray IT_LIST = new JSONArray(3); + JSONObject result;//sap应付凭证接口返回值 + JSONObject sapdata;//sap应付凭证接口返回值data + String formatStartDate; // 开始日期-文本 + String formatEndDate; // 结束日期-文本 + String record;//日期拼接记录 + Map payapplys;//付款申请单处理结果集 + //以调用次数开始循环 + for (int i = 1; i <= callCount; i++) { + formatStartDate = startDate.format(formatter); + if(i == callCount){ + //如果是最后一次循环,结束日期用endDate + formatEndDate = endDate.format(formatter); + }else{ + //否则结束日期用开始日期加上间隔天数 + formatEndDate = startDate.plusDays(callInterval).format(formatter); + } + IT_LIST.clear();//使用之前先清空 + // 添加SAP应付凭到期日过滤条件 + addFilterCondition(IT_LIST, "FAEDT", formatStartDate, formatEndDate); + //供应商账户组作为筛选条件,此时需要剔除D200 D201两个选项 + removeSupplierGroupFilter(IT_LIST); + record = formatStartDate+"临期第"+i+"次"+formatEndDate; + logger.info(record); + result = vouchers_payable(IT_LIST,record); + if (null != result && result.containsKey("data")) { + // 处理查询结果 + sapdata = (JSONObject) result.get("data"); + if (null != sapdata && sapdata.containsKey("IT_ITEM")) { + JSONArray IT_ITEMs = (JSONArray) sapdata.get("IT_ITEM"); + if (!IT_ITEMs.isEmpty()) { + payapplys = getPayapply(IT_ITEMs,filterSet); + //若多条数据相同,则合并为一条数据处理 + OperateOption option = OperateOption.create(); + option.setVariableValue(OperateOptionConst.IGNOREWARN, String.valueOf(false)); // 不执行警告级别校验器 + String fkBillNum; + String sapuniquevalue; + for (DynamicObject ap_payapply : payapplys.values()) { + fkBillNum = ap_payapply.getString("shjh_vouchernum");//凭证号 + sapuniquevalue = ap_payapply.getString("shjh_sapuniquevalue");//凭证唯一码 + // 新增数据 + OperationResult saveResult = OperationServiceHelper.executeOperate("save", AP_PAYAPPLY, new DynamicObject[]{ap_payapply}, option); + if (!saveResult.isSuccess()) { + handleAndLogError(saveResult, "保存失败", apimenthod, fkBillNum, sapuniquevalue); + continue; + } + OperationResult submitResult = OperationServiceHelper.executeOperate("submit", AP_PAYAPPLY, new DynamicObject[]{ap_payapply}, option); + if (!submitResult.isSuccess()) { + // 提交失败,将保存的数据删除,记录日志 + OperationServiceHelper.executeOperate("delete", AP_PAYAPPLY, new DynamicObject[]{ap_payapply}, option); + handleAndLogError(submitResult, "提交失败", apimenthod, fkBillNum, sapuniquevalue); + continue; + } + OperationResult auditResult = OperationServiceHelper.executeOperate("audit", AP_PAYAPPLY, new DynamicObject[]{ap_payapply}, option); + if (!auditResult.isSuccess()) { + handleAndLogError(auditResult, "审核失败", apimenthod, fkBillNum, sapuniquevalue); + continue; + } + logger.info("审核成功,凭证号:" + sapuniquevalue); + } + } + } + } + //一次循环结束后,开始日期变为加上间隔天数+1后的日期 + startDate = startDate.plusDays(callInterval+1); + } + } + + //增加供应商账户组的过滤条件,剔除这两个选项 D200 D201 + private void removeSupplierGroupFilter(JSONArray IT_LIST){ + JSONObject jsonObject0 = new JSONObject(); + jsonObject0.put("FIELD", "KTOKK"); // 字段名称 + jsonObject0.put("SIGN", "E"); // I:包含 E:排除 + jsonObject0.put("LOW", "D200"); // LOW ,枚举字段所代表值的区间开始值 + jsonObject0.put("HIGH", "D200"); // HIGH,枚举字段所代表值的区间结束值 + jsonObject0.put("OPTION", "EQ"); // 默认BT:单条 + IT_LIST.add(jsonObject0); + + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.put("FIELD", "KTOKK"); // 字段名称 + jsonObject1.put("SIGN", "E"); // I:包含 E:排除 + jsonObject1.put("LOW", "D201"); // LOW ,枚举字段所代表值的区间开始值 + jsonObject1.put("HIGH", "D201"); // HIGH,枚举字段所代表值的区间结束值 + jsonObject1.put("OPTION", "EQ"); // 默认BT:单条 + IT_LIST.add(jsonObject1); + } + + /** + * 通过SAP接口查询应付凭证数据,并生成应付付款申请单 + */ + private Map getPayapply(JSONArray IT_ITEMs,Set filterSet){ + Map bills = new HashMap<>(); + JSONObject it_list;//sap单个应付凭证 + String shjh_payee = "";//往来类型 + String shjh_payeebanknum = "";//往来户名称 + // 定义往来类型和对应值的映射 + Map asstactTypeMap = new HashMap<>(); + asstactTypeMap.put("供应商", "bd_supplier"); + asstactTypeMap.put("客户", "bd_customer"); + String[][] currencyInfo = { + {"paycurrency", "付款币别"}, + {"settlecurrency", "结算币别"} + }; + //常量字段处理 + DynamicObject ds_paytype = BusinessDataServiceHelper.loadSingle(CAS_PAYMENTBILLTYPE, + new QFilter[]{new QFilter("name", QCP.equals, "对私付款")}); + DynamicObject dg_paytype = BusinessDataServiceHelper.loadSingle(CAS_PAYMENTBILLTYPE, + new QFilter[]{new QFilter("name", QCP.equals, "对公付款")}); + DynamicObject default_settletype = BusinessDataServiceHelper.loadSingle("bd_settlementtype", + new QFilter[]{new QFilter("number", QCP.equals, "T")});//银企直连 + //单据类型 + DynamicObject billtype = BusinessDataServiceHelper.loadSingle(BOS_BILLTYPE, + new QFilter[]{new QFilter("name", QCP.equals, "其他付款申请")}); + //汇率表 + DynamicObject exrate = BusinessDataServiceHelper.loadSingle(BD_EXRATETABLE, + new QFilter[]{new QFilter("number", QCP.equals, "ERT-01")}); + + for (Object itItem : IT_ITEMs) { + it_list = (JSONObject) itItem; + + String uuid = it_list.getString("XBLNR");//单据号 + // 判断uuid是否包含filterSet中的任何字符串 + boolean shouldSkip = false; + for (String filter : filterSet) { + if (uuid.contains(filter)) { + shouldSkip = true; + break; + } + } + + if (!shouldSkip) { + continue; // 跳过当前循环 + } + + String bukrs = it_list.getString("BUKRS");//公司编号 + String fkBillNum = it_list.getString("BELNR");//凭证号 + String gjahr = it_list.getString("GJAHR");//会计年度 + String accountingsubject = it_list.getString("HKONT");//会计科目 + String ebelp = it_list.getString("BUZEI");//会计科目行项目号 + BigDecimal wrbtr = new BigDecimal(it_list.getString("WRBTR"));//未清金额 + //汇率 + BigDecimal KURSF = new BigDecimal(it_list.getString("KURSF")); + if (KURSF.compareTo(BigDecimal.ZERO) == 0) { + KURSF = BigDecimal.ONE; + } + BigDecimal dmbtr = new BigDecimal(it_list.getString("DMBTR"));//申请金额折结算币别 + Date FAEDTs = null;//到期日,净价到期日 + String FAEDT = it_list.getString("FAEDT"); + if (StringUtils.isNotEmpty(FAEDT)) { + FAEDTs = StrToDate(FAEDT); + } + Date BUDATs = null;//记账日期,凭证中的过帐日期 + String BUDAT = it_list.getString("BUDAT"); + if (StringUtils.isNotEmpty(BUDAT)) { + BUDATs = StrToDate(BUDAT); + } + Date BLDATs = null;//凭证日期,凭证中的凭证日期 + String BLDAT = it_list.getString("BLDAT"); + if (StringUtils.isNotEmpty(BLDAT)) { + BLDATs = StrToDate(BLDAT); + } + Date ZFBDTs = null;//基准日期,用于到期日计算的基准日期 + String ZFBDT = it_list.getString("ZFBDT"); + if (StringUtils.isNotEmpty(ZFBDT)) { + ZFBDTs = StrToDate(ZFBDT); + } + + String kunnr = it_list.getString("KUNNR");//客户(员工) + String lifnr = it_list.getString("LIFNR");//供应商 + if (StringUtils.isNotEmpty(kunnr)) { + shjh_payee = "客户"; + shjh_payeebanknum = kunnr; + } else { + shjh_payee = "供应商"; + shjh_payeebanknum = lifnr; + } + String assacct = it_list.getString("BVTYP");//合作银行类型 + //原因码 + String reasoncode =it_list.getString("RSTGR"); + //todo:资金计划分类 +// String zreqDept = it_list.getString("ZREQ_DEPT");//二级部门 + String procurementeam = it_list.getString("EKGRP");//采购组 + String isselfprocurment = it_list.getString("ZZXCG_FLAG");//是否自行采购 + String waers = it_list.getString("WAERS");//付款币别编号CNY,货币码 && 结算币别编号,货币码 + String paymentterms = it_list.getString("ZTERM");// 付款条件_付款条件代码 + String refertoinvoicenumber = it_list.getString("XBLNR");// 参照发票号 + + // 公司编号 bukrs + QFilter Q1 = new QFilter("number", QCP.equals, bukrs); + DynamicObject org = BusinessDataServiceHelper.loadSingle(orgEntName, new QFilter[]{Q1}); + if(org == null){ + logger.error("同步失败,凭证号:" + fkBillNum + "的公司未在金蝶找到对应公司"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,SAP的公司未在金蝶找到对应公司", false, "API"); + continue; + } + + // 申请金额 , 汇率 , 申请金额折结算币别 + BigDecimal amount = BigDecimal.ZERO; + // 未清金额 amount + try { + wrbtr = wrbtr.setScale(2, RoundingMode.HALF_UP); + amount = wrbtr; + } catch (NumberFormatException e) { + logger.error("未清金额格式错误", e.getMessage()); + continue; + } + // 往来类型 shjh_payee + // 往来户 party + QFilter Q3 = new QFilter("number", QCP.equals, shjh_payeebanknum); + DynamicObject party = "供应商".equals(shjh_payee) + ? BusinessDataServiceHelper.loadSingle(BD_SUPPLIER, new QFilter[]{Q3}) + : BusinessDataServiceHelper.loadSingle(BD_CUSTOMER, new QFilter[]{Q3}); + + if(party == null){ + logger.error("同步失败,凭证号:" + fkBillNum + "的客商未在金蝶找到对应数据"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,SAP的客商未在金蝶找到对应数据", false, "API"); + continue; + } + + // 新增应付付款申请单 + DynamicObject ap_payapply = BusinessDataServiceHelper.newDynamicObject(AP_PAYAPPLY); + + //防重校验条件1:根据入参中的应付凭证ID作为唯一值,去金蝶的付款申请单中查找有无此记录,如果有且单据中SAP锁定 + // 状态为已锁定,则校验失败,记录日志。数据库层面,将应付凭证ID建立唯一约束。 + QFilter Q4 = new QFilter("shjh_vouchernum", QCP.equals, fkBillNum);//凭证号 + QFilter Q5 = new QFilter("applyorg.number", QCP.equals, bukrs); + QFilter Q6 = new QFilter("shjh_voucheryear", QCP.equals, gjahr);//会计年度 + QFilter Q7 = new QFilter("shjh_voucherentrynum", QCP.equals, ebelp);//会计科目行项目号 + DynamicObject ap_payapplys = BusinessDataServiceHelper.loadSingle(AP_PAYAPPLY, new QFilter[]{Q4, Q5, Q6, Q7}); + if (null != ap_payapplys) { + boolean shjhSapwhetherlocking = ap_payapplys.getBoolean("shjh_sapwhetherlocking");//SAP是否锁定 + if (shjhSapwhetherlocking) { + logger.error("同步失败,凭证号:" + fkBillNum + "的单据SAP已锁定"); + continue; + } else { + //存在付款申请单且单据中SAP锁定状态为未锁定,更新数据 + ap_payapply = ap_payapplys; + } + } + + ap_payapply.set("settleorg", org); // 结算组织 + ap_payapply.set("applyorg", org); // 申请组织 + ap_payapply.set("payorg", org); // 付款组织 + ap_payapply.set("purorg", org); // 采购组织 + + // 申请日期 + ap_payapply.set("applydate", BUDATs); + + //SAP会计科目 + if (accountingsubject != null && !accountingsubject.isEmpty()) { + QFilter Q8 = new QFilter("number", QCP.equals, accountingsubject);//会计科目编号 + Q8.and("createorg.id", QCP.equals, org.getPkValue());//当前公司ID + //如果当前数据中心是测试的则使用测试库科目表ID,否则用正式的 + if("2162562979827025920".equals(RequestContext.get().getAccountId())){ + Q8.and("accounttable.id", QCP.equals, 2125524820924832768L);//测试科目表 + }else{ + Q8.and("accounttable.id", QCP.equals, EsbUtils.ACCTABLE);//正式科目表 + } + DynamicObject accountview = BusinessDataServiceHelper.loadSingle(BD_ACCOUNTVIEW, Q8.toArray()); + if(accountview == null){ + logger.error("同步失败,凭证号:" + fkBillNum + "的SAP会计科目在金蝶中未找到对应科目"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,SAP会计科目在金蝶中未找到对应科目", false, "API"); + continue; + } + ap_payapply.set("shjh_sapkjkm", accountview); + }else{ + logger.error("同步失败,凭证号:" + fkBillNum + "的SAP会计科目为空"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,SAP会计科目为空", false, "API"); + continue; + } + ap_payapply.set("applycause", "");//请款事由 + + //币别-处理 + for (String[] info : currencyInfo) { + String currencyType = info[0]; +// String currencyTypeName = info[1]; + // 根据币别类型从 applybill 获取对应的币别编号 + String currencyNumber = waers; + if ("RMB".equals(currencyNumber)) { + currencyNumber = "CNY"; + } + QFilter filter = new QFilter("number", QCP.equals, currencyNumber); + DynamicObject currency = BusinessDataServiceHelper.loadSingle(BD_CURRENCY, new QFilter[]{filter}); + ap_payapply.set(currencyType, currency); + } + //汇率 + try { + KURSF = KURSF.setScale(5, RoundingMode.HALF_UP); + ap_payapply.set("exchangerate", KURSF); + } catch (NumberFormatException e) { + logger.error("同步失败,凭证号:" + fkBillNum + "的汇率处理异常"); + continue; + } + + //申请金额折结算币别 + try { + dmbtr = dmbtr.setScale(2, RoundingMode.HALF_UP); + ap_payapply.set("appseleamount", dmbtr); + } catch (NumberFormatException e) { + logger.error("同步失败,凭证号:" + fkBillNum + "的申请金额折结算币别处理异常"); + continue; + } + + DynamicObjectCollection entry = ap_payapply.getDynamicObjectCollection("entry");//明细 + entry.clear(); + DynamicObject ap_payapply_entry = entry.addNew(); + + // 根据往来类型设置值 + ap_payapply_entry.set("e_asstacttype", asstactTypeMap.get(shjh_payee)); + // 往来户 + ap_payapply_entry.set("e_asstact", party); + + //如果往来户为供应商,才会有往来账户和银行,根据供应商银行分录里面的合作银行类型来确定往来账户和银行 + //往来账户 && 往来银行 + if ("供应商".equals(shjh_payee)) { + DynamicObjectCollection bankentrys = party.getDynamicObjectCollection("entry_bank");//银行信息分录 + if (!bankentrys.isEmpty()) { + boolean ispp = false;//sap合作银行类型是否与金蝶供应商银行账号匹配 + //如果sap的合作银行类型为空,再判断供应商银行分录是否只有一个,只有一个时,携带此银行 + if(EsbUtils.isEmpty(assacct) && bankentrys.size() == 1){ + DynamicObject bankentry = bankentrys.get(0); + String bankaccount = bankentry.getString("bankaccount"); + DynamicObject bank = bankentry.getDynamicObject("bank"); + String accountname = bankentry.getString("accountname"); + // 检查银行账号,开户银行,账户名称是否为空 + if (bankaccount == null || bankaccount.trim().isEmpty()) { + logger.error("同步失败,凭证号:" + fkBillNum + "的银行账号为空(供应商)"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的银行账号为空(供应商)", false, "API"); + continue; + } + if (null == bank) { + logger.error("同步失败,凭证号:" + fkBillNum + "的开户银行为空(供应商)"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的开户银行为空(供应商)", false, "API"); + continue; + } + if (accountname == null || accountname.trim().isEmpty()) { + logger.error("同步失败,凭证号:" + fkBillNum + "的账户名称为空(供应商)"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的账户名称为空(供应商)", false, "API"); + continue; + } + //20250814开发培训时沟通:判断银行的账号状态,如果是E 则代表已被sap删了,不可使用 + if("E".equalsIgnoreCase(bankentry.getString("shjh_bankstatus"))){ + logger.error("同步失败,凭证号:" + fkBillNum + "的账户状态为E,不可使用"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的账户状态为E,不可使用", false, "API"); + continue; + } + ap_payapply_entry.set("e_assacct", bankaccount);//银行账号 + ap_payapply_entry.set("e_bebank", bank);//开户银行 + ap_payapply_entry.set("shjh_asstactrealname", accountname);//账户名称 + ispp = true; + }else if(!EsbUtils.isEmpty(assacct)){ + for (DynamicObject bankentry : bankentrys) { + if (assacct.equals(bankentry.getString("shjh_banktype"))) { + String bankaccount = bankentry.getString("bankaccount"); + DynamicObject bank = bankentry.getDynamicObject("bank"); + String accountname = bankentry.getString("accountname"); + // 检查银行账号,开户银行,账户名称是否为空 + if (bankaccount == null || bankaccount.trim().isEmpty()) { + logger.error("同步失败,凭证号:" + fkBillNum + "的银行账号为空(供应商)"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的银行账号为空(供应商)", false, "API"); + continue; + } + if (null == bank) { + logger.error("同步失败,凭证号:" + fkBillNum + "的开户银行为空(供应商)"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的开户银行为空(供应商)", false, "API"); + continue; + } + if (accountname == null || accountname.trim().isEmpty()) { + logger.error("同步失败,凭证号:" + fkBillNum + "的账户名称为空(供应商)"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的账户名称为空(供应商)", false, "API"); + continue; + } + //20250814开发培训时沟通:判断银行的账号状态,如果是E 则代表已被sap删了,不可使用 + if("E".equalsIgnoreCase(bankentry.getString("shjh_bankstatus"))){ + logger.error("同步失败,凭证号:" + fkBillNum + "的账户状态为E,不可使用"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的账户状态为E,不可使用", false, "API"); + continue; + } + ap_payapply_entry.set("e_assacct", bankaccount);//银行账号 + ap_payapply_entry.set("e_bebank", bank);//开户银行 + ap_payapply_entry.set("shjh_asstactrealname", accountname);//账户名称 + ispp = true; + break; + } + } + } + if (!ispp) { + logger.error("同步失败,凭证号:" + fkBillNum + "的合作银行类型无匹配数据(供应商)"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的合作银行类型无匹配数据(供应商)", false, "API"); + continue; + } + }else { + logger.error("同步失败,凭证号:" + fkBillNum + "的供应商不存在银行信息"); + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "同步失败,凭证号:" + fkBillNum + "的供应商不存在银行信息", false, "API"); + continue; + } + }else { + //客户 默认取第一行银行信息 + DynamicObjectCollection entryBank = party.getDynamicObjectCollection("entry_bank"); + if (!entryBank.isEmpty()) { + DynamicObject bankentry = entryBank.get(0); + String bankaccount = bankentry.getString("bankaccount");//银行账号 + DynamicObject bank = bankentry.getDynamicObject("bank");//开户银行 + String accountname = bankentry.getString("accountname");//账户名称 + + ap_payapply_entry.set("e_assacct", bankaccount);//银行账号 + ap_payapply_entry.set("e_bebank", bank);//开户银行 + ap_payapply_entry.set("shjh_asstactrealname", accountname);//账户名称 + } + } + //到期日 + ap_payapply_entry.set("e_duedate", FAEDTs); + //分录申请金额 + ap_payapply_entry.set("e_applyamount", amount); + //分录申请金额折结算币 + ap_payapply_entry.set("e_appseleamount", dmbtr); + //表头申请金额 + ap_payapply.set("applyamount", amount); + //凭证抬头文本 + ap_payapply.set("shjh_voucherheadertext", it_list.getString("BKTXT")); + + //付款类型:对公付款、对私付款;SAP:科目编号1221020200 对私付款。费控:劳务人员报销单 对私付款。其他均赋值为对公付款。 + if ("1221020200".equals(accountingsubject)) { + ap_payapply_entry.set("e_paymenttype", ds_paytype);//对私付款 + } else { + ap_payapply_entry.set("e_paymenttype", dg_paytype);//对公付款 + } + //------------------------------默认字段-------------------------------- + ap_payapply.set("billtype", billtype);//单据类型 + ap_payapply.set("exratetable", exrate);//汇率表 + ap_payapply.set("billstatus", "A");//状态:暂存 + + //select * from t_ap_applypaybill where fid = 2148014743875508224 or fid = 2148018902158815232 + //单头:申请人,approvalamount(核准金额),aprseleamount(核准金额折结算币),paystatus(付款状态),freezestate(冻结状态), + // quotation(换算方式),billsrctype(单据来源类型) + //申请人 + long currUserId = RequestContext.get().getCurrUserId();//当前用户 creator + ap_payapply.set("creator", currUserId); + // 核准金额 + ap_payapply.set("approvalamount", amount); + // 核准金额折结算币 + ap_payapply.set("aprseleamount", dmbtr);//Unpaid + // 付款状态 + ap_payapply.set("paystatus", "Unpaid");//未付款 + // 冻结状态 + ap_payapply.set("freezestate", "unfreeze");//未冻结 + // 换算方式 + ap_payapply.set("quotation", "0");//直接汇率 + // 单据来源类型 + ap_payapply.set("billsrctype", "2");//后台生成 + //select * from t_ap_applypaybillentry where fid = 2148014743875508224 or fid = 2148018902158815232 + //明细:seq,e_approvedamt(核准金额),e_approvedseleamt(核准金额折结算币),e_corebilltype(核心单据类型),e_freezestate(冻结状态), + // e_creator(创建人),e_closestatus(行关闭状态) + // 序号 + ap_payapply_entry.set("seq", 1); + // 核准金额 + ap_payapply_entry.set("e_approvedamt", amount); + // 核准金额折结算币 + ap_payapply_entry.set("e_approvedseleamt", dmbtr); + // 核心单据类型 + ap_payapply_entry.set("e_corebilltype", "pm_purorderbill");//采购订单 + // 冻结状态 + ap_payapply_entry.set("e_freezestate", "unfreeze");//未冻结 + // 创建人 + ap_payapply_entry.set("e_creator", currUserId); + // 行关闭状态 + ap_payapply_entry.set("e_closestatus", "A");//正常 + //SAP应付凭证号 + ap_payapply.set("shjh_vouchernum", fkBillNum); + //SAP应付凭证行号 + ap_payapply.set("shjh_voucherentrynum", ebelp); + //SAP应付凭证会计年度 + ap_payapply.set("shjh_voucheryear", gjahr); + //采购组 + ap_payapply.set("shjh_procurementteam", procurementeam); + //是否自行采购 + ap_payapply.set("shjh_zxcg", isselfprocurment); + //原因码 + if (reasoncode != null && !reasoncode.isEmpty()) { + QFilter Q11 = new QFilter("number", QCP.equals, reasoncode); + DynamicObject cause = BusinessDataServiceHelper.loadSingle(GL_CASHFLOWITEM, new QFilter[]{Q11}); + ap_payapply.set("shjh_yym", cause); + } + //过账日期(记账) + ap_payapply.set("shjh_bookkeepingdate", BUDATs); + //凭证日期 + ap_payapply.set("shjh_documentdate", BLDATs); + //结算方式-先设置一个默认值 银企直连,然后根据供应商分录判断重新赋值 + ap_payapply_entry.set("e_settlementtype", default_settletype); + + if ("供应商".equals(shjh_payee)) { + DynamicObjectCollection shjhEntrySap = party.getDynamicObjectCollection("shjh_entry_sap"); + if (!shjhEntrySap.isEmpty()) { + for (DynamicObject object : shjhEntrySap) { + if (org.getString("number").equals(object.getString("shjh_companynum"))) { + // 结算方式(付款方式) + DynamicObject settlementtype = BusinessDataServiceHelper.loadSingle("bd_settlementtype", + new QFilter[]{new QFilter("number", QCP.equals, object.getString("shjh_settlementmethod"))}); + if (settlementtype != null) { + ap_payapply_entry.set("e_settlementtype", settlementtype); + break; + } + } + } + } + } + ap_payapply.set("shjh_fkdjbh", uuid); + String bizbig = it_list.getString("ZYWDLCODE");//业务大类编 + String bizsmall = it_list.getString("ZYWXLCODE");//业务小类编码 + //业务大类,业务小类 + if (kd.bos.util.StringUtils.isNotEmpty(bizbig)) { + DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle("shjh_bizbigtype", new QFilter[]{new QFilter("shjh_fknumber", QCP.equals, bizbig)}); + ap_payapply.set("shjh_bizbig", dynamicObject); + } + if (kd.bos.util.StringUtils.isNotEmpty(bizsmall)) { + DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle("shjh_bizsmalltype", new QFilter[]{new QFilter("shjh_fknumber", QCP.equals, bizsmall)}); + ap_payapply.set("shjh_basedatafield", dynamicObject); + } + String department = it_list.getString("ZREQ_DEPT");//部门编号 + if (kd.bos.util.StringUtils.isNotEmpty(department)) { + DynamicObject adminorg = BusinessDataServiceHelper.loadSingle("bos_adminorg", + new QFilter[]{new QFilter("number", QCP.equals, department)}); + ap_payapply.set("shjh_secondarydept", adminorg); + } + + // 设置付款类型 外部系统单据类型 + setPaymentType(ap_payapply, uuid, dg_paytype, ds_paytype); + + //凭证类型 + String blart = it_list.getString("BLART"); + if (kd.bos.util.StringUtils.isNotEmpty(blart)) { + DynamicObject vouchertype = BusinessDataServiceHelper.loadSingle("gl_vouchertype", + new QFilter[]{new QFilter("number", QCP.equals, blart)}); + ap_payapply.set("shjh_documenttype", vouchertype);//凭证类型 + } + + //基准日期 + ap_payapply.set("shjh_basedate", ZFBDTs); + //付款条件 + ap_payapply.set("shjh_fktj", paymentterms); + //参照发票号 + ap_payapply.set("shjh_czfph", refertoinvoicenumber); + //来源系统 + ap_payapply.set("shjh_sourcesystem", "A");//SAP + //到期日 + ap_payapply.set("shjh_duedate", FAEDTs); + + //SAP应付凭证ID:金蝶组装:公司编号+SAP应付凭证会计年度+SAP应付凭证号+SAP应付凭证行号 + ap_payapply.set("shjh_sapuniquevalue", bukrs + gjahr + fkBillNum + ebelp); + bills.put(ap_payapply.getString("shjh_sapuniquevalue"), ap_payapply); + //付款申请单校验成功,保存日志,后续单子保存提交审核没问题的话,不再记录日志 + JhzjUtils.saveLog(fkBillNum, apimenthod, it_list.toJSONString(), "校验成功", true, "API"); + } + return bills; + } + + private void setPaymentType(DynamicObject ap_payapply, String uuid, DynamicObject paytype_g, DynamicObject paytype_s){ + //根据单据号 uuid 判断 + DynamicObjectCollection entry = ap_payapply.getDynamicObjectCollection("entry"); + //付款类型 外部系统单据类型 + if (uuid.contains("JKY")) { + ap_payapply.set("shjh_externalsystemdocume","A");//员工借款单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_s);//对私 + } + }else if (uuid.contains("TYB")) { + ap_payapply.set("shjh_externalsystemdocume","B");//通用报销单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_s);//对私 + } + }else if (uuid.contains("CLB")) { + ap_payapply.set("shjh_externalsystemdocume","C");//差旅报销单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_s);//对私 + } + }else if (uuid.contains("LWB")) { + ap_payapply.set("shjh_externalsystemdocume","D");//劳务人员报销单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_s);//对私 + } + }else if (uuid.contains("YFK")) { + ap_payapply.set("shjh_externalsystemdocume","E");//预付款单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_g);//对公 + } + }else if (uuid.contains("JCW")) { + ap_payapply.set("shjh_externalsystemdocume","F");//请款单无订单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_g);//对公 + } + }else if (uuid.contains("FWK")) { //服务付款单 + ap_payapply.set("shjh_externalsystemdocume","G"); + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_g);//对公 + } + }else if (uuid.contains("TFK")) { + ap_payapply.set("shjh_externalsystemdocume","I");//其他付款单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_g);//对公 + } + }else if (uuid.contains("SPA")) { + ap_payapply.set("shjh_externalsystemdocume","J");//SPA会员退卡申请单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_g);//对公 + } + }else if (uuid.contains("JCH")) { +// ap_payapply.set("shjh_externalsystemdocume","JC");//TPM_请款单 + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_g);//对公JKY0000001 + } + }else if (uuid.contains("TYH")) { //TPM_通用报销单 +// ap_payapply.set("shjh_externalsystemdocume","TY"); + if (!entry.isEmpty()) { + entry.get(0).set("e_paymenttype", paytype_s);//对私 + } + } + } +} \ No newline at end of file diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyTask.java b/main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyTask.java index 9f1a10d..dd24850 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyTask.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/task/QuerySapCreatePayApplyTask.java @@ -24,9 +24,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import static shjh.jhzj7.fi.fi.plugin.form.SappzFormPlugin.*; import static shjh.jhzj7.fi.fi.utils.SapUtils.vouchers_payable; @@ -34,6 +32,7 @@ import static shjh.jhzj7.fi.fi.webapi.ApplyBillControler.*; /** * 定时调用SAP应付凭证接口生成付款申请单,过滤参数仅为临期 + * 全量类型执行 */ public class QuerySapCreatePayApplyTask extends AbstractTask { @@ -45,6 +44,20 @@ public class QuerySapCreatePayApplyTask extends AbstractTask { // 获取临期天数并转换 String lqBefore = (String) map.get("临期_前"); String lqAfter = (String) map.get("临期_后"); + Set filterSet = new HashSet<>(); + String filterType = (String) map.get("不执行类型"); + + if (filterType != null && !filterType.trim().isEmpty()) { + // 按分号分割,并去除前后空格 + String[] types = filterType.split(";"); + for (String type : types) { + String trimmedType = type.trim(); + if (!trimmedType.isEmpty()) { + filterSet.add(trimmedType); + } + } + } + // 检查是否有有效的临期数据 if (StringUtils.isEmpty(lqBefore) || StringUtils.isEmpty(lqAfter)) { return; @@ -94,7 +107,7 @@ public class QuerySapCreatePayApplyTask extends AbstractTask { if (null != sapdata && sapdata.containsKey("IT_ITEM")) { JSONArray IT_ITEMs = (JSONArray) sapdata.get("IT_ITEM"); if (!IT_ITEMs.isEmpty()) { - payapplys = getPayapply(IT_ITEMs); + payapplys = getPayapply(IT_ITEMs,filterSet); //若多条数据相同,则合并为一条数据处理 OperateOption option = OperateOption.create(); option.setVariableValue(OperateOptionConst.IGNOREWARN, String.valueOf(false)); // 不执行警告级别校验器 @@ -153,7 +166,7 @@ public class QuerySapCreatePayApplyTask extends AbstractTask { /** * 通过SAP接口查询应付凭证数据,并生成应付付款申请单 */ - private Map getPayapply(JSONArray IT_ITEMs){ + private Map getPayapply(JSONArray IT_ITEMs,Set filterSet){ Map bills = new HashMap<>(); JSONObject it_list;//sap单个应付凭证 String shjh_payee = "";//往来类型 @@ -182,6 +195,21 @@ public class QuerySapCreatePayApplyTask extends AbstractTask { for (Object itItem : IT_ITEMs) { it_list = (JSONObject) itItem; + + String uuid = it_list.getString("XBLNR");//单据号 + // 判断uuid是否包含filterSet中的任何字符串 + boolean shouldSkip = false; + for (String filter : filterSet) { + if (uuid.contains(filter)) { + shouldSkip = true; + break; + } + } + + if (shouldSkip) { + continue; // 跳过当前循环 + } + String bukrs = it_list.getString("BUKRS");//公司编号 String fkBillNum = it_list.getString("BELNR");//凭证号 String gjahr = it_list.getString("GJAHR");//会计年度 @@ -573,7 +601,6 @@ public class QuerySapCreatePayApplyTask extends AbstractTask { } } } - String uuid = it_list.getString("XBLNR");//单据号 ap_payapply.set("shjh_fkdjbh", uuid); String bizbig = it_list.getString("ZYWDLCODE");//业务大类编 String bizsmall = it_list.getString("ZYWXLCODE");//业务小类编码