dingsixi 1 неделя назад
Родитель
Сommit
85753a91d1

+ 112 - 26
base/nckd-base-common/src/main/java/nckd/base/common/utils/GzwCommonUtils.java

@@ -4,13 +4,22 @@ import com.alibaba.fastjson.JSONObject;
 import kd.bos.bos.servicehelper.ServiceFactory;
 import kd.bos.bos.servicehelper.ServiceFactory;
 import kd.bos.cache.CacheFactory;
 import kd.bos.cache.CacheFactory;
 import kd.bos.cache.TempFileCache;
 import kd.bos.cache.TempFileCache;
+import kd.bos.coderule.api.CodeRuleInfo;
+import kd.bos.context.RequestContext;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.metadata.IDataEntityType;
+import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
+import kd.bos.db.DB;
 import kd.bos.exception.KDBizException;
 import kd.bos.exception.KDBizException;
 import kd.bos.fileservice.FileService;
 import kd.bos.fileservice.FileService;
 import kd.bos.fileservice.FileServiceFactory;
 import kd.bos.fileservice.FileServiceFactory;
 import kd.bos.fileservice.extension.FileServiceExtFactory;
 import kd.bos.fileservice.extension.FileServiceExtFactory;
 import kd.bos.form.IFormView;
 import kd.bos.form.IFormView;
 import kd.bos.mvc.SessionManager;
 import kd.bos.mvc.SessionManager;
+import kd.bos.servicehelper.AttachmentServiceHelper;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
 import kd.bos.servicehelper.workflow.WorkflowServiceHelper;
 import kd.bos.servicehelper.workflow.WorkflowServiceHelper;
 import kd.bos.url.UrlService;
 import kd.bos.url.UrlService;
 import kd.bos.workflow.component.approvalrecord.IApprovalRecordGroup;
 import kd.bos.workflow.component.approvalrecord.IApprovalRecordGroup;
@@ -40,6 +49,58 @@ import java.util.*;
  */
  */
 public class GzwCommonUtils {
 public class GzwCommonUtils {
 
 
+    /**
+     * @param formId      推送单据标识
+     * @param billNos     推送单据编号
+     * @param isSuccess   是否推送成功
+     * @param pushParam   推送报文
+     * @param returnParam 返回报文
+     * @param file        推送文件
+     * @return 创建推送日志
+     */
+    public static Map<String, Object> createPushLogDynamic(String formId, String billNos, Boolean isSuccess, String pushParam, String returnParam, File file) {
+        Map<String, Object> logMap = new HashMap<>();
+        DynamicObject log = BusinessDataServiceHelper.newDynamicObject("nckd_em_pushlog");
+        Long id = DB.genLongId(formId);
+        CodeRuleInfo codeRule = CodeRuleServiceHelper.getCodeRule(log.getDataEntityType().getName(), log, null);
+        log.set("id", id);
+        log.set("billno", CodeRuleServiceHelper.getNumber(codeRule, log));
+        log.set("billstatus", "C");
+        log.set("nckd_entityobject", formId);
+        log.set("nckd_bizbillnos", billNos);
+        log.set("nckd_pushuser", RequestContext.get().getCurrUserId());
+        log.set("nckd_pushtime", new Date());
+        log.set("nckd_pushstatus", isSuccess ? "success" : "error");
+        log.set("nckd_pushparam", "点击查看报文");
+        log.set("nckd_pushparam_tag", pushParam);
+        log.set("nckd_returnparam", "点击查看报文");
+        log.set("nckd_returnparam_tag", returnParam);
+        logMap.put("log", log);
+        if (file != null) {
+            //保存单据附件面板
+            //注册文件服务
+            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
+            try {
+                String name = file.getName();
+                byte[] bytes = Files.readAllBytes(file.toPath());
+                String tempUrl = cache.saveAsUrl(name, bytes, 60 * 60 * 4);
+                String uid = "rc-upload-" + System.currentTimeMillis();
+                Map<String, Object> attachmentInfoMap = new HashMap<>(1);
+                Map<String, Object> fileInfo = new HashMap<>(8);
+                fileInfo.put("uid", uid);
+                fileInfo.put("url", tempUrl);
+                fileInfo.put("name", name);
+                fileInfo.put("size", bytes.length);
+                fileInfo.put("type", name.split("\\.")[1]);
+                attachmentInfoMap.put("attachmentpanel", Collections.singletonList(fileInfo));
+                logMap.put("logAttr", attachmentInfoMap);
+            } catch (Exception e) {
+                throw new KDBizException("生成推送日志失败:" + e);
+            }
+        }
+        return logMap;
+    }
+
     /**
     /**
      * @param sysCtrlParameter 系统参数
      * @param sysCtrlParameter 系统参数
      * @param zipFile          zip文件
      * @param zipFile          zip文件
@@ -68,7 +129,7 @@ public class GzwCommonUtils {
     public final static String FILEPATH = "gzw/";
     public final static String FILEPATH = "gzw/";
 
 
     /**
     /**
-     * @param orgCode          企业统一社会信用代码
+     * @param uscc             集团统一社会信用代码
      * @param ver              版本号
      * @param ver              版本号
      * @param cusDateStr       当前时间
      * @param cusDateStr       当前时间
      * @param xmlMap           单据XML动态参数  key=资源代号  value = 动态参数
      * @param xmlMap           单据XML动态参数  key=资源代号  value = 动态参数
@@ -76,7 +137,7 @@ public class GzwCommonUtils {
      * @param apiCode          接口代号
      * @param apiCode          接口代号
      * @return 将单据数据动态参数生成XML文件,附件转为FIle文件,合并生成zip文件
      * @return 将单据数据动态参数生成XML文件,附件转为FIle文件,合并生成zip文件
      */
      */
-    public static File createZipFile(String orgCode, String ver, String cusDateStr, Map<String, Object> xmlMap,
+    public static File createZipFile(String uscc, String ver, String cusDateStr, Map<String, Object> xmlMap,
                                      List<File> billAttrFileList, String apiCode) {
                                      List<File> billAttrFileList, String apiCode) {
         //单据XMl参数为空
         //单据XMl参数为空
         if (xmlMap.isEmpty()) {
         if (xmlMap.isEmpty()) {
@@ -85,12 +146,12 @@ public class GzwCommonUtils {
         List<File> xmlFileList = new ArrayList<>();
         List<File> xmlFileList = new ArrayList<>();
         //生成单据数据XML文件
         //生成单据数据XML文件
         for (Map.Entry<String, Object> entry : xmlMap.entrySet()) {
         for (Map.Entry<String, Object> entry : xmlMap.entrySet()) {
-            File xmlFile = GzwCommonUtils.createXMLFile(orgCode, entry.getKey(), ver, cusDateStr, (List<LinkedHashMap<String, Object>>) entry.getValue());
+            File xmlFile = GzwCommonUtils.createXMLFile(uscc, entry.getKey(), ver, cusDateStr, (List<LinkedHashMap<String, Object>>) entry.getValue());
             xmlFileList.add(xmlFile);
             xmlFileList.add(xmlFile);
         }
         }
 
 
         //生成ZIP文件名称
         //生成ZIP文件名称
-        String zipFileName = GzwCommonUtils.generateFileName(orgCode, apiCode, ver, cusDateStr, GzwXmlUtils.ZIP);
+        String zipFileName = GzwCommonUtils.generateFileName(uscc, apiCode, ver, cusDateStr, GzwXmlUtils.ZIP);
 
 
         //单据XML文件、单据附件File文件合并生成zip文件
         //单据XML文件、单据附件File文件合并生成zip文件
         File zip = GzwXmlUtils.createZipWithAttachments(xmlFileList, billAttrFileList, zipFileName);
         File zip = GzwXmlUtils.createZipWithAttachments(xmlFileList, billAttrFileList, zipFileName);
@@ -103,7 +164,7 @@ public class GzwCommonUtils {
     }
     }
 
 
     /**
     /**
-     * @param orgCode    企业统一社会信用代码
+     * @param orgCode    集团统一社会信用代码
      * @param resCode    资源代号
      * @param resCode    资源代号
      * @param ver        版本号
      * @param ver        版本号
      * @param cusDateStr 当前时间
      * @param cusDateStr 当前时间
@@ -143,11 +204,12 @@ public class GzwCommonUtils {
      * @param auditResMap  业务审批记录资源代号信息
      * @param auditResMap  业务审批记录资源代号信息
      * @param dataFlag     数据标识
      * @param dataFlag     数据标识
      * @param org          单据组织
      * @param org          单据组织
+     * @param uscc         集团社会统一代码
      * @param auditResCode 业务审批记录资源代号
      * @param auditResCode 业务审批记录资源代号
      * @param xmlMap       单据XML参数
      * @param xmlMap       单据XML参数
      */
      */
     public static void getBillApprovalRecordsData(DynamicObject bill, Map<String, String> auditResMap, String dataFlag,
     public static void getBillApprovalRecordsData(DynamicObject bill, Map<String, String> auditResMap, String dataFlag,
-                                                  DynamicObject org, String auditResCode, Map<String, Object> xmlMap) {
+                                                  DynamicObject org, String uscc, String auditResCode, Map<String, Object> xmlMap) {
 
 
         //获取单据审批记录
         //获取单据审批记录
         List<IApprovalRecordGroup> approvalRecords = WorkflowServiceHelper.getApprovalRecords(bill.getDynamicObjectType().getName(), bill.getPkValue().toString(), false);
         List<IApprovalRecordGroup> approvalRecords = WorkflowServiceHelper.getApprovalRecords(bill.getDynamicObjectType().getName(), bill.getPkValue().toString(), false);
@@ -158,7 +220,7 @@ public class GzwCommonUtils {
         //将审批记录格式化为map对象
         //将审批记录格式化为map对象
         List<Map<String, Object>> approvalRecordForFormat = getApprovalRecordForFormat(approvalRecords);
         List<Map<String, Object>> approvalRecordForFormat = getApprovalRecordForFormat(approvalRecords);
 
 
-        Map<String, Object> fixedData = GzwCommonUtils.getFixedData(auditResMap, org, dataFlag);
+        Map<String, Object> fixedData = GzwCommonUtils.getFixedData(auditResMap, org, uscc, dataFlag);
 
 
         //当前附件表资源代号对应的XMl参数信息
         //当前附件表资源代号对应的XMl参数信息
         List<LinkedHashMap<String, Object>> existingAttachData =
         List<LinkedHashMap<String, Object>> existingAttachData =
@@ -194,11 +256,12 @@ public class GzwCommonUtils {
      * @param allAttachFiles 当前组织下所有的附件信息
      * @param allAttachFiles 当前组织下所有的附件信息
      * @param attrResCode    附件表资源代号
      * @param attrResCode    附件表资源代号
      * @param xmlMap         当前组织下所有的xml文件
      * @param xmlMap         当前组织下所有的xml文件
+     * @param uscc           集团统一社会信用
      */
      */
     public static void getBillAttrDataAndFile(Map<String, List<Map<String, Object>>> billAttrMap, DynamicObject bill,
     public static void getBillAttrDataAndFile(Map<String, List<Map<String, Object>>> billAttrMap, DynamicObject bill,
                                               Map<String, String> attrResMap, String dataFlag, DynamicObject org,
                                               Map<String, String> attrResMap, String dataFlag, DynamicObject org,
                                               List<File> allAttachFiles, String attrResCode, Map<String, Object> xmlMap,
                                               List<File> allAttachFiles, String attrResCode, Map<String, Object> xmlMap,
-                                              String attachmentServer) {
+                                              String attachmentServer, String uscc) {
         // 获取当前单据附件信息
         // 获取当前单据附件信息
         List<Map<String, Object>> billAttachments = billAttrMap.getOrDefault(
         List<Map<String, Object>> billAttachments = billAttrMap.getOrDefault(
                 bill.getString("id"),
                 bill.getString("id"),
@@ -214,7 +277,7 @@ public class GzwCommonUtils {
 
 
         //将单据附件信息转成动态参数及File文件
         //将单据附件信息转成动态参数及File文件
         GzwCommonUtils.getBillAttrDataAndFile(billAttachments, allAttachFiles, existingAttachData,
         GzwCommonUtils.getBillAttrDataAndFile(billAttachments, allAttachFiles, existingAttachData,
-                GzwCommonUtils.getFixedData(attrResMap, org, dataFlag), attachmentServer);
+                GzwCommonUtils.getFixedData(attrResMap, org, uscc, dataFlag), attachmentServer);
 
 
         //更新附件XML参数
         //更新附件XML参数
         xmlMap.put(attrResCode, existingAttachData);
         xmlMap.put(attrResCode, existingAttachData);
@@ -241,7 +304,7 @@ public class GzwCommonUtils {
             //将单据附件转为File对象
             //将单据附件转为File对象
             File file = generateBillAttrToFile(fileMap, attachmentFileService);
             File file = generateBillAttrToFile(fileMap, attachmentFileService);
             //重新设置附件信息名称 文件名称添加MD5前缀
             //重新设置附件信息名称 文件名称添加MD5前缀
-            fileMap.put("name",file.getName());
+            fileMap.put("name", file.getName());
             billAttrFileList.add(file);
             billAttrFileList.add(file);
 
 
             //附件动态参数
             //附件动态参数
@@ -261,7 +324,6 @@ public class GzwCommonUtils {
         attrMap.put("uuid", fileMap.get("uid"));
         attrMap.put("uuid", fileMap.get("uid"));
         attrMap.put("biz_uuid", fileMap.get("billPkId"));
         attrMap.put("biz_uuid", fileMap.get("billPkId"));
         attrMap.put("file_name", fileMap.get("name"));
         attrMap.put("file_name", fileMap.get("name"));
-        //TODO mc参数未配置正确
         attrMap.put("file_path", attachmentServer + fileMap.get("url").toString().split("path=")[1]);
         attrMap.put("file_path", attachmentServer + fileMap.get("url").toString().split("path=")[1]);
         attrMap.put("file_type", fileMap.get("type"));
         attrMap.put("file_type", fileMap.get("type"));
         attrMap.put("create_time", DateUtil.date2str((Date) fileMap.get("lastModified"), DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
         attrMap.put("create_time", DateUtil.date2str((Date) fileMap.get("lastModified"), DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
@@ -311,24 +373,48 @@ public class GzwCommonUtils {
     }
     }
 
 
     /**
     /**
-     * @param operationKey 操作标识
-     * @param obj          业务数据
+     * @param obj 业务数据
      * @return 获取数据标识( 1  表示新增,2 表示修改,3  表示删除 ),默认为 1
      * @return 获取数据标识( 1  表示新增,2 表示修改,3  表示删除 ),默认为 1
      */
      */
-    public static String getDataFlag(String operationKey, DynamicObject obj) {
-        //删除 = 3 ,非删除从数据库取出来得数据则是修改=2,不是从数据库取出的则是新增 = 1 。 根据数据判断
-//        return operationKey.equals(OperationKeyConst.DELETE) ? "3" : obj.getDataEntityState().getFromDatabase() ? "2" : "1";
-        //删除 = 3,非删除是否推送国资委为false = 新增 ,true为修改。根据字段值判断
-        return operationKey.equals(OperationKeyConst.DELETE) ? "3" : obj.getBoolean("nckd_ispush") ? "2" : "1";
+    public static String getDataFlag(DynamicObject obj,String pushState) {
+        //是否推送
+        boolean isPush = obj.getBoolean("nckd_ispush");
+        //元数据
+        IDataEntityType dataEntityType = obj.getDataEntityType();
+        //字段属性
+        DataEntityPropertyCollection properties = dataEntityType.getProperties();
+        //获取单据状态标识
+        String statusSign = properties.containsKey("status") ? "status" : "billstatus";
+        //获取单据编码
+        String numberSign = properties.containsKey("number") ? "number" : "billno";
+        //单据已审核 且 未推送单据  标识 = 新增。  如果已推送,说明不需要再次推送
+        if ((obj.getString(statusSign).equals("C") || obj.getString(statusSign).equals("E")) && !isPush) {
+            if(pushState.equals("ZCTS")){
+                //设置已推送
+                obj.set("nckd_ispush", Boolean.TRUE);
+            }
+            return "1";
+        }
+        //单据非已审核 且 已推送 标识=删除。 如果未推送,说明数据还未审核过 或者 已进行过删除,也不需要再次推送
+        if (!obj.getString(statusSign).equals("C") && !obj.getString(statusSign).equals("E") && isPush) {
+            if(pushState.equals("ZCTS")){
+                //设置未推送
+                obj.set("nckd_ispush", Boolean.FALSE);
+            }
+            return "3";
+        }
+        //审核发起接口进行新增,反审核接口发起失败,不存在修改操作。
+        throw new KDBizException(String.format("%s,单据编号:%s,不满足推送条件,无法推送", dataEntityType.getDisplayName(), obj.getString(numberSign)));
     }
     }
 
 
     /**
     /**
      * @param resMap   国资委采集平台对应的表名(文档提供)
      * @param resMap   国资委采集平台对应的表名(文档提供)
      * @param org      业务单元
      * @param org      业务单元
-     * @param dataFlag 数据标识 ( 1  表示新增,2 表示修改,3  表示删除 ),默认为 1
+     * @param uscc     集团统一社会信用代码
+     * @param dataFlag 数据标识 ( 1  表示新增,2 表示修改,3  表示删除 ),根据单据数据判断,未推送数据推送为1,已推送数据再次推送为2,删除为3
      * @return XML固定参数内容 不要动key值,固定参数
      * @return XML固定参数内容 不要动key值,固定参数
      */
      */
-    public static Map<String, Object> getFixedData(Map<String, String> resMap, DynamicObject org, String dataFlag) {
+    public static Map<String, Object> getFixedData(Map<String, String> resMap, DynamicObject org, String uscc, String dataFlag) {
         //单位编码 统一社会信用代码
         //单位编码 统一社会信用代码
         String code = org.getString("uniformsocialcreditcode");
         String code = org.getString("uniformsocialcreditcode");
         //单位名称
         //单位名称
@@ -337,11 +423,11 @@ public class GzwCommonUtils {
 
 
         //资源简称
         //资源简称
         fixedData.put("resCaption", resMap.get("nckd_rescaption"));
         fixedData.put("resCaption", resMap.get("nckd_rescaption"));
-        //上报单位 编 码
+        //资源代号
         fixedData.put("resCode", resMap.get("nckd_rescode"));
         fixedData.put("resCode", resMap.get("nckd_rescode"));
-        //上报单位 编 码
-        fixedData.put("EXT_REPORTSOCIALCODE", code);
-        //单 位 编 码
+        //上报单位 编 码(集团)
+        fixedData.put("EXT_REPORTSOCIALCODE", uscc);
+        //单 位 编 码(实际业务单据单位)
         fixedData.put("EXT_CORPSOCIALCODE", code);
         fixedData.put("EXT_CORPSOCIALCODE", code);
         //数据标识
         //数据标识
         fixedData.put("EXT_DATAFLAG", dataFlag);
         fixedData.put("EXT_DATAFLAG", dataFlag);
@@ -422,7 +508,7 @@ public class GzwCommonUtils {
     }
     }
 
 
     /**
     /**
-     * @param orgCode    业务单元.统一社会信用代码
+     * @param orgCode    集团统一社会信用代码
      * @param resCode    接口代号/资源代号
      * @param resCode    接口代号/资源代号
      * @param ver        版本号
      * @param ver        版本号
      * @param cusDateStr 当前时间
      * @param cusDateStr 当前时间
@@ -616,7 +702,7 @@ public class GzwCommonUtils {
             throw new RuntimeException(ex);
             throw new RuntimeException(ex);
         }
         }
         //审批流程无法获取
         //审批流程无法获取
-        if(ObjectUtils.isEmpty(sessions)){
+        if (ObjectUtils.isEmpty(sessions)) {
             return null;
             return null;
         }
         }
         //取第一个视图,随便取的,不知道是不是当前页面操作的视图,其他场景使用自己考虑,只用来操作插件下载文件
         //取第一个视图,随便取的,不知道是不是当前页面操作的视图,其他场景使用自己考虑,只用来操作插件下载文件

+ 72 - 15
base/nckd-base-common/src/main/java/nckd/base/common/utils/GzwSyncBillUtils.java

@@ -3,6 +3,8 @@ package nckd.base.common.utils;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import nckd.base.common.constant.BaseFieldConst;
 import nckd.base.common.constant.BaseFieldConst;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.*;
@@ -119,25 +121,25 @@ public class GzwSyncBillUtils {
         String chiefGuestName = dailyApply.getString("nckd_lfzbxm");
         String chiefGuestName = dailyApply.getString("nckd_lfzbxm");
         //来访主宾职务
         //来访主宾职务
         String chiefGuestTitle = dailyApply.getString("nckd_zw");
         String chiefGuestTitle = dailyApply.getString("nckd_zw");
-
+        //用餐类型
+        String type = dailyApply.getString("nckd_combofield");
         //费用明细
         //费用明细
         DynamicObjectCollection entryEntity = dailyApply.getDynamicObjectCollection("expenseentryentity");
         DynamicObjectCollection entryEntity = dailyApply.getDynamicObjectCollection("expenseentryentity");
-        //宴请人均标准  TODO 6 = 其他 ,系统内没有宴请的招待项目
-        DynamicObject yqEntry = entryEntity.stream().filter(it -> it.getString("treatway").equals("6")).findAny().orElse(null);
-        BigDecimal yqPerAvgStd = yqEntry.getBigDecimal("nckd_decimalfield");
+        //宴请人均标准
+        DynamicObject yqEntry = entryEntity.stream().filter(it -> ObjectUtils.isNotEmpty(it.get("treatway")) && type.equals("1") && it.getString("treatway").equals("1")).findAny().orElse(null);
+        BigDecimal yqPerAvgStd = null == yqEntry ? BigDecimal.ZERO : yqEntry.getBigDecimal("nckd_decimalfield");
         //日常用餐人均标准
         //日常用餐人均标准
-        DynamicObject rcycEntry = entryEntity.stream().filter(it -> it.getString("treatway").equals("1")).findAny().orElse(null);
-        BigDecimal rcycPerAvgStd = rcycEntry.getBigDecimal("nckd_decimalfield");
+        DynamicObject rcycEntry = entryEntity.stream().filter(it -> ObjectUtils.isNotEmpty(it.get("treatway")) && type.equals("2") && it.getString("treatway").equals("1")).findAny().orElse(null);
+        BigDecimal rcycPerAvgStd = null == rcycEntry ? BigDecimal.ZERO :  rcycEntry.getBigDecimal("nckd_decimalfield");
         //住宿人均标准
         //住宿人均标准
-        DynamicObject zsEntry = entryEntity.stream().filter(it -> it.getString("treatway").equals("2")).findAny().orElse(null);
-        BigDecimal zsPerAvgStd = zsEntry.getBigDecimal("nckd_decimalfield");
-
+        DynamicObject zsEntry = entryEntity.stream().filter(it -> ObjectUtils.isNotEmpty(it.get("treatway")) && it.getString("treatway").equals("2")).findAny().orElse(null);
+        BigDecimal zsPerAvgStd = null == zsEntry ? BigDecimal.ZERO : zsEntry.getBigDecimal("nckd_decimalfield");
         //纪念品人均标准
         //纪念品人均标准
-        DynamicObject jnpEntry = entryEntity.stream().filter(it -> it.getString("treatway").equals("4")).findAny().orElse(null);
-        BigDecimal jnpPerAvgStd = jnpEntry.getBigDecimal("nckd_decimalfield");
+        DynamicObject jnpEntry = entryEntity.stream().filter(it -> ObjectUtils.isNotEmpty(it.get("treatway")) && it.getString("treatway").equals("4")).findAny().orElse(null);
+        BigDecimal jnpPerAvgStd = null == jnpEntry ? BigDecimal.ZERO : jnpEntry.getBigDecimal("nckd_decimalfield");
         //用车数量
         //用车数量
-        DynamicObject ycEntry = entryEntity.stream().filter(it -> it.getString("treatway").equals("5")).findAny().orElse(null);
-        BigDecimal ycQty = ycEntry.getBigDecimal("nckd_integerfield");
+        DynamicObject ycEntry = entryEntity.stream().filter(it -> ObjectUtils.isNotEmpty(it.get("treatway")) && it.getString("treatway").equals("5")).findAny().orElse(null);
+        BigDecimal ycQty = null == ycEntry ? BigDecimal.ZERO : ycEntry.getBigDecimal("nckd_integerfield");
 
 
 
 
         LinkedHashMap<String, Object> dynamicData = new LinkedHashMap<>();
         LinkedHashMap<String, Object> dynamicData = new LinkedHashMap<>();
@@ -300,7 +302,7 @@ public class GzwSyncBillUtils {
             //结束时间
             //结束时间
             Date endDate = entry.getDate("nckd_enddate");
             Date endDate = entry.getDate("nckd_enddate");
             //天数
             //天数
-            int day = DateUtil.daysBetweenIfBlankReturnZero(startDate, endDate)+1;
+            int day = DateUtil.daysBetweenIfBlankReturnZero(startDate, endDate) + 1;
             //是否在食堂用餐
             //是否在食堂用餐
             boolean isCafeteria = entry.getBoolean("nckd_iscafeteria");
             boolean isCafeteria = entry.getBoolean("nckd_iscafeteria");
 
 
@@ -363,7 +365,7 @@ public class GzwSyncBillUtils {
             //结束时间
             //结束时间
             Date endDate = entry.getDate("nckd_enddate");
             Date endDate = entry.getDate("nckd_enddate");
             //天数
             //天数
-            int day = DateUtil.daysBetweenIfBlankReturnZero(startDate, endDate)+1;
+            int day = DateUtil.daysBetweenIfBlankReturnZero(startDate, endDate) + 1;
 
 
             LinkedHashMap<String, Object> data = new LinkedHashMap<>();
             LinkedHashMap<String, Object> data = new LinkedHashMap<>();
             data.put("uuid", entryId);
             data.put("uuid", entryId);
@@ -419,4 +421,59 @@ public class GzwSyncBillUtils {
         }
         }
         return dataList;
         return dataList;
     }
     }
+
+    /**
+     * @param billAttrMap 单据附件信息
+     * @param maxSize     最大值MAX分组标准
+     * @param bills       单据数据
+     * @return 每组不超过500MB
+     */
+    public static List<List<Long>> groupIds(Map<String, List<Map<String, Object>>> billAttrMap, Long maxSize, DynamicObject[] bills) {
+        //找出没有附件信息的单据,默认给个长度
+        List<Map<String, Object>> collect = Arrays.stream(bills).filter(it -> !billAttrMap.containsKey(it.getString("id")))
+                .map(it -> {
+                    Map<String, Object> billSizeMap = new HashMap<>();
+                    billSizeMap.put("billPkId", it.getString("id"));
+                    billSizeMap.put("size", "1");
+                    return billSizeMap;
+                })
+                .collect(Collectors.toList());
+        //找出有附件的单据信息
+        List<Map<String, Object>> list = billAttrMap.values().stream().flatMap(it -> it.stream())
+                .collect(Collectors.toList());
+        //合并附件信息进行分组
+        list.addAll(collect);
+
+        // 直接处理原始数据,保持顺序
+        List<List<Long>> groups = new ArrayList<>();
+        List<Long> currentGroup = new ArrayList<>();
+        long currentGroupSize = 0;
+
+        for (Map<String, Object> map : list) {
+            long id = Long.parseLong(map.get("billPkId").toString());
+            long size = Long.parseLong(map.get("size").toString());
+
+            // 检查当前组是否能容纳
+            if (currentGroupSize + size <= maxSize) {
+                currentGroup.add(id);
+                currentGroupSize += size;
+            } else {
+                // 不能容纳,保存当前组并开始新组
+                if (!currentGroup.isEmpty()) {
+                    groups.add(new ArrayList<>(currentGroup));
+                }
+                currentGroup = new ArrayList<>();
+                currentGroup.add(id);
+                currentGroupSize = size;
+            }
+        }
+
+        // 添加最后一组
+        if (!currentGroup.isEmpty()) {
+            groups.add(currentGroup);
+        }
+
+        return groups;
+    }
+
 }
 }

+ 0 - 6
nckd-fi/src/main/java/nckd/fi/er/opplugin/BizPolicyPushOpPlugin.java

@@ -38,12 +38,6 @@ public class BizPolicyPushOpPlugin extends GzwPushOpPlugin {
         return "nckd_attachmentpanelap";
         return "nckd_attachmentpanelap";
     }
     }
 
 
-    @Override
-    protected String getOrgCode(DynamicObject bill) {
-        //社会统一信用代码
-        return bill.getString("nckd_code");
-    }
-
     @Override
     @Override
     protected DynamicObject getBillOrg(DynamicObject bill) {
     protected DynamicObject getBillOrg(DynamicObject bill) {
         //单据组织字段
         //单据组织字段

+ 0 - 6
nckd-fi/src/main/java/nckd/fi/er/opplugin/DailyApplyPushOpPlugin.java

@@ -38,12 +38,6 @@ public class DailyApplyPushOpPlugin extends GzwPushOpPlugin{
         return "attachmentpanel";
         return "attachmentpanel";
     }
     }
 
 
-    @Override
-    protected String getOrgCode(DynamicObject bill) {
-        //费用承担公司.社会统一信用代码 TODO 保存提交校验费用承担公司统一社会信息代码不允许为空
-        return bill.getString("costcompany.uniformsocialcreditcode");
-    }
-
     @Override
     @Override
     protected DynamicObject getBillOrg(DynamicObject bill) {
     protected DynamicObject getBillOrg(DynamicObject bill) {
         //费用承担公司
         //费用承担公司

+ 0 - 6
nckd-fi/src/main/java/nckd/fi/er/opplugin/EntertainmentPushOpPlugin.java

@@ -70,12 +70,6 @@ public class EntertainmentPushOpPlugin extends GzwPushOpPlugin {
         return "nckd_attachmentpanelap";
         return "nckd_attachmentpanelap";
     }
     }
 
 
-    @Override
-    protected String getOrgCode(DynamicObject bill) {
-        //公司.社会统一信用代码
-        return bill.getString("costcompany.uniformsocialcreditcode");
-    }
-
 
 
     @Override
     @Override
     protected DynamicObject getBillOrg(DynamicObject bill) {
     protected DynamicObject getBillOrg(DynamicObject bill) {

+ 121 - 74
nckd-fi/src/main/java/nckd/fi/er/opplugin/GzwPushOpPlugin.java

@@ -1,35 +1,19 @@
 package nckd.fi.er.opplugin;
 package nckd.fi.er.opplugin;
 
 
-import kd.bos.base.BaseShowParameter;
-import kd.bos.bill.BillShowParameter;
-import kd.bos.cache.CacheFactory;
-import kd.bos.cache.TempFileCache;
+import com.alibaba.fastjson.JSONObject;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObject;
-import kd.bos.entity.MainEntityType;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.PreparePropertysEventArgs;
 import kd.bos.entity.plugin.PreparePropertysEventArgs;
-import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
 import kd.bos.exception.KDBizException;
 import kd.bos.exception.KDBizException;
-import kd.bos.exception.KDException;
-import kd.bos.form.FormShowParameter;
-import kd.bos.form.IFormView;
-import kd.bos.mvc.FormConfigFactory;
-import kd.bos.mvc.SessionManager;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
 import kd.bos.servicehelper.AttachmentServiceHelper;
 import kd.bos.servicehelper.AttachmentServiceHelper;
-import kd.bos.servicehelper.MetadataServiceHelper;
-import kd.bos.servicehelper.workflow.WorkflowServiceHelper;
-import kd.bos.workflow.component.approvalrecord.IApprovalRecordGroup;
-import nckd.base.common.utils.GzwCommonUtils;
-import nckd.base.common.utils.GzwSyncBillUtils;
-import nckd.base.common.utils.HttpUtils;
-import nckd.base.common.utils.ParamUtils;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import nckd.base.common.utils.*;
 import nckd.base.common.config.ResCodeConfig;
 import nckd.base.common.config.ResCodeConfig;
-import org.apache.commons.lang3.ObjectUtils;
 
 
 import java.io.File;
 import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.nio.file.Files;
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -39,6 +23,8 @@ import java.util.stream.Collectors;
  * @create: 2025/12/24 17:24
  * @create: 2025/12/24 17:24
  */
  */
 public abstract class GzwPushOpPlugin extends AbstractOperationServicePlugIn {
 public abstract class GzwPushOpPlugin extends AbstractOperationServicePlugIn {
+    private final static Log logger = LogFactory.getLog(GzwPushOpPlugin.class);
+
 
 
     @Override
     @Override
     public void onPreparePropertys(PreparePropertysEventArgs e) {
     public void onPreparePropertys(PreparePropertysEventArgs e) {
@@ -47,31 +33,49 @@ public abstract class GzwPushOpPlugin extends AbstractOperationServicePlugIn {
     }
     }
 
 
     @Override
     @Override
-    public void endOperationTransaction(EndOperationTransactionArgs e) {
-        super.endOperationTransaction(e);
-        DynamicObject[] dataEntities = e.getDataEntities();
-        pushGzw(dataEntities, e);
+    public void afterExecuteOperationTransaction(AfterOperationArgs args) {
+        super.afterExecuteOperationTransaction(args);
+        //事务结束后执行。不影响单据流程
+        DynamicObject[] dataEntities = args.getDataEntities();
+        try {
+            pushGzw(dataEntities);
+        } catch (Exception e) {
+            logger.info(String.format("%s推送国资委接口内部异常:%s", this.billEntityType.getDisplayName().getLocaleValue(), e));
+            //是否显示异常信息
+            Boolean isShowMsg = (Boolean) ParamUtils.getSysCtrlParameter(ParamUtils.EM, "nckd_isshowmsg");
+            if (isShowMsg) {
+                throw new KDBizException("此提示不影响业务流程,推送国资委接口内部异常:" + Arrays.stream(e.getStackTrace())
+                        .map(StackTraceElement::toString)
+                        .collect(Collectors.joining("\n    at ",
+                                e.toString() + "\n    at ",
+                                "")));
+            }
+        }
     }
     }
 
 
     /**
     /**
-     * 推送国资委数据采集平台统一方法
+     * @param bills 业务单据数据
      */
      */
-    protected void pushGzw(DynamicObject[] bills, EndOperationTransactionArgs e) {
-        // 获取当前时间
-        String cusDateStr = GzwCommonUtils.getCusDateStr();
-
+    protected void pushGzw(DynamicObject[] bills) {
         // 获取费控系统参数
         // 获取费控系统参数
         Map<String, Object> sysCtrlParameter = ParamUtils.getSysCtrlParameter(ParamUtils.EM);
         Map<String, Object> sysCtrlParameter = ParamUtils.getSysCtrlParameter(ParamUtils.EM);
         String pushState = (String) sysCtrlParameter.get("nckd_gzwpushstate");
         String pushState = (String) sysCtrlParameter.get("nckd_gzwpushstate");
         //关闭推送
         //关闭推送
         if (pushState.equals("GBTS")) {
         if (pushState.equals("GBTS")) {
+            logger.info("系统参数.推送状态设置为关闭推送,结束推送");
             return;
             return;
         }
         }
+        String billNoSign = bills[0].getDataEntityType().getProperties().containsKey("billno") ? "billno" : "number";
+        logger.info(String.format("%s推送国资委接口开始,推送单据编号:%s", this.billEntityType.getDisplayName().getLocaleValue(),
+                Arrays.stream(bills).map(it -> it.getString(billNoSign)).collect(Collectors.joining(","))));
 
 
+        // 获取当前时间
+        String cusDateStr = GzwCommonUtils.getCusDateStr();
+        //集团统一社会信用代码
+        String uscc = (String) sysCtrlParameter.get("nckd_uscc");
         // 获取接口代号和版本号
         // 获取接口代号和版本号
         String ver = (String) sysCtrlParameter.get("nckd_ver");
         String ver = (String) sysCtrlParameter.get("nckd_ver");
         String apiCode = getApiCode(sysCtrlParameter);
         String apiCode = getApiCode(sysCtrlParameter);
-
         // 获取单据对应的所有资源代号信息
         // 获取单据对应的所有资源代号信息
         List<ResCodeConfig> datasetConfigs = getDatasetConfigs(sysCtrlParameter);
         List<ResCodeConfig> datasetConfigs = getDatasetConfigs(sysCtrlParameter);
         //获取资源代号信息 附件信息
         //获取资源代号信息 附件信息
@@ -82,9 +86,11 @@ public abstract class GzwPushOpPlugin extends AbstractOperationServicePlugIn {
         Map<String, String> auditResMap = GzwCommonUtils.getResMap(GzwSyncBillUtils.BIZ_APPROVE_RECORD, (String) sysCtrlParameter.get("nckd_res"));
         Map<String, String> auditResMap = GzwCommonUtils.getResMap(GzwSyncBillUtils.BIZ_APPROVE_RECORD, (String) sysCtrlParameter.get("nckd_res"));
         //业务审批记录资源代号
         //业务审批记录资源代号
         String auditResCode = auditResMap.get("nckd_rescode");
         String auditResCode = auditResMap.get("nckd_rescode");
-        //文件服务器
+        //文件服务器地址
         String attachmentServer = (String) sysCtrlParameter.get("nckd_attachmentserver");
         String attachmentServer = (String) sysCtrlParameter.get("nckd_attachmentserver");
-
+        //接口数据文件最大M分组标准
+        Long maxSize = Long.parseLong(sysCtrlParameter.get("nckd_maxsize").toString()) * 1024L * 1024L;
+        logger.info("系统参数获取完成");
 
 
         // 获取所有单据附件
         // 获取所有单据附件
         Object[] ids = Arrays.stream(bills).map(it -> it.getString("id")).toArray();
         Object[] ids = Arrays.stream(bills).map(it -> it.getString("id")).toArray();
@@ -94,87 +100,133 @@ public abstract class GzwPushOpPlugin extends AbstractOperationServicePlugIn {
                 getAttachmentPanelField(),
                 getAttachmentPanelField(),
                 Boolean.FALSE
                 Boolean.FALSE
         );
         );
-
-        // 根据组织统一社会信息代码分组
-        Map<String, List<DynamicObject>> billsByOrgCode = Arrays.stream(bills)
-                .collect(Collectors.groupingBy(this::getOrgCode));
-
-        for (Map.Entry<String, List<DynamicObject>> entry : billsByOrgCode.entrySet()) {
-            //统一社会信用代码
-            String orgCode = entry.getKey();
-            List<DynamicObject> billList = entry.getValue();
-
+        logger.info("获取单据附件信息完成");
+
+        //附件大小分组
+        List<List<Long>> lists = GzwSyncBillUtils.groupIds(billAttrMap, maxSize, bills);
+        logger.info(String.format("根据单据附件大小标准分组完成,分组批次:%s,开始执行单据接口参数转换......", lists.size()));
+
+        //记录推送成功单据
+        List<DynamicObject> successList = new ArrayList<>();
+        //推送日志
+        List<Map<String, Object>> logList = new ArrayList<>();
+        // 遍历分组单据id
+        for (List<Long> list : lists) {
             // 构建所有数据集的数据
             // 构建所有数据集的数据
             Map<String, Object> xmlMap = new HashMap<>();
             Map<String, Object> xmlMap = new HashMap<>();
             //单据所有附件
             //单据所有附件
             List<File> allAttachFiles = new ArrayList<>();
             List<File> allAttachFiles = new ArrayList<>();
 
 
-            // 处理每张单据
+            //找到对应的分组单据
+            List<DynamicObject> billList = Arrays.stream(bills).filter(it -> list.contains(it.getLong("id"))).collect(Collectors.toList());
+            String billNos = billList.stream().map(it -> it.getString(billNoSign)).collect(Collectors.joining(","));
+            logger.info(String.format("当前批次推送单据编号:%s", billNos));
+
             for (DynamicObject bill : billList) {
             for (DynamicObject bill : billList) {
+                logger.info(String.format("推送单据编号%s", bill.getString(billNoSign)));
                 DynamicObject org = getBillOrg(bill);
                 DynamicObject org = getBillOrg(bill);
-                String dataFlag = GzwCommonUtils.getDataFlag(e.getOperationKey(), bill);
-
+                String dataFlag = GzwCommonUtils.getDataFlag(bill,pushState);
+                logger.info(String.format("推送单据编号%s,数据标识:%s", bill.getString(billNoSign), dataFlag));
                 // 处理每个资源代号
                 // 处理每个资源代号
                 for (ResCodeConfig config : datasetConfigs) {
                 for (ResCodeConfig config : datasetConfigs) {
+                    logger.info(String.format("推送单据编号%s,资源代号:%s,开始转换XML参数", bill.getString(billNoSign), config.getResCode()));
 
 
                     // 获取该数据集的数据
                     // 获取该数据集的数据
                     List<LinkedHashMap<String, Object>> datasetData = convertDatasetData(
                     List<LinkedHashMap<String, Object>> datasetData = convertDatasetData(
-                            config.getResourceType(),
-                            bill,
-                            dataFlag,
-                            config.getResMap(),
-                            org
+                            config.getResourceType(), bill, dataFlag, config.getResMap(), org, uscc
                     );
                     );
-
                     //设置资源代号XML参数
                     //设置资源代号XML参数
                     GzwCommonUtils.setResCodeData(config, xmlMap, datasetData);
                     GzwCommonUtils.setResCodeData(config, xmlMap, datasetData);
+                    logger.info(String.format("推送单据编号%s,资源代号:%s,转换XML参数完成。转换后参数:\n%s", bill.getString(billNoSign), config.getResCode(), JSONObject.toJSONString(datasetData)));
                 }
                 }
 
 
                 //将单据附件信息转成XML参数及File文件
                 //将单据附件信息转成XML参数及File文件
-                GzwCommonUtils.getBillAttrDataAndFile(billAttrMap, bill, attrResMap, dataFlag, org, allAttachFiles, attrResCode, xmlMap,attachmentServer);
+                GzwCommonUtils.getBillAttrDataAndFile(billAttrMap, bill, attrResMap, dataFlag, org, allAttachFiles, attrResCode, xmlMap, attachmentServer, uscc);
+                logger.info(String.format("推送单据编号%s,附件参数转换完成", bill.getString(billNoSign)));
 
 
                 //将单据审批记录转成XML参数
                 //将单据审批记录转成XML参数
-                GzwCommonUtils.getBillApprovalRecordsData(bill, auditResMap, dataFlag, org, auditResCode, xmlMap);
+                GzwCommonUtils.getBillApprovalRecordsData(bill, auditResMap, dataFlag, org, uscc, auditResCode, xmlMap);
+                logger.info(String.format("推送单据编号%s,审批流数转换完成", bill.getString(billNoSign)));
             }
             }
+            logger.info("当前批次单据XML参数转换完成,生成ZIP文件");
 
 
             // 生成ZIP文件
             // 生成ZIP文件
-            File zipFile = GzwCommonUtils.createZipFile(orgCode, ver, cusDateStr, xmlMap, allAttachFiles, apiCode);
+            File zipFile = GzwCommonUtils.createZipFile(uscc, ver, cusDateStr, xmlMap, allAttachFiles, apiCode);
             if (zipFile == null) {
             if (zipFile == null) {
+                logger.info("生成ZIP文件失败");
                 return;
                 return;
             }
             }
 
 
-
             if (pushState.equals("ZCTS")) {
             if (pushState.equals("ZCTS")) {
-                //TODO 异步执行生成推送日志
-                // 推送国资委数据采集平台
+                //推送国资委数据采集平台接口
+                logger.info("发起推送接口请求");
                 Map<String, Object> respMap = GzwCommonUtils.pushGzwApi(sysCtrlParameter, zipFile);
                 Map<String, Object> respMap = GzwCommonUtils.pushGzwApi(sysCtrlParameter, zipFile);
-                String serviceFlag = (String)respMap.get("serviceFlag");
-                if(serviceFlag.equals("0")){
-                    throw new KDBizException("推送国资委接口失败:"+respMap.get("msg"));
+                logger.info(String.format("推送接口请求返回报文:%s", JSONObject.toJSONString(respMap)));
+
+                String serviceFlag = (String) respMap.get("serviceFlag");
+                if (serviceFlag.equals("0")) {
+                    logger.info("推送接口请求失败,失败结果描述:" + respMap.get("msg"));
+                } else {
+                    logger.info("推送接口请求成功,成功结果描述:" + respMap.get("msg"));
+                    //记录推送成功日志
+                    //记录推送成功单据
+                    successList.addAll(billList);
                 }
                 }
-                //TODO 推送成功回写单据推送状态
-            } else if (pushState.equals("XZWJ")) {
-                //后台操作插件获取表单IFormView下载File文件
-                GzwCommonUtils.download(zipFile);
+                //创建推送日志
+                Map<String, Object> pushLogDynamic = GzwCommonUtils.createPushLogDynamic(this.billEntityType.getName(), billNos, serviceFlag.equals("1"), "", JSONObject.toJSONString(respMap), zipFile);
+                logList.add(pushLogDynamic);
             }
             }
 
 
+            if (pushState.equals("XZWJ")) {
+                logger.info("下载推送接口的ZIP文件");
+                //后台操作插件获取表单IFormView下载File文件,只限于表单界面操作下载,业务流、调度计划无法下载
+                GzwCommonUtils.download(zipFile);
+            }
             //删除zip文件
             //删除zip文件
             zipFile.delete();
             zipFile.delete();
+            logger.info("删除推送接口ZIP文件");
+        }
+
+        if (!successList.isEmpty()) {
+            SaveServiceHelper.save(successList.toArray(new DynamicObject[0]));
+        }
+        //创建日志
+        if (!logList.isEmpty()) {
+            List<DynamicObject> addLogList = new ArrayList<>();
+            for (Map<String, Object> log : logList) {
+                //日志
+                DynamicObject bill = (DynamicObject) log.get("log");
+                addLogList.add(bill);
+
+                Map<String, Object> attachmentInfoMap = (Map<String, Object>) log.get("logAttr");
+                //文件绑定单据进行持久化
+                AttachmentServiceHelper.saveTempAttachments("nckd_em_pushlog", bill.getLong("id"), "em", attachmentInfoMap);
+            }
+            //批量保存日志
+            SaveServiceHelper.save(addLogList.toArray(new DynamicObject[0]));
         }
         }
+
     }
     }
 
 
 
 
     /**
     /**
-     * 转换指定数据集的数据
+     * @param resourceType 资源类型(国资委提供的文档每个资源代号信息都对应了一张数据表,此处次数据表名定义资源类型保持唯一)
+     * @param bill         业务单据
+     * @param dataFlag     数据标识
+     * @param resMap       资源代号信息
+     * @param org          单据组织
+     * @param uscc         集团统一社会信用代码
+     * @return 转换指定数据集的数据
      */
      */
     protected List<LinkedHashMap<String, Object>> convertDatasetData(
     protected List<LinkedHashMap<String, Object>> convertDatasetData(
             String resourceType,
             String resourceType,
             DynamicObject bill,
             DynamicObject bill,
             String dataFlag,
             String dataFlag,
             Map<String, String> resMap,
             Map<String, String> resMap,
-            DynamicObject org) {
+            DynamicObject org,
+            String uscc) {
 
 
-        Map<String, Object> fixedData = GzwCommonUtils.getFixedData(resMap, org, dataFlag);
+        Map<String, Object> fixedData = GzwCommonUtils.getFixedData(resMap, org, uscc, dataFlag);
         List<LinkedHashMap<String, Object>> result = new ArrayList<>();
         List<LinkedHashMap<String, Object>> result = new ArrayList<>();
 
 
         if (isMainDataset(resourceType)) {
         if (isMainDataset(resourceType)) {
@@ -206,11 +258,6 @@ public abstract class GzwPushOpPlugin extends AbstractOperationServicePlugIn {
      */
      */
     protected abstract String getAttachmentPanelField();
     protected abstract String getAttachmentPanelField();
 
 
-    /**
-     * 获取组织代码(分组依据)
-     */
-    protected abstract String getOrgCode(DynamicObject bill);
-
     /**
     /**
      * 获取单据对应的组织
      * 获取单据对应的组织
      */
      */

+ 66 - 0
nckd-fi/src/main/java/nckd/fi/er/task/GzwPushTask.java

@@ -0,0 +1,66 @@
+package nckd.fi.er.task;
+
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.exception.KDException;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.schedule.executor.AbstractTask;
+import kd.bos.servicehelper.QueryServiceHelper;
+import nckd.base.common.utils.OperationUtils;
+import nckd.base.common.utils.QFilterUtils;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @description:补推国资委
+ * @author: dingsixi
+ * @create: 2025/12/30 14:32
+ */
+public class GzwPushTask extends AbstractTask {
+    /**
+     * 元数据单据操作-推送国资委
+     */
+    private final static String PUSHGZW = "pushgzw";
+
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        //1.单据已审核 且 未推送单据  标识 = 新增。  如果已推送,说明不需要再次推送
+        //2.单据非已审核 且 已推送 标识=删除。 如果未推送,说明数据还未审核过 或者 已进行过删除,也不需要再次推送
+        QFilter baseQFOne = new QFilter("status", QCP.equals, "C").and("nckd_ispush", QCP.equals, false);
+        QFilter baseQFTwo = new QFilter("status", QCP.not_in, Arrays.asList("C","E")).and("nckd_ispush", QCP.equals, true);
+        QFilter baseQf = baseQFOne.or(baseQFTwo);
+
+        QFilter billQFOne = new QFilter("billstatus", QCP.equals, "C").and("nckd_ispush", QCP.equals, false);
+        QFilter billQFTwo = new QFilter("billstatus", QCP.not_in, Arrays.asList("C","E")).and("nckd_ispush", QCP.equals, true);
+        QFilter billQf = billQFOne.or(billQFTwo);
+
+        //查询业务招待制度
+        DynamicObjectCollection bizPolicyCol = QueryServiceHelper.query("nckd_em_bizpolicy", "id",baseQf.toArray());
+        if (!bizPolicyCol.isEmpty()) {
+            Set<Object> ids = bizPolicyCol.stream().map(it -> it.get("id")).collect(Collectors.toSet());
+            //调用后台操作推送国资委
+            OperationUtils.operationDoMethod("nckd_em_bizpolicy", PUSHGZW, ids);
+        }
+
+        //业务招待清单
+        DynamicObjectCollection entertainmentListCol = QueryServiceHelper.query("nckd_entertainment_list", "id,billno",billQf.toArray());
+        if (!entertainmentListCol.isEmpty()) {
+            Set<Object> ids = entertainmentListCol.stream().map(it -> it.get("id")).collect(Collectors.toSet());
+            //调用后台操作推送国资委
+            OperationUtils.operationDoMethod("nckd_entertainment_list", PUSHGZW, ids);
+        }
+
+        //业务招待申请单
+        DynamicObjectCollection dailyApplyBillCol = QueryServiceHelper.query("er_dailyapplybill", "id",billQf.toArray());
+        if (!dailyApplyBillCol.isEmpty()) {
+            Set<Object> ids = dailyApplyBillCol.stream().map(it -> it.get("id")).collect(Collectors.toSet());
+            //调用后台操作推送国资委
+            OperationUtils.operationDoMethod("er_dailyapplybill", PUSHGZW, ids);
+        }
+
+    }
+}