Просмотр исходного кода

Merge remote-tracking branch 'origin/master'

lzh 2 дней назад
Родитель
Сommit
bd1eb7876b
71 измененных файлов с 9279 добавлено и 185 удалено
  1. 13 1
      code/base/nckd-jimin-base-helper/src/main/java/nckd/base/helper/CommonHelperUtils.java
  2. 1 1
      code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/FanWeiRSAUtils.java
  3. 2 2
      code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/FanWeiSSOAuthtication.java
  4. 115 0
      code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/SSOAuthtication.java
  5. 143 0
      code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/SSORSAUtils.java
  6. 41 0
      code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/form/HandWrittenSignFormPlugin.java
  7. 33 5
      code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/task/SynSupplierFromSAPTask.java
  8. 66 33
      code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/webapi/SynSupplierApiPlugin.java
  9. BIN
      code/jyyy/nckd-jimin-jyyy-fi/bin/main/nckd/jimin/jyyy/fi/common/CommonHelperUtils.class
  10. BIN
      code/jyyy/nckd-jimin-jyyy-fi/bin/main/nckd/jimin/jyyy/fi/webapi/AttachmentFileUtil.class
  11. BIN
      code/jyyy/nckd-jimin-jyyy-fi/bin/main/nckd/jimin/jyyy/fi/webapi/TransDetailApiPlugin.class
  12. 860 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/PayBillToolUtil.java
  13. 64 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/PayToZFQZOP.java
  14. 145 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/PaymentProcessOpPlugin.java
  15. 77 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGatewayProxy.java
  16. 141 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGatewaySoapBindingStub.java
  17. 8 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGateway_PortType.java
  18. 14 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGateway_Service.java
  19. 138 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGateway_ServiceLocator.java
  20. 1119 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TypeUtils.java
  21. 148 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/Utils.java
  22. 137 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/task/AgentpaybillQueryStatusTast.java
  23. 95 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/task/PayQueryStatusTast.java
  24. 39 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/task/PayUpadteStatusTask.java
  25. 33 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/em/opplugin/AgentpaybillOpPlugin.java
  26. 56 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/AccountSynReturnModel.java
  27. 55 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/BankSynReturnModel.java
  28. 26 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/CustomApiResultForMy.java
  29. 274 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/SaveAccountApi.java
  30. 135 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/SaveBankApi.java
  31. 187 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/business/DiDiTripDailyVehicleBillCusInvoke.java
  32. 531 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/business/DiDiTripReqBillCusInvoke.java
  33. 97 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/common/FinanceCommonUtils.java
  34. 49 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/DailyApplyBillEditPlugin.java
  35. 52 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/ExpenseItemFilterFormPlugin.java
  36. 58 38
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/PayBigCategoryFormPlugin.java
  37. 50 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/PublicReimburseBillFormPlugin.java
  38. 49 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/TripReqMobFormPlugin.java
  39. 92 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/operate/DailyVehicleBillSubmitOpPlugin.java
  40. 99 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/operate/TripReqBillSubmitOpPlugin.java
  41. 110 57
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/AttachmentFileUtil.java
  42. 299 0
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/ContractbillApiPlugin.java
  43. 8 2
      code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/TransDetailApiPlugin.java
  44. 91 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/opplugin/web/position/AutoEndPartTimeTask.java
  45. 82 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/opplugin/web/position/PosEndPartTimeConfirmPlugin.java
  46. 68 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/opplugin/web/position/PositionEndPartTimePlugin.java
  47. 1 1
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/PositionTree.java
  48. 10 23
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncAdminOrgTask.java
  49. 5 8
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncPersonTask.java
  50. 3 9
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncPositionTask.java
  51. 47 5
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncUtil.java
  52. 695 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/CasRecrApplyFormPlugin.java
  53. 103 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/CasRecrApplyListPlugin.java
  54. 781 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyFormPlugin.java
  55. 130 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyListPlugin.java
  56. 441 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyPlanFormPlugin.java
  57. 68 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyPlanListPlugin.java
  58. 61 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/CasRecrApplyUnAuditValidator.java
  59. 86 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/CasRecrApplyWorkFlowPlugin.java
  60. 151 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyPlanOperatePlugin.java
  61. 66 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyPlanUnAuditValidator.java
  62. 73 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyPlanWorkFlowPlugin.java
  63. 56 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplySubmitValidator.java
  64. 86 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyWorkFlowPlugin.java
  65. 61 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/util/RecUtils.java
  66. 71 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyAlertTask.java
  67. 39 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyBillOpEx.java
  68. 70 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyBillTask.java
  69. 129 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyBillUtil.java
  70. 94 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaChangeBillAuditOp.java
  71. 52 0
      code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaUpdateBillEditEx.java

+ 13 - 1
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/CommonHelperUtils.java → code/base/nckd-jimin-base-helper/src/main/java/nckd/base/helper/CommonHelperUtils.java

@@ -1,4 +1,4 @@
-package nckd.jimin.jyyy.bd.common;
+package nckd.base.helper;
 
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
@@ -6,10 +6,22 @@ import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
 import org.apache.commons.lang3.ObjectUtils;
+
 import java.util.Map;
 import java.util.stream.Collectors;
 
+
+/**
+ * 工具类
+ * @author wanghaiwu_kd
+ * @date 2025/04/23
+ */
 public class CommonHelperUtils {
+    /**
+     * 根据单据编号获取客户化配置
+     * @param number
+     * @return
+     */
     public static Map<String, String> getCommonParams(String number){
         String selectField = "nckd_entryentity.nckd_key, nckd_entryentity.nckd_value";
 

+ 1 - 1
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/RSAUtils.java → code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/FanWeiRSAUtils.java

@@ -12,7 +12,7 @@ import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 
-public class RSAUtils {
+public class FanWeiRSAUtils {
 
     private static Provider provider;
 

+ 2 - 2
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/FanWeiSSOAuthtication.java

@@ -89,7 +89,7 @@ public class FanWeiSSOAuthtication extends ThirdAppAuthtication {
             }
 
             String privateKey = mapentity.get("privatekey");
-            if(StringUtils.isEmpty(userUrl)){
+            if(StringUtils.isEmpty(privateKey)){
                 logger.info("FanWeiSSOAuthtication:privatekey is null");
 
                 result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数privatekey");
@@ -141,7 +141,7 @@ public class FanWeiSSOAuthtication extends ThirdAppAuthtication {
 
             String userJSONString = "";
             if(isDecode != null && "true".equals(isDecode)) {
-                userJSONString = new String(RSAUtils.decryptByKey(RSAUtils.getPrivateKey(Base64.decodeBase64(privateKey))
+                userJSONString = new String(FanWeiRSAUtils.decryptByKey(FanWeiRSAUtils.getPrivateKey(Base64.decodeBase64(privateKey))
                         , Base64.decodeBase64(apiResult.getBytes("UTF-8"))));
             }
 

+ 115 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/SSOAuthtication.java

@@ -0,0 +1,115 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import kd.bos.dc.api.model.Account;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.login.thirdauth.app.AppAuthResult;
+import kd.bos.login.thirdauth.app.ThirdAppAuthtication;
+import kd.bos.login.thirdauth.app.UserType;
+import nckd.base.helper.CommonHelperUtils;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+/**
+ * @author wanghaiwu_kd
+ * @date 2025/05/06
+ * @description 单点登录拦截,加固单点校验方式
+ */
+public class SSOAuthtication extends ThirdAppAuthtication {
+    private static Log logger = LogFactory.getLog(SSOAuthtication.class);
+    /**
+     * 判断该接口请求是否需要通过此插件认证
+     */
+    @Override
+    public boolean isNeedHandle(HttpServletRequest request, Account account) {
+        //加密的数据信息
+        String code = request.getParameter("kd_code");
+        if(StringUtils.isNotBlank(code)){
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     *用户身份解析
+     */
+    @Override
+    public AppAuthResult appAuthtication(HttpServletRequest request, Account account) {
+        AppAuthResult result = new AppAuthResult();
+        result.setSucceed(false);
+        try{
+            //加密的数据信息
+            String code = request.getParameter("kd_code");
+            if(StringUtils.isBlank(code)){
+                logger.info("SSOAuthtication:kd_code is null");
+
+                result.setErrorMessage("sso:kd_code is null");
+                return result;
+            }
+
+            Map<String, String> mapentity = CommonHelperUtils.getCommonParams("SSO");
+            if(mapentity == null ){
+                logger.info("SSOAuthtication:nckd_entryentity is null");
+
+                result.setErrorMessage("SSOAuthtication:未配置单点相关参数");
+                return result;
+            }
+
+            //私钥
+            String privateKey = mapentity.get("privatekey");
+            if(StringUtils.isEmpty(privateKey)){
+                logger.info("SSOAuthtication:privateKey is null");
+
+                result.setErrorMessage("SSOAuthtication:未配置单点相关参数privatekey");
+                return result;
+            }
+
+            //和第三方约定加签
+            String secret = mapentity.get("secret");
+            if(StringUtils.isEmpty(secret)){
+                logger.info("SSOAuthtication:secret is null");
+
+                result.setErrorMessage("SSOAuthtication:未配置单点相关参数secret");
+                return result;
+            }
+
+            //可以先使用SHAUtils.getSHA256Hex实现签名验证再数据解密
+            String timeStamp = request.getParameter("timeStamp");
+            String signture = request.getParameter("signture");
+            if(!SHAUtils.checkDateTime(timeStamp)) {
+                logger.info("SSOAuthtication:timeStamp check fail");
+
+                result.setErrorMessage("sso:timeStamp check fail");
+                return result;
+            }
+
+            String sign = SHAUtils.getSHA256Hex(code + timeStamp + secret);
+
+            //签名认证
+            if(StringUtils.isBlank(signture) || !signture.equals(sign)) {
+                logger.info("SSOAuthtication:sign check fail");
+
+                result.setErrorMessage("sso:sign check fail");
+                return result;
+            }
+
+            String user = new String(SSORSAUtils.decryptByKey(SSORSAUtils.getPrivateKey(Base64.decodeBase64(privateKey))
+                                        , Base64.decodeBase64(code.getBytes("UTF-8"))));
+            if(StringUtils.isBlank(user)){
+                logger.info("SSOAuthtication:user is null");
+
+                result.setErrorMessage("sso:user is null");
+                return result;
+            }
+
+            result.setUserFlag(user);
+            result.setUserType(UserType.USER_NAME);
+            result.setSucceed(true);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return result;
+    }
+}

+ 143 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/SSORSAUtils.java

@@ -0,0 +1,143 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.ByteArrayOutputStream;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+public class SSORSAUtils {
+
+    private static Provider provider;
+
+    static {
+        provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
+        Security.addProvider(provider);
+    }
+
+    /**
+     * 产生key pair,提供provider和random
+     * @return
+     * @throws NoSuchAlgorithmException
+     */
+    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
+        // 产生用于安全加密的随机数
+        SecureRandom random = new SecureRandom();
+
+        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
+        Integer length = 2048;//加密算法位数
+        generator.initialize(length, random);
+        return generator.generateKeyPair();
+    }
+
+    /**
+     * 返回一个keyBytes生成的PublicKey对象
+     * @param keyBytes
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+        return publicKey;
+    }
+
+    public static byte[] encryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        // Cipher: 提供加密和解密功能的实例
+        // transformation: "algorithm/mode/padding"
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
+        // PrivateKey privateKey = keyPair.getPrivate();
+        // 初始化
+        cipher.init(Cipher.ENCRYPT_MODE, keys);
+        // doFinal(): 加密或者解密数据
+        byte[] plainText = cipher.doFinal(byteArray);
+        return plainText;
+    }
+
+    /**
+     * 返回一个keyBytes生成的privateKey对象
+     * @param keyBytes
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+        return privateKey;
+    }
+
+    /**
+     * 用相应的key解密对应加密的问题
+     *
+     * @param keys
+     * @param byteArray
+     * @return
+     */
+    public static byte[] decryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        // Cipher: 提供加密和解密功能的实例
+        // transformation: "algorithm/mode/padding"
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
+
+        // 初始化
+        cipher.init(Cipher.DECRYPT_MODE, keys);
+        // doFinal(): 加密或者解密数据
+        byte[] plainText = cipher.doFinal(byteArray);
+
+//        byte[] bytes = processData(cipher, byteArray, 1024 / 8);
+
+        return plainText;
+    }
+
+    /**
+     * 分段处理数据.
+     *
+     * @param cipher      密码算法
+     * @param dataes      数据
+     * @param segmentSize 分段大小(小于等于0不分段)
+     * @return
+     */
+    private static byte[] processData(Cipher cipher, byte[] dataes, int segmentSize) {
+        byte[] decBytes = null;
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            int inputLength = dataes.length;
+            int offSet = 0;
+            for (int i = 0; inputLength - offSet > 0; offSet = i * segmentSize) {
+                byte[] cache;
+                if (inputLength - offSet > segmentSize) {
+                    cache = cipher.doFinal(dataes, offSet, segmentSize);
+                } else {
+                    cache = cipher.doFinal(dataes, offSet, inputLength - offSet);
+                }
+                out.write(cache, 0, cache.length);
+                ++i;
+            }
+            decBytes = out.toByteArray();
+            out.close();
+        } catch (Exception e) {
+        }
+        return decBytes;
+    }
+
+    /**
+     * 产生public key
+     *
+     * @return public key字符串
+     */
+    public static String generateBase64Key(byte[] keys) {
+        // encodeBase64(): Encodes binary data using the base64
+        // algorithm but does not chunk the output.
+        // getEncoded():返回key的原始编码形式
+        return new String(Base64.encodeBase64(keys));
+    }
+}

+ 41 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/form/HandWrittenSignFormPlugin.java

@@ -0,0 +1,41 @@
+package nckd.jimin.jyyy.bd.plugin.form;
+
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.form.control.Toolbar;
+import kd.bos.form.control.events.UploadEvent;
+import kd.bos.form.control.events.UploadListener;
+import java.util.EventObject;
+
+/**
+ * 表单标识:手写签名(nckd_bos_handwritten__ext)
+ * @author wnaghaiwu_kd
+ * @date 2025/05/08
+ */
+public class HandWrittenSignFormPlugin extends AbstractBillPlugIn implements UploadListener {
+    @Override
+    public void initialize() {
+        super.initialize();
+
+        Toolbar toolbar = this.getControl("nckd_toolbarap");
+        toolbar.addUploadListener(this);
+    }
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+    }
+
+    @Override
+    public void upload(UploadEvent evt) {
+//        UploadListener.super.upload(evt);
+
+        Object[] urls = evt.getUrls();
+        String callbackKey = evt.getCallbackKey();
+        if ("nckd_btnupload".equals(callbackKey)) {
+            //执行业务逻辑
+            if(urls.length > 0){
+                this.getModel().setValue("handwrittensign", urls[0].toString());
+            }
+        }
+    }
+}

+ 33 - 5
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/task/SynSupplierFromSAPTask.java

@@ -22,7 +22,8 @@ import kd.bos.servicehelper.basedata.BaseDataServiceHelper;
 import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.bos.util.StringUtils;
-import nckd.jimin.jyyy.bd.common.CommonHelperUtils;
+import nckd.base.helper.CommonHelperUtils;
+
 import java.io.IOException;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -82,7 +83,7 @@ public class SynSupplierFromSAPTask extends AbstractTask implements StopTask {
             logger.info("------同步组织 " + org.getString("number") + "(" + org.getString("number") + ")下的供应商----------");
             String orgNumber = org.getString("number");
 
-            buildSupplier(supplierNameMap, supplierOrgMap, param_supplierurl, header, orgNumber);
+            buildSupplier(supplierNameMap, supplierOrgMap, param_supplierurl, header, orgNumber, map);
         }
 
         if(supplierNameMap.size() > 0){
@@ -111,8 +112,10 @@ public class SynSupplierFromSAPTask extends AbstractTask implements StopTask {
      * @param orgNumber
      */
     private void buildSupplier(Map<String, String> supplierNameMap, Map<String, List<String>> supplierOrgMap
-                                , String url, Map<String, String> header, String orgNumber){
+                                , String url, Map<String, String> header, String orgNumber, Map<String, Object> map){
         try {
+
+
             JSONObject jsonData = new JSONObject();
 
             jsonData.put("BUKRS", orgNumber);
@@ -155,15 +158,22 @@ public class SynSupplierFromSAPTask extends AbstractTask implements StopTask {
             }
 
             int size = 0;
+            int maxSize = 0;
+            if(map.get("maxCount") != null){
+                maxSize = Integer.parseInt(map.get("maxCount").toString());
+            }
+
             for(int i = 0; i < rItemArray.size(); ++i) {
                 JSONObject item = rItemArray.getJSONObject(i);
                 String number = item.getString("LIFNR");
 
                 if(StringUtils.isNotEmpty(number) && "5".equals(number.substring(0, 1))){
                     size++;
-                    if(size > 100){
+
+                    if(maxSize > 0 && size > maxSize){
                         break;
                     }
+
                     String name = item.getString("NAME1");
 
                     if(!supplierNameMap.containsKey(number)){
@@ -199,6 +209,23 @@ public class SynSupplierFromSAPTask extends AbstractTask implements StopTask {
         //供应商名称
         String supplierName = jsonData.getString("name");
         //供应商类型:法人企业1,非法人企业2,非企业单位3,个人4,个体户5
+
+        if(StringUtils.isEmpty(supplierNumber)){
+            returnMap.put("code", "500");
+            returnMap.put("msg", "供应商编码为空!");
+
+            return returnMap;
+        }
+
+        if(StringUtils.isEmpty(supplierName)){
+//            supplierName = supplierNumber;
+
+            returnMap.put("code", "500");
+            returnMap.put("msg", "供应商名称为空!");
+
+            return returnMap;
+        }
+
         String type = "1";
         if(supplierName.length() < 4){
             type = "4";
@@ -218,11 +245,13 @@ public class SynSupplierFromSAPTask extends AbstractTask implements StopTask {
         if (supplier == null) {
             supplier = BusinessDataServiceHelper.newDynamicObject(ENTITY_SUPPLIER);
             supplier.set("status", "A");
+            supplier.set("createtime", curDate);
         } else {
             supplierId = supplier.getLong("id");
             isUpdate = true;
         }
 
+        supplier.set("nckd_datasource", "sap");
 //        supplier.set("societycreditcode", "test");
 
         supplier.set("type", type);
@@ -253,7 +282,6 @@ public class SynSupplierFromSAPTask extends AbstractTask implements StopTask {
         supplier.set("creator", user);
         supplier.set("createorg", defaultOrg);
         supplier.set("org", defaultOrg);
-        supplier.set("createtime", curDate);
 
         qFilter = new QFilter("number", QCP.equals, param_suppliertype);
         qFilter.and(new QFilter("enable", QCP.equals, "1"));

+ 66 - 33
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/webapi/SynSupplierApiPlugin.java

@@ -151,6 +151,29 @@ public class SynSupplierApiPlugin implements Serializable {
         String supplierNumber = jsonData.getString("mdCode");
         //供应商名称
         String supplierName = jsonData.getString("mdDescription");
+        //数据来源
+        String dataSource = jsonData.getString("dataSource");
+        if(StringUtils.isEmpty(dataSource)){
+            dataSource = "mdm";
+        }
+
+
+        if(StringUtils.isEmpty(supplierNumber)){
+            returnMap.put("code", "500");
+            returnMap.put("msg", "供应商编码为空!");
+
+            return returnMap;
+        }
+
+        if(StringUtils.isEmpty(supplierName)){
+//            supplierName = supplierNumber;
+
+            returnMap.put("code", "500");
+            returnMap.put("msg", "供应商名称为空!");
+
+            return returnMap;
+        }
+
         //供应商类型:法人企业1,非法人企业2,非企业单位3,个人4,个体户5
         String type = "1";
         //社会信用识别码societycreditcode
@@ -167,10 +190,13 @@ public class SynSupplierApiPlugin implements Serializable {
         if (supplier == null) {
             supplier = BusinessDataServiceHelper.newDynamicObject(ENTITY_SUPPLIER);
             supplier.set("status", "A");
+            supplier.set("createtime", curDate);
         } else {
             supplierId = supplier.getLong("id");
             isUpdate = true;
         }
+
+        supplier.set("nckd_datasource", "mdm");
         supplier.set("societycreditcode", uniqueCode);
         supplier.set("type", type);
         supplier.set("number", supplierNumber);
@@ -193,8 +219,6 @@ public class SynSupplierApiPlugin implements Serializable {
         supplier.set("creator", createUser);
         supplier.set("createorg", defaultOrg);
         supplier.set("org", defaultOrg);
-        supplier.set("createtime", curDate);
-
 
         supplier.set("group", supplierGroup);
 
@@ -298,46 +322,55 @@ public class SynSupplierApiPlugin implements Serializable {
             supplier.set("entry_bank",bankEntry);
         }
 
-        //判断是否更新与新增,通过不同方法处理,保存操作会变更状态为保存
-        if(isUpdate) {
-//            SaveServiceHelper.update(new DynamicObject[]{customer});
-            OperationResult resultSave = SaveServiceHelper.saveOperate(ENTITY_SUPPLIER, new DynamicObject[]{supplier}, OperateOption.create());
+        try {
+            //判断是否更新与新增,通过不同方法处理,保存操作会变更状态为保存
+            if(isUpdate) {
+    //            SaveServiceHelper.update(new DynamicObject[]{customer});
+                OperationResult resultSave = SaveServiceHelper.saveOperate(ENTITY_SUPPLIER, new DynamicObject[]{supplier}, OperateOption.create());
+
+                StringBuilder err = new StringBuilder();
+                if (resultSave.getSuccessPkIds().size() <= 0) {
+                    for (int i = 0; i < resultSave.getAllErrorOrValidateInfo().size(); i++) {
+                        String message = resultSave.getAllErrorOrValidateInfo().get(i).getMessage();
+                        err.append("/").append(message);
+                    }
+
+                    returnMap.put("code", "500");
+                    returnMap.put("msg", err.toString());
 
-            StringBuilder err = new StringBuilder();
-            if (resultSave.getSuccessPkIds().size() <= 0) {
-                for (int i = 0; i < resultSave.getAllErrorOrValidateInfo().size(); i++) {
-                    String message = resultSave.getAllErrorOrValidateInfo().get(i).getMessage();
-                    err.append("/").append(message);
+                    return returnMap;
                 }
+                supplierId = supplier.getLong("id");
+            } else {
+                //新增保存供应商对象
+                OperationResult resultSave = SaveServiceHelper.saveOperate(ENTITY_SUPPLIER, new DynamicObject[]{supplier}, OperateOption.create());
+
+                StringBuilder err = new StringBuilder();
+                if (resultSave.getSuccessPkIds().size() <= 0) {
+                    for (int i = 0; i < resultSave.getAllErrorOrValidateInfo().size(); i++) {
+                        String message = resultSave.getAllErrorOrValidateInfo().get(i).getMessage();
+                        err.append("/").append(message);
+                    }
 
-                returnMap.put("code", "500");
-                returnMap.put("msg", err.toString());
+                    returnMap.put("code", "500");
+                    returnMap.put("msg", err.toString());
 
-                return returnMap;
-            }
-            supplierId = supplier.getLong("id");
-        }else {
-            //新增保存供应商对象
-            OperationResult resultSave = SaveServiceHelper.saveOperate(ENTITY_SUPPLIER, new DynamicObject[]{supplier}, OperateOption.create());
-
-            StringBuilder err = new StringBuilder();
-            if (resultSave.getSuccessPkIds().size() <= 0) {
-                for (int i = 0; i < resultSave.getAllErrorOrValidateInfo().size(); i++) {
-                    String message = resultSave.getAllErrorOrValidateInfo().get(i).getMessage();
-                    err.append("/").append(message);
+                    return returnMap;
+                } else {
+                    supplierId = (Long) resultSave.getSuccessPkIds().get(0);
                 }
 
-                returnMap.put("code", "500");
-                returnMap.put("msg", err.toString());
+                DynamicObject customerObj = BusinessDataServiceHelper.loadSingle(supplierId, "bd_supplier");
 
-                return returnMap;
-            } else {
-                supplierId = (Long) resultSave.getSuccessPkIds().get(0);
+                OperationServiceHelper.executeOperate("submit", ENTITY_SUPPLIER, new DynamicObject[]{customerObj}, OperateOption.create());
+                OperationServiceHelper.executeOperate("audit", ENTITY_SUPPLIER, new DynamicObject[]{customerObj}, OperateOption.create());
             }
-            DynamicObject customerObj = BusinessDataServiceHelper.loadSingle(supplierId, "bd_supplier");
 
-            OperationServiceHelper.executeOperate("submit", ENTITY_SUPPLIER, new DynamicObject[]{customerObj}, OperateOption.create());
-            OperationServiceHelper.executeOperate("audit", ENTITY_SUPPLIER, new DynamicObject[]{customerObj}, OperateOption.create());
+        } catch(Exception e){
+            returnMap.put("code", "500");
+            returnMap.put("msg", e.getMessage());
+
+            return returnMap;
         }
 
         List<Long> assignOrgIds = new ArrayList<>();

BIN
code/jyyy/nckd-jimin-jyyy-fi/bin/main/nckd/jimin/jyyy/fi/common/CommonHelperUtils.class


BIN
code/jyyy/nckd-jimin-jyyy-fi/bin/main/nckd/jimin/jyyy/fi/webapi/AttachmentFileUtil.class


BIN
code/jyyy/nckd-jimin-jyyy-fi/bin/main/nckd/jimin/jyyy/fi/webapi/TransDetailApiPlugin.class


+ 860 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/PayBillToolUtil.java

@@ -0,0 +1,860 @@
+package fi.cas.opplugin;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.encrypt.Encrypters;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.Timestamp;
+import java.util.*;
+
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+
+public class PayBillToolUtil {
+    public static final String ENTITY_NAME = "cas_paybill";
+    public static final String AGENT_ENTITY_NAME = "cas_agentpaybill";
+    protected static final Log log = LogFactory.getLog(PayBillToolUtil.class);
+    public static final String CHANNELCODE_PILIANG = "JF";
+
+
+    /**
+     * 代发单付款请求拼接
+     *
+     * @return
+     */
+    public static String createSingleAgentPaymentRequest_1(DynamicObject info) {
+        try {
+            JSONObject param = new JSONObject();
+            headJson(param);
+
+            JSONObject data = new JSONObject();
+
+            //单据状态
+            if ("C".equals(info.get("billstatus"))) {
+                data.put("FBillStatus", "12");
+            }
+
+            //EAS付款单据号
+            String bbh = info.get("nckd_bbh") + "";//版本号
+            data.put("ERP_INS_ID", info.getPkValue() + "-" + bbh);
+            //EAS付款单据号
+            data.put("ERP_PAYNO", info.get("billno") + "-" + bbh);
+
+            //录入人
+            data.put("CREATOR", info.get("creator.name").toString());
+
+            //录入时间
+            data.put("CREATE_TIME", TypeUtils.date2String(new Date(((Timestamp) info.get("modifytime")).getTime()), TypeUtils.DEFAULT_DATE_FORMAT));
+
+            //摘要
+            data.put("REMARK", info.get("description") + "-" + info.get("billno"));
+
+            data.put("IS_TRANSFER", "0");
+
+            //付款单位--->公司编号
+            if (info.get("org") != null) {//付款单位--->公司编号
+                String companyNumber = TypeUtils.nullToString(info.get("org.number"));
+                data.put("PAY_CLT_NO", companyNumber);
+            }
+
+            DynamicObject payeracctbankEntity = BusinessDataServiceHelper.loadSingleFromCache(info.getDynamicObject("payeracctbank").getPkValue(), "am_accountbank");
+            String payeracc = payeracctbankEntity.getString("bankaccountnumber");
+            String payername = payeracctbankEntity.getString("acctname");
+
+            //付款方账号 ---> 付款账户基础资料银行账号
+            data.put("PAY_ACNT_NO", payeracc);
+
+            //付款银行 ---> 金融机构行号编码
+            data.put("PAY_CNAPS", payeracctbankEntity.get("bank.number") + "");
+
+            data.put("PAY_DATE", TypeUtils.date2String(new Date(), TypeUtils.DEFAULT_DATE_FORMAT));//付款日期
+
+            //付款金额
+
+            data.put("AMOUNT", info.getBigDecimal("payamount").setScale(2, RoundingMode.DOWN).toString());
+            //币别
+            if ("CNY".equals(info.get("currency.number"))) {
+                data.put("CURRENCY", "BB01");
+            }
+
+            //对公
+            if (!info.getBoolean("ispersonpay")) {
+                data.put("IS_PERSON", "0");
+            } else {
+                data.put("IS_PERSON", "1");
+            }
+
+            //加急
+            if (info.getBoolean("urgentflag")) {
+                data.put("URGENT_FLAG", "1");
+            } else {
+                data.put("URGENT_FLAG", "0");
+            }
+
+            //用途
+            data.put("PURPOSE", "用途:" + info.get("nckd_usage"));
+
+            //费用类型
+            data.put("BUSS_TYPE", JSONObject.NULL);
+
+            //付款类型,工资  997
+            if ("997".equals(info.get("paymenttype.number"))) {
+                data.put("PAY_FLAG", "2");
+            } else {
+                data.put("PAY_FLAG", "1");
+            }
+
+            //明细条数
+            data.put("PAY_NUM", info.getString("count"));
+
+
+            //明细数据
+            JSONArray OP_ACNT_LIST = new JSONArray();
+
+            // 获取分录数据
+            DynamicObjectCollection entryList = info.getDynamicObjectCollection("entry");
+            Map<String, BigDecimal> decodeAmount = new HashMap(entryList.size());
+
+            for(int i = 0; i < entryList.size(); ++i) {
+                DynamicObject entry = (DynamicObject)entryList.get(i);
+                String encryptLocalAmtStr;
+                if (entry.getDataEntityType().getProperties().get("e_encryptamount") != null) {
+                    encryptLocalAmtStr = entry.getString("e_encryptamount");
+                    if (encryptLocalAmtStr != null && !encryptLocalAmtStr.trim().isEmpty()) {
+                        entry.set("e_amount", getDecodeAmount(encryptLocalAmtStr, decodeAmount));
+                    }
+                }
+
+                if (entry.getDataEntityType().getProperties().get("e_encryptlocalamt") != null) {
+                    encryptLocalAmtStr = entry.getString("e_encryptlocalamt");
+                    if (encryptLocalAmtStr != null && !encryptLocalAmtStr.trim().isEmpty()) {
+                        entry.set("e_localamt", getDecodeAmount(encryptLocalAmtStr, decodeAmount));
+                    }
+                }
+            }
+
+            for (int i = 0; i < entryList.size(); i++) {
+                DynamicObject entry = entryList.get(i);
+                JSONObject entrydata = new JSONObject();
+                //明细id
+                entrydata.put("ERP_PVT_ID", entry.getPkValue() + "");
+                //收款方账号
+                entrydata.put("RECE_ACC_NO", entry.get("payeeacctbank") + "");
+                //收款方户名
+                entrydata.put("RECE_ACC_NAME", entry.get("payeename") + "");
+                //收款行行号
+                entrydata.put("RECE_CNAPS", entry.get("payeebanknumber") + "");
+                //付款金额,待补充
+
+                entrydata.put("AMOUNT", entry.getBigDecimal("e_amount").setScale(2, RoundingMode.DOWN).toString());
+                //明细用途
+                entrydata.put("PURPOSE", "用途:" + info.get("nckd_usage"));
+
+                OP_ACNT_LIST.put(entrydata);
+            }
+            data.put("OP_ACNT_LIST", OP_ACNT_LIST);
+
+
+            //无用字段
+            data.put("CLT_NO", JSONObject.NULL);
+            data.put("PAY_ACNT_NAME", JSONObject.NULL);
+            data.put("PAY_BANK", JSONObject.NULL);
+            data.put("CASHAMOUNT", JSONObject.NULL);
+            data.put("BILLAMOUNT", JSONObject.NULL);
+            data.put("RECE_ACC_NO", JSONObject.NULL);
+            data.put("RECE_ACC_NAME", JSONObject.NULL);
+            data.put("RECE_OPBANK_NAME", JSONObject.NULL);
+            data.put("RECE_OPBANK_NAME", JSONObject.NULL);
+            data.put("RECE_BANK_NO", JSONObject.NULL);
+            data.put("RECE_CNAPS", JSONObject.NULL);
+            data.put("REG_NO", JSONObject.NULL);
+            data.put("TERM", JSONObject.NULL);
+
+
+            param.put("data", data);
+            param.put("txDateTime", Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("batchNo", TypeUtils.nullToString(info.get("billno")) + "-" + TypeUtils.nullToString(info.get("nckd_bbh")) + "-" + Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("code", "NSTC-T003");
+
+            return param.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+
+
+
+
+
+
+    private static BigDecimal getDecodeAmount(String encryptLocalAmtStr, Map<String, BigDecimal> decodeAmount) {
+        BigDecimal amount = (BigDecimal)decodeAmount.get(encryptLocalAmtStr);
+        if (amount == null) {
+            decodeAmount.put(encryptLocalAmtStr, decodeAmount(encryptLocalAmtStr));
+        }
+
+        return (BigDecimal)decodeAmount.get(encryptLocalAmtStr);
+    }
+    public static BigDecimal decodeAmount(String encryptAmount) {
+        if (encryptAmount != null && !encryptAmount.trim().isEmpty()) {
+            String decode = "";
+            if (Encrypters.isEncrypted(encryptAmount)) {
+                decode = Encrypters.decode(encryptAmount);
+                return new BigDecimal(decode);
+            } else {
+                return decodeAmountOld(encryptAmount);
+            }
+        } else {
+            return BigDecimal.ZERO;
+        }
+    }
+    public static BigDecimal decodeAmountOld(String encryptAmount) {
+        if (encryptAmount != null && !encryptAmount.trim().isEmpty()) {
+            byte[] decode = Base64.getDecoder().decode(encryptAmount);
+            return new BigDecimal(new String(decode));
+        } else {
+            return BigDecimal.ZERO;
+        }
+    }
+    /***
+     * 拼接json对象
+     */
+    public static JSONObject getServiceBean_youhua(DynamicObject info) {
+        JSONObject data = new JSONObject();
+
+        //单据状态
+        if ("C".equals(info.get("billstatus"))) {
+            data.put("FBillStatus", "12");
+        }
+
+
+        //录入人
+        data.put("CREATOR", info.get("creator.name").toString());
+
+        //录入时间
+        data.put("CREATE_TIME", TypeUtils.date2String(new Date(((Timestamp) info.get("modifytime")).getTime()), TypeUtils.DEFAULT_DATE_FORMAT));
+        //摘要
+        data.put("REMARK", info.get("description") + "-" + info.get("billno"));
+
+
+        String entrance = info.get("entrance") + "";//是否资金调度,待补充
+        if ("SYN".equals(entrance) || "SPAN".equals(entrance)) {
+            data.put("IS_TRANSFER", "1");
+        } else {
+            data.put("IS_TRANSFER", "0");
+        }
+        data.put("IS_TRANSFER", "0");
+
+
+        String bbh = info.get("nckd_bbh") + "";//版本号
+        data.put("ERP_INS_ID", info.getPkValue() + "-" + bbh);
+        //EAS付款单据号
+        data.put("ERP_PAYNO", info.get("billno") + "-" + bbh);
+
+        //付款日期
+        data.put("PAY_DATE", TypeUtils.date2String(new Date(), TypeUtils.DEFAULT_DATE_FORMAT));
+        //对公
+        if (!info.getBoolean("ispersonpay")) {
+            data.put("IS_PERSON", "0");
+        } else {
+            data.put("IS_PERSON", "1");
+        }
+
+        //加急
+        if (info.get("priority") != null) {
+            if ("prior".equals(info.get("priority"))) {//优先
+                data.put("URGENT_FLAG", "1");
+            } else {
+                data.put("URGENT_FLAG", "0");
+            }
+        }
+        data.put("PURPOSE", "用途:" + info.get("nckd_usage"));
+        //费用类型,取分录第一条费用项目编码
+        DynamicObjectCollection entrycoll = info.getDynamicObjectCollection("entry");
+        if (entrycoll.size() > 0) {
+            if (entrycoll.get(0).get("e_expenseitem.number") == null) {
+                data.put("BUSS_TYPE", "");
+            } else {
+                data.put("BUSS_TYPE", entrycoll.get(0).get("e_expenseitem.number") + "");
+            }
+        }
+
+
+        DynamicObject skyhinfo = BusinessDataServiceHelper.loadSingleFromCache(info.getDynamicObject("payeebank").getPkValue(), "bd_bebank");
+
+        //收款方开户行 名称
+        data.put("RECE_OPBANK_NAME", skyhinfo.get("name").toString());//收款方开户行 名称
+
+        //收款方开户行 CNAPS号 ,行号,取联行号
+        data.put("RECE_CNAPS", skyhinfo.get("union_number") + "");
+
+        //收款方户名
+        data.put("RECE_ACC_NAME", info.get("recaccbankname") + "");
+        //收款方账号
+        data.put("RECE_ACC_NO", info.get("payeebanknum") + "");
+
+        //付款单位--->公司编号
+        if (info.get("org") != null) {//付款单位--->公司编号
+            String companyNumber = TypeUtils.nullToString(info.get("org.number"));
+            data.put("PAY_CLT_NO", companyNumber);
+        }
+
+
+        //付款账号
+        DynamicObject payeracctbankEntity = BusinessDataServiceHelper.loadSingle(info.getDynamicObject("payeracctbank").getPkValue(), "am_accountbank");
+        String payeracc = payeracctbankEntity.getString("bankaccountnumber");
+        String payername = payeracctbankEntity.getString("acctname");
+
+        //付款方账号 ---> 付款账户基础资料银行账号
+        data.put("PAY_ACNT_NO", payeracc);
+
+        //付款银行 ---> 金融机构行号编码,是不是就是金融机构编码
+        data.put("PAY_CNAPS", payeracctbankEntity.get("bank.number") + "");
+
+        data.put("AMOUNT", info.getBigDecimal("actpayamt").setScale(2, RoundingMode.DOWN));
+        //币别
+
+        if ("CNY".equals(info.get("currency.number"))) {
+            data.put("CURRENCY", "BB01");
+        }
+
+        //无用字段
+        data.put("CLT_NO", JSONObject.NULL);
+        data.put("PAY_ACNT_NAME", JSONObject.NULL);
+        data.put("PAY_BANK", JSONObject.NULL);
+        data.put("CASHAMOUNT", JSONObject.NULL);
+        data.put("BILLAMOUNT", JSONObject.NULL);
+        data.put("RECE_BANK_NO", JSONObject.NULL);
+        data.put("REG_NO", JSONObject.NULL);
+        data.put("TERM", JSONObject.NULL);
+        data.put("PAY_FLAG", JSONObject.NULL);
+        data.put("PAY_NUM", "0");
+        data.put("OP_ACNT_LIST", JSONObject.NULL);
+
+
+        //应付票据逻辑,不需要付息方式了
+//        if ("012".equals(info.get("settletype.number"))) { // 012 应付票据(银行承兑汇票)
+//            DynamicObject payInterest =info.getDynamicObject("payInterest");
+//            if (payInterest != null) {
+//                paymentBill.setPAY_INTEREST(payInterest.get("number")+"");
+//            }
+//        }
+        return data;
+    }
+
+
+    public static String createSinglePaymentRequest(DynamicObject payBillEntity, String JKNO) {
+        try {
+            JSONObject param = new JSONObject();
+            headJson(param);
+            JSONObject datainfo = getServiceBean_youhua(payBillEntity);
+            param.put("data", datainfo);
+            param.put("txDateTime", Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("batchNo", TypeUtils.nullToString(payBillEntity.get("billno")) + "-" + TypeUtils.nullToString(payBillEntity.get("nckd_bbh")) + "-" + Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("code", JKNO);
+            String text = param.toString();
+            return text;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static void headJson(JSONObject param) {
+        param.put("nodeId", "client.001");
+        param.put("channelId", "EAS");
+        param.put("clientId", "001");
+        param.put("clientName", "金蝶");
+    }
+
+
+
+
+
+    /**
+     * 代发单支付
+     *
+     * @params billEntities
+     * @returns 返回报错信息
+     */
+    public static String agentpayBillForCBSSync(DynamicObject[] billEntities) {
+        StringBuffer errMsg = new StringBuffer();
+        //获取接口链接等信息
+        DynamicObject jkpzxx = BusinessDataServiceHelper.loadSingle("nckd_jkpzxx", new QFilter[]{new QFilter("number", "=", "paytoJHX")});
+        String url = jkpzxx.getString("nckd_servername");
+
+        for (DynamicObject dataEntity : billEntities) {
+            boolean isSuccess = false;//是否成功标识
+            boolean isZFQZ = true;
+            Map<String, String> qzObject = new HashMap<>();
+            DynamicObject payBillEntity = BusinessDataServiceHelper.loadSingle(dataEntity.getPkValue(), AGENT_ENTITY_NAME);
+
+
+            /**
+             *   判断是否可以走前置支付
+             *   1、代发单为审核状态
+             *   2、支付状态为未支付
+             */
+            String billNum = payBillEntity.getString("billno");
+            String billstatusString = payBillEntity.getString("billstatus");
+            String paystatus = payBillEntity.getString("nckd_paystatus");
+            int bbh = payBillEntity.getInt("nckd_bbh");
+            int fkcs = payBillEntity.getInt("nckd_fkcs");
+
+            if (!"C".equals(billstatusString)) {
+                errMsg.append("单据号:").append(billNum).append(",代发单为审核状态,才能提交~\r\n");
+                isZFQZ = false;
+            }
+            if (!"1".equals(paystatus) && !"".equals(paystatus)) {
+                errMsg.append("单据号:").append(billNum).append(",代发单为未支付,才能提交~\r\n");
+                isZFQZ = false;
+            }
+            if (bbh >= 1 && bbh != fkcs) {
+                errMsg.append("单据号:").append(billNum).append(",代发单未调整,请调整数据,或点击重付~\r\n");
+                isZFQZ = false;
+            }
+            if (payBillEntity.getDynamicObject("payeracctbank") == null) {
+                errMsg.append("单据号:").append(billNum).append(",付款账户为空~\r\n");
+                isZFQZ = false;
+            }
+            /***
+             * 审批时校验,如果资金银企行号包含,则提交九恒星,否则不提交。待补充
+             */
+
+
+            //构建支付数据导入请求xml
+            String qjjson = createSingleAgentPaymentRequest_1(payBillEntity);
+            if (qjjson == null) {
+                isZFQZ = false;
+                errMsg.append("单据号:").append(billNum).append("无法拼出正确的json请求~\r\n");
+            }
+
+            if (!isZFQZ) {
+                continue;
+            }
+            log.info("单据号:" + billNum + "传入参数" + qjjson);
+            if ("".equals(url)) {
+                url = "http://172.16.150.71:7081/FDLKF_OUTER/webservice/TxServiceGateway";
+            }
+
+            JSONObject cbsReturnJson = httpjhxService(url, qjjson);
+            log.info("单据号:" + billNum + "返回参数" + cbsReturnJson.toString());
+            //存入日志表
+            saveAgentlog(payBillEntity, qjjson, cbsReturnJson.toString(), "1");
+
+            if (cbsReturnJson == null) {
+                isSuccess = false;
+                errMsg.append("单据号:").append(billNum).append(",推送资金系统失败,");
+                errMsg.append("错误号:").append("XXXXXXX");
+                errMsg.append(",错误原因:").append("接口无法连通,未获取到返回结果");
+                errMsg.append("\r\n");
+            } else if (!"000000".equals(cbsReturnJson.get("resultCode"))) {
+                isSuccess = false;
+                String resultCode = cbsReturnJson.get("resultCode")+"";
+                String resultMsg = cbsReturnJson.get("resultMsg") + "";
+
+                if("JFXXXXC".equals(resultCode)){//超时,有可能成功,所以不处理
+                    isSuccess = false;
+                    errMsg.append("单据号:").append(billNum).append(",推送资金系统失败,");
+                    errMsg.append("错误号:").append(cbsReturnJson.get("resultCode"));
+                    errMsg.append(",错误原因:").append(resultMsg);
+                    errMsg.append("\r\n");
+                }else if (resultMsg.indexOf("单据是非驳回状态") >= 0 || resultMsg.indexOf("付款指令重复") >= 0) {//指令重复,说明已经传过去了,改状态为支付中,查询结果
+                    isSuccess = true;
+                    errMsg.append("单据号:").append(billNum).append("付款指令重复,说明已推送到资金系统!");
+                    payBillEntity.set("nckd_fkcs", fkcs + 1);//付款次数+1
+                    payBillEntity.set("nckd_sbyy", "指令重复,已推送到资金系统");//返回信息
+                    payBillEntity.set("nckd_paystatus", 2);//支付中
+                } else { //如果不是驳回或重发,失败
+                    errMsg.append("单据号:").append(billNum).append(",推送资金系统失败,");
+                    errMsg.append("错误号:").append(cbsReturnJson.get("resultCode"));
+                    errMsg.append(",错误原因:").append(resultMsg);
+                    errMsg.append("\r\n");
+                    payBillEntity.set("nckd_fkcs", fkcs + 1);//付款次数+1
+                    payBillEntity.set("nckd_paystatus", 4);//传输失败
+                    payBillEntity.set("nckd_sbyy", cbsReturnJson.get("resultMsg") + "");//错误信息
+                    SaveServiceHelper.update(new DynamicObject[]{payBillEntity});
+                }
+            } else if ("000000".equals(cbsReturnJson.get("resultCode"))) {//已受理,改为支付中
+                String resultMsg = cbsReturnJson.get("resultMsg") + "";
+                if ("SUCCESS".equals(resultMsg)) {
+                    isSuccess = true;
+                    errMsg.append("单据号:").append(billNum).append(",推送资金系统成功!");
+                    payBillEntity.set("nckd_fkcs", fkcs + 1);//付款次数+1
+                    payBillEntity.set("nckd_sbyy", "传输成功");//返回信息
+                    payBillEntity.set("nckd_paystatus", 2);//支付中
+                }
+            }
+            if (isSuccess) {
+                SaveServiceHelper.update(new DynamicObject[]{payBillEntity});
+            }
+        }
+        return errMsg.toString();
+    }
+
+
+    /**
+     * 支付单同步
+     *
+     * @params billEntities
+     * @returns 返回报错信息
+     */
+    public static String payBillForCBSSync(DynamicObject[] billEntities) {
+        StringBuffer errMsg = new StringBuffer();
+        //获取接口链接等信息
+        DynamicObject jkpzxx = BusinessDataServiceHelper.loadSingle("nckd_jkpzxx", new QFilter[]{new QFilter("number", "=", "paytoJHX")});
+
+        String url = jkpzxx.get("nckd_servername") + "";
+        for (DynamicObject dataEntity : billEntities) {
+            boolean isSuccess = false;
+            boolean isZFQZ = true;
+            DynamicObject payBillEntity = BusinessDataServiceHelper.loadSingle(dataEntity.getPkValue(), ENTITY_NAME);
+
+
+            /**
+             *   判断是否可以走前置支付
+             *   1、付款单为审核状态
+             *   2、支付状态为未支付
+             *   3、版本号>=1时,必须等于付款次数
+             */
+            String billNum = payBillEntity.getString("billno");
+            String billstatusString = payBillEntity.getString("billstatus");
+            String paystatus = payBillEntity.getString("nckd_paystatus");
+            int bbh = payBillEntity.getInt("nckd_bbh");
+            int fkcs = payBillEntity.getInt("nckd_fkcs");
+
+
+            //查询流水,如果存在流水,则不能支付
+            String billno = payBillEntity.get("billno") + "";
+//            QFilter orgFilter = new QFilter("nckd_reserve80", "like", "%"+billno+"%");
+//            DynamicObject fkclinfo = BusinessDataServiceHelper.loadSingle("bei_transdetail","",new QFilter[]{orgFilter});
+
+
+            if (!"C".equals(billstatusString)) {
+                errMsg.append("单据号:").append(billNum).append(",付款单为审核状态,才能提交~\r\n");
+                isZFQZ = false;
+            }
+            if (!"1".equals(paystatus) && !"".equals(paystatus)) {
+                errMsg.append("单据号:").append(billNum).append(",付款单为未支付,才能提交~\r\n");
+                isZFQZ = false;
+            }
+            if (bbh >= 1 && bbh != fkcs) {
+                errMsg.append("单据号:").append(billNum).append(",付款单未调整,请调整数据,或点击重付~\r\n");
+                isZFQZ = false;
+            }
+            if (payBillEntity.getDynamicObject("payeracctbank") == null) {
+                errMsg.append("单据号:").append(billNum).append(",付款账户为空~\r\n");
+                isZFQZ = false;
+            }
+            if (payBillEntity.getDynamicObject("payeebank") == null) {
+                errMsg.append("单据号:").append(billNum).append(",收款账户为空~\r\n");
+                isZFQZ = false;
+            }
+            //流水判断 待补充
+//            if(fkclinfo!=null && isZFQZ) {
+//                errMsg.append("单据号:").append(billNum).append(",已存在支付流水,为防止重复付款,无法提交。请联系运维核查数据\r\n");
+//                isZFQZ = false;
+//            }
+
+            //是否资金调度逻辑,用新增入口
+            boolean IS_TRANSFER = false;//判断是否资金调度
+            String entrance = payBillEntity.get("entrance") + "";
+            if ("SYN".equals(entrance) || "SPAN".equals(entrance)) {
+                IS_TRANSFER = true;
+            }
+//            if(IS_TRANSFER){
+//                isZFQZ = false;
+//                errMsg.append("单据号:").append(billNum).append(",跨主体调拨或者同名转账~\r\n");
+//            }
+
+            /***
+             * 根据付款单结算方式,结算方式类似承兑的调用资金的票据接口,结算方式为其他的调用资金的对外付款接口
+             */
+            String JKNO = "";
+            String settletype = payBillEntity.get("settletype.number") + "";
+            if (settletype != null && !"".equals(settletype)) {
+                if (settletype.equals("BILL")) {//票据
+                    JKNO = "NSTC-T002";
+                } else {
+                    JKNO = "NSTC-T001";
+                }
+            } else {
+                isZFQZ = false;
+                errMsg.append("单据号:").append(billNum).append(",结算方式为空~\r\n");
+            }
+
+
+            //付款单审批时校验未上线银行基础数据资料表,待补充
+            /***
+             * 审批时校验,如果资金银企行号包含,则提交九恒星,否则不提交。
+             */
+
+
+            String qjjson = "";
+            if (isZFQZ) {
+                //构建请求对象
+                qjjson = createSinglePaymentRequest(payBillEntity, JKNO);
+                if (qjjson == null) {
+                    isZFQZ = false;
+                    errMsg.append("单据号:").append(billNum).append(",无法拼出正确的json请求~\r\n");
+                }
+            }
+
+            if (!isZFQZ) {
+                continue;
+            }
+            //qjjson = "{\"code\":\"NSTC-T001\",\"batchNo\":\"PV-202504-000041-0-20250427106427\",\"nodeId\":\"client.001\",\"channelId\":\"EAS\",\"clientId\":\"001\",\"clientName\":\"金蝶\",\"txDateTime\":\"20250425175615\",\"data\":{\"ERP_INS_ID\":\""+billNum+"-"+bbh+"\",\"PAY_CLT_NO\":\"A004\",\"CLT_NO\":null,\"PAY_ACNT_NO\":\"824581178610001\",\"PAY_ACNT_NAME\":null,\"PAY_BANK\":null,\"PAY_CNAPS\":\"308421022063\",\"PAY_DATE\":\"2025-04-25\",\"AMOUNT\":3234,\"CASHAMOUNT\":null,\"BILLAMOUNT\":null,\"CURRENCY\":\"BB01\",\"BUSS_TYPE\":null,\"RECE_ACC_NO\":\"1\",\"RECE_ACC_NAME\":\"1\",\"RECE_OPBANK_NAME\":\"非税缴款\",\"RECE_BANK_NO\":null,\"RECE_CNAPS\":\"001100000001\",\"REG_NO\":null,\"IS_PERSON\":\"0\",\"URGENT_FLAG\":\"0\",\"PURPOSE\":\"用途\",\"REMARK\":\"缴款码(XXX)\",\"CREATOR\":\"张清全\",\"CREATE_TIME\":\"2025-04-25\",\"ERP_PAYNO\":\"PV-202504-000041-0\",\"TERM\":null,\"IS_TRANSFER\":\"0\",\"PAY_FLAG\":null,\"FBillStatus\":12,\"PAY_NUM\":0,\"OP_ACNT_LIST\":null}}";
+            log.info("单据号:" + billNum + "传入参数" + qjjson);
+            if ("".equals(url)) {
+                url = "http://172.16.150.71:7081/FDLKF_OUTER/webservice/TxServiceGateway";
+            }
+
+
+            JSONObject cbsReturnJson = httpjhxService(url, qjjson);
+            log.info("单据号:" + billNum + "返回参数" + cbsReturnJson.toString());
+            //存入日志表
+            savelog(payBillEntity, qjjson, cbsReturnJson.toString());
+
+
+            if (cbsReturnJson == null) {
+                isSuccess = false;
+                errMsg.append("单据号:").append(billNum).append(",推送资金系统失败,");
+                errMsg.append("错误号:").append("XXXXXXX");
+                errMsg.append(",错误原因:").append("接口无法连通,未获取到返回结果");
+                errMsg.append("\r\n");
+            }if (!"000000".equals(cbsReturnJson.get("resultCode"))) {
+                isSuccess = false;
+                String resultCode = cbsReturnJson.get("resultCode")+"";
+                String resultMsg = cbsReturnJson.get("resultMsg") + "";
+                if("JFXXXXC".equals(resultCode)){//超时,有可能成功,所以不处理
+                    isSuccess = false;
+                    errMsg.append("单据号:").append(billNum).append(",推送资金系统失败,");
+                    errMsg.append("错误号:").append(cbsReturnJson.get("resultCode"));
+                    errMsg.append(",错误原因:").append(resultMsg);
+                    errMsg.append("\r\n");
+                }else if (resultMsg.indexOf("单据是非驳回状态") >= 0 || resultMsg.indexOf("付款指令重复") >= 0) {//指令重复,说明已经传过去了,改状态为支付中,查询结果
+                    isSuccess = true;
+                    errMsg.append("单据号:").append(billNum).append("付款指令重复,说明已推送到资金系统!");
+                    payBillEntity.set("nckd_fkcs", fkcs + 1);//付款次数+1
+                    payBillEntity.set("nckd_sbyy", "指令重复,已推送到资金系统");//返回信息
+                    payBillEntity.set("nckd_paystatus", 2);//支付中
+                } else { //如果不是驳回或重发,失败
+                    errMsg.append("单据号:").append(billNum).append(",推送资金系统失败,");
+                    errMsg.append("错误号:").append(cbsReturnJson.get("resultCode"));
+                    errMsg.append(",错误原因:").append(resultMsg);
+                    errMsg.append("\r\n");
+                    payBillEntity.set("nckd_fkcs", fkcs + 1);//付款次数+1
+                    payBillEntity.set("nckd_paystatus", 4);//传输失败
+                    payBillEntity.set("nckd_sbyy", cbsReturnJson.get("resultMsg") + "");//错误信息
+                    SaveServiceHelper.update(new DynamicObject[]{payBillEntity});
+                }
+            } else if ("000000".equals(cbsReturnJson.get("resultCode"))) {//已受理,改为支付中
+                String resultMsg = cbsReturnJson.get("resultMsg") + "";
+                if ("SUCCESS".equals(resultMsg)) {
+                    isSuccess = true;
+                    errMsg.append("单据号:").append(billNum).append(",推送资金系统成功!");
+                    payBillEntity.set("nckd_fkcs", fkcs + 1);//付款次数+1
+                    payBillEntity.set("nckd_sbyy", "传输成功");//返回信息
+                    payBillEntity.set("nckd_paystatus", 2);//支付中
+                }
+            }
+
+            if (isSuccess) {
+                SaveServiceHelper.update(new DynamicObject[]{payBillEntity});
+            }
+        }
+        return errMsg.toString();
+    }
+
+
+    public static void saveAgentlog(DynamicObject payBillEntity, String qqbw, String fhbw, String type) {
+        try {
+            DynamicObject logInfo = new DynamicObject(EntityMetadataCache.getDataEntityType("nckd_dfjkdyrz"));
+            String channelserno = payBillEntity.getString("billno");
+            logInfo.set("number", channelserno);
+            if ("1".equals(type)) {
+                logInfo.set("name", payBillEntity.get("billno") + "支付数据传输日志");
+            } else if ("6".equals(type)) {
+                logInfo.set("name", payBillEntity.get("billno") + "代发单支付信息查询日志");
+            }
+            logInfo.set("nckd_jklx", type);
+            logInfo.set("status", "A");
+            logInfo.set("enable", "1");
+            Calendar currentdate = Calendar.getInstance();
+            logInfo.set("nckd_redate", currentdate.getTime());
+            logInfo.set("nckd_billno", payBillEntity.get("billno"));
+            logInfo.set("nckd_payid", payBillEntity.getPkValue() + "");
+            logInfo.set("nckd_qqbw_tag", qqbw);
+            logInfo.set("nckd_fhbw_tag", fhbw);
+            logInfo.set("nckd_redate", new Date());
+
+            logInfo.set("nckd_djlx", "2");
+            OperationServiceHelper.executeOperate("save", "nckd_zfjkdyrz", new DynamicObject[]{logInfo});
+
+        } catch (Exception e) {
+            log.info("保存日志报错" + e.getMessage());
+
+        }
+
+
+    }
+
+    public static void savePayDayChecklog(String qqbw, String fhbw) {
+        try {
+            DynamicObject logInfo = new DynamicObject(EntityMetadataCache.getDataEntityType("nckd_paydaycheck"));
+            Calendar currentdate = Calendar.getInstance();
+            String enddzrq = TypeUtils.date2String(currentdate.getTime(), "yyyy-MM-dd HH:mm:ss");
+
+            logInfo.set("number", enddzrq);
+            logInfo.set("name", enddzrq + "付款日结查询日志");
+            logInfo.set("status", "A");
+            logInfo.set("enable", "1");
+            logInfo.set("nckd_qqbw_tag", qqbw);
+            logInfo.set("nckd_fhbw_tag", fhbw);
+            OperationServiceHelper.executeOperate("save", "nckd_paydaycheck", new DynamicObject[]{logInfo});
+
+        } catch (Exception e) {
+            log.info("保存日志报错" + e.getMessage());
+
+        }
+
+
+    }
+
+
+    public static void savelog(DynamicObject payBillEntity, String qqbw, String fhbw) {
+        try {
+            DynamicObject logInfo = new DynamicObject(EntityMetadataCache.getDataEntityType("nckd_zfjkdyrz"));
+            String channelserno = payBillEntity.get("billno") + "-" + payBillEntity.getInt("nckd_bbh");
+            logInfo.set("number", channelserno);
+            logInfo.set("name", payBillEntity.get("billno") + "付款日志");
+            logInfo.set("status", "A");
+            logInfo.set("enable", "1");
+            Calendar currentdate = Calendar.getInstance();
+            logInfo.set("nckd_redate", currentdate.getTime());
+            logInfo.set("nckd_billno", payBillEntity.get("billno"));
+            logInfo.set("nckd_payid", payBillEntity.getPkValue() + "");
+            logInfo.set("nckd_qqbw_tag", qqbw);
+            logInfo.set("nckd_fhbw_tag", fhbw);
+            logInfo.set("nckd_redate", new Date());
+
+            logInfo.set("nckd_djlx", "1");
+            OperationServiceHelper.executeOperate("save", "nckd_zfjkdyrz", new DynamicObject[]{logInfo});
+
+        } catch (Exception e) {
+            log.info("保存日志报错" + e.getMessage());
+
+        }
+
+
+    }
+
+
+    public static void saveupdatelog(DynamicObject payBillEntity, String qqbw, String fhbw) {
+        try {
+            DynamicObject logInfo = new DynamicObject(EntityMetadataCache.getDataEntityType("nckd_zfcxjkrz"));
+            String channelserno = payBillEntity.get("billno") + "-" + payBillEntity.getInt("nckd_bbh");
+            logInfo.set("number", channelserno);
+            logInfo.set("name", payBillEntity.get("billno") + "查询状态日志");
+            logInfo.set("status", "A");
+            logInfo.set("enable", "1");
+            Calendar currentdate = Calendar.getInstance();
+            logInfo.set("nckd_redate", currentdate.getTime());
+            logInfo.set("nckd_billno", payBillEntity.get("billno"));
+            logInfo.set("nckd_payid", payBillEntity.getPkValue() + "");
+            logInfo.set("nckd_qqbw_tag", qqbw);
+            logInfo.set("nckd_fhbw_tag", fhbw);
+            logInfo.set("nckd_redate", new Date());
+
+            logInfo.set("nckd_djlx", "1");
+            OperationServiceHelper.executeOperate("save", "nckd_zfcxjkrz", new DynamicObject[]{logInfo});
+
+        } catch (Exception e) {
+            log.info("保存日志报错" + e.getMessage());
+
+        }
+
+
+    }
+
+    public static JSONObject httpjhxService(String url, String qjjson) {
+        String result = "";
+        try {
+            Date d1 = new Date();
+            TxServiceGatewayProxy txServiceGatewayProxy = new TxServiceGatewayProxy("", url);
+            result = txServiceGatewayProxy.send(qjjson);
+
+            Date d2 = new Date();
+
+            long diffs = Math.abs(d2.getTime() - d1.getTime()) / 1000;
+            JSONObject jsonObject = new JSONObject(result);
+            if (jsonObject != null) {
+                if ("{}".equals(jsonObject.toString()) || "".equals(result)) {
+                    if (diffs > 60) {//超时
+
+                        jsonObject.put("resultCode", "JFXXXXC");
+                        jsonObject.put("resultMsg", "超时");
+
+                    }
+
+                }
+                jsonObject.put("请求时间", TypeUtils.date2String(d1, TypeUtils.DEFAULT_TIMESTAMP_FORMAT));
+                jsonObject.put("返回时间", TypeUtils.date2String(d2, TypeUtils.DEFAULT_TIMESTAMP_FORMAT));
+                jsonObject.put("响应时长", diffs + "");
+            }
+            return jsonObject;
+        } catch (IOException e) {
+            e.printStackTrace();
+            log.info(e.getMessage());
+        }
+        return null;
+    }
+
+
+    public static JSONObject JHXServiceQuery(String url, String bodyjson) {
+        try {
+            Date d1 = new Date();
+            TxServiceGatewayProxy txServiceGatewayProxy = new TxServiceGatewayProxy("", url);
+            String result = txServiceGatewayProxy.send(bodyjson);
+
+            Date d2 = new Date();
+
+            long diffs = Math.abs(d2.getTime() - d1.getTime()) / 1000;
+
+            JSONObject jsonObject = new JSONObject(result);
+            if (jsonObject != null || "".equals(result) || result == null) {
+                if ("{}".equals(jsonObject.toString())) {
+                    if (diffs > 60) {//超时
+
+                        jsonObject.put("resultCode", "JFXXXXC");
+                        jsonObject.put("resultMsg", "超时");
+                    }
+
+                }
+                jsonObject.put("请求时间", TypeUtils.date2String(d1, TypeUtils.DEFAULT_TIMESTAMP_FORMAT));
+                jsonObject.put("返回时间", TypeUtils.date2String(d2, TypeUtils.DEFAULT_TIMESTAMP_FORMAT));
+                jsonObject.put("响应时长", diffs + "");
+            }
+
+            return jsonObject;
+        } catch (IOException e) {
+            e.printStackTrace();
+            log.info(e.getMessage());
+        }
+        return null;
+    }
+
+
+}

+ 64 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/PayToZFQZOP.java

@@ -0,0 +1,64 @@
+package fi.cas.opplugin;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
+import kd.bos.entity.plugin.args.BeforeOperationArgs;
+import com.alibaba.druid.util.StringUtils;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+
+
+public class PayToZFQZOP  extends AbstractOperationServicePlugIn {
+    private static final String ENTITY_NAME = "cas_paybill";
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+
+
+    }
+
+    @Override
+    public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
+
+        String errMsg = "";
+
+        //获取选中行
+        DynamicObject[] billEntities = e.getDataEntities();
+        String operationKey = e.getOperationKey();
+
+
+        //获取操作按钮操作编码
+        if (StringUtils.equals( "paytojhx",operationKey)){
+            for (DynamicObject dataEntity : billEntities) {
+                DynamicObject payBillEntity = BusinessDataServiceHelper.loadSingle(dataEntity.getPkValue(), ENTITY_NAME);
+
+                String paystatus = payBillEntity.getString("nckd_paystatus");
+                int bbh = payBillEntity.getInt("nckd_bbh");
+                int fkcs = payBillEntity.getInt("nckd_fkcs");
+                String billstatusString = payBillEntity.getString("billstatus");
+                if ("C".equals(billstatusString)&&("4".equals(paystatus)||"5".equals(paystatus))&&bbh>=0 && bbh==fkcs-1) {//状态为传输失败或驳回,(驳回必须走调整才能支付)
+                    //状态为已审批,支付状态为失败,版本号>0,版本号=付款次数-1。符合付款条件,修改状态和版本号先
+                    payBillEntity.set("nckd_paystatus", "1");//支付状态改回未支付
+                    payBillEntity.set("nckd_bbh",bbh+1);
+                    SaveServiceHelper.update(payBillEntity);
+                }
+            }
+            errMsg =  PayBillToolUtil.payBillForCBSSync(billEntities);
+        }
+        if(!errMsg.isEmpty()) {
+            //将成功错误信息返回到前端
+            e.setCancelMessage(errMsg);
+            e.setCancel(true);
+        }
+    }
+
+
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+        super.afterExecuteOperationTransaction(e);
+
+    }
+}

+ 145 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/PaymentProcessOpPlugin.java

@@ -0,0 +1,145 @@
+package fi.cas.opplugin;
+
+import com.alibaba.druid.util.StringUtils;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+
+//付款处理单付款反写
+public class PaymentProcessOpPlugin extends AbstractOperationServicePlugIn {
+    private static String nckd_cas_arbill_gz_l = "ar_finarbill"; //应收挂帐单标识
+    private static String nckd_er_prepaybill_ext = "er_prepaybill"; //预付借款单标识
+    private static String nckd_er_publicreimbur_ext = "er_publicreimbursebill"; //报销单标识
+    private static String er_contractbill = "er_contractbill"; //合同台账单标识
+    private static String nckd_ap_finapbill_gz = "ap_finapbill"; //应付挂账单标识
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        //获取付款处理单据信息
+        DynamicObject[] dynamicObjects = e.getDataEntities();
+        for (int i = 0; i < dynamicObjects.length; i++) {
+            //当前单头数据包
+            DynamicObject info = BusinessDataServiceHelper.loadSingle(dynamicObjects[i].getPkValue(), dynamicObjects[i].getDynamicObjectType().getName());
+            //付款金额
+            BigDecimal actpayamt = info.getBigDecimal("actpayamt");
+            //单据编号
+            String billno = info.getString("billno");
+            //付款处理id
+            long id = info.getLong("id");
+            //付款日期
+            Date paydate = info.getDate("paydate");
+            //获取源单id
+            Long sourcebillid = info.getLong("sourcebillid");
+            //存储源单分录id和付款处理分录实付金额
+            HashMap<Long,BigDecimal> amountMap = new HashMap<>();
+            //循环付款明细分录
+            for (DynamicObject entryentity : info.getDynamicObjectCollection("entry")) {
+                //取当前循环付款明细分录的实付金额
+                BigDecimal expenseamount = entryentity.getBigDecimal("e_actamt");
+                //取当前循环付款明细分录的源单分录id
+                Long sourcebillentryid = entryentity.getLong("e_sourcebillentryid");
+                amountMap.put(sourcebillentryid,expenseamount);
+            }
+            //查询应收挂账单
+            QFilter gzFilter = new QFilter("id", QCP.equals,sourcebillid);
+            DynamicObject[] gzDynamicObjects = BusinessDataServiceHelper.load(nckd_cas_arbill_gz_l,"id",new QFilter[] {gzFilter});
+
+            //查询报销单
+            QFilter bxFilter = new QFilter("id", QCP.equals,sourcebillid);
+            DynamicObject[] bxDynamicObjects = BusinessDataServiceHelper.load(nckd_er_publicreimbur_ext,"id",new QFilter[] {bxFilter});
+            //应收方向的回写
+            if (gzDynamicObjects.length > 0) {
+                //循环数组获取结算状态,已结算金额,未结算金额
+                for (int c=0;c<gzDynamicObjects.length;c++) {
+                    //应收挂帐单头数据包
+                    DynamicObject gzInfo = BusinessDataServiceHelper.loadSingle(gzDynamicObjects[c].getPkValue(), gzDynamicObjects[c].getDynamicObjectType().getName());
+                    //获取预付借款单id
+                    String yfjkId = gzInfo.getString("sourcebillid");
+                    if (!StringUtils.isEmpty(yfjkId)) {
+                        //存储预付借款单分录id和付款处理分录实付金额
+                        HashMap<Long,BigDecimal> yfjkMap = new HashMap<>();
+                        //循环应收挂帐单付款明细分录
+                        for (DynamicObject entryentity : gzInfo.getDynamicObjectCollection("entry")) {
+                            //获取分录实付金额
+                            BigDecimal nckd_amountfield5 = amountMap.get(entryentity.getLong("id")) == null ? BigDecimal.ZERO:amountMap.get(entryentity.getLong("id"));
+                            //获取未结算金额
+                            BigDecimal nckd_amountfield7 = entryentity.getBigDecimal("nckd_amountfield7");
+                            nckd_amountfield7 = nckd_amountfield7.subtract(nckd_amountfield5);
+                            //反写分录已付金额,未付金额
+                            entryentity.set("nckd_amountfield5",nckd_amountfield5);
+                            entryentity.set("nckd_amountfield7",nckd_amountfield7);
+                            Long yfjkSourceBillEntryId = entryentity.getLong("e_srcentryid");
+                            yfjkMap.put(yfjkSourceBillEntryId,nckd_amountfield5);
+                        }
+                        SaveServiceHelper.save(new DynamicObject[]{gzInfo});
+
+                        //查询预付借款单
+                        Long prebillId = Long.valueOf(yfjkId);
+                        QFilter nckd_yfjkFilter = new QFilter("id", QCP.equals,prebillId);
+                        DynamicObject[] yfjkDynamicObjects = BusinessDataServiceHelper.load(nckd_er_prepaybill_ext,"id",new QFilter[] {nckd_yfjkFilter});
+                        //循环数组获取结算状态,已结算金额,未结算金额
+                        for (int d=0;d<yfjkDynamicObjects.length;d++) {
+                            BigDecimal nckd_amountfield5 = BigDecimal.ZERO;
+                            BigDecimal nckd_amountfield6 = BigDecimal.ZERO;
+                            //预付借款单头数据包
+                            DynamicObject yfjkInfo = BusinessDataServiceHelper.loadSingle(yfjkDynamicObjects[d].getPkValue(), yfjkDynamicObjects[d].getDynamicObjectType().getName());
+                            //循环预付借款单预付借款信息分录
+                            for (DynamicObject entryentity : yfjkInfo.getDynamicObjectCollection("expenseentryentity")) {
+                                //获取分录实付金额
+                                BigDecimal nckd_amountfield4 = yfjkMap.get(entryentity.getLong("id")) == null ? BigDecimal.ZERO:yfjkMap.get(entryentity.getLong("id"));
+                                //获取未结算金额
+                                BigDecimal nckd_amountfield3 = entryentity.getBigDecimal("nckd_amountfield3");
+                                nckd_amountfield3 = nckd_amountfield3.subtract(nckd_amountfield4);
+                                //反写分录已结算金额,未结算金额
+                                entryentity.set("nckd_amountfield4",nckd_amountfield4);
+                                entryentity.set("nckd_amountfield3",nckd_amountfield3);
+                                nckd_amountfield5 = nckd_amountfield5.add(nckd_amountfield4);
+                                nckd_amountfield6 = nckd_amountfield6.add(nckd_amountfield3);
+                            }
+                            yfjkInfo.set("nckd_amountfield5", nckd_amountfield5);
+                            yfjkInfo.set("nckd_amountfield6", nckd_amountfield6);
+                            yfjkInfo.set("billstatus", "G");
+                            SaveServiceHelper.save(new DynamicObject[]{yfjkInfo});
+                        }
+                    }
+                }
+            }//应付方向的回写
+            else if (bxDynamicObjects.length > 0) {
+                //循环数组获取结算状态,已结算金额,未结算金额
+                for (int c=0;c<bxDynamicObjects.length;c++) {
+                    //报销单头数据包
+                    DynamicObject bxInfo = BusinessDataServiceHelper.loadSingle(bxDynamicObjects[c].getPkValue(), bxDynamicObjects[c].getDynamicObjectType().getName());
+                    String nckd_sourcebillid = bxInfo.getString("nckd_sourcebillid");
+                    //报账类型等于工程报账回写合同台账单
+                    if (!StringUtils.isEmpty(nckd_sourcebillid)) {
+                        //获取合同台账单id
+                        Long contractbillId = Long.parseLong(nckd_sourcebillid);
+                        //查询合同台账单
+                        QFilter htFilter = new QFilter("id", QCP.equals,contractbillId);
+                        DynamicObject[] htDynamicObjects = BusinessDataServiceHelper.load(er_contractbill,"id",new QFilter[] {htFilter});
+                        for (int j=0;j<htDynamicObjects.length;j++) {
+                            //合同台账单头数据包
+                            DynamicObject htInfo = BusinessDataServiceHelper.loadSingle(htDynamicObjects[j].getPkValue(), htDynamicObjects[j].getDynamicObjectType().getName());
+                            //反写付款明细
+                            DynamicObjectCollection entryEntity = htInfo.getDynamicObjectCollection("nckd_payentry");
+                            DynamicObject entry1 = entryEntity.addNew();
+                            entry1.set("nckd_pay_billno1", billno);//付款处理单据编号
+                            entry1.set("nckd_pay_id1", id);//付款处理单据id
+                            entry1.set("nckd_amountfield1", actpayamt);//付款金额
+                            entry1.set("nckd_timefield2", paydate);//付款日期
+                            SaveServiceHelper.save(new DynamicObject[]{htInfo});
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 77 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGatewayProxy.java

@@ -0,0 +1,77 @@
+package fi.cas.opplugin;
+import java.rmi.RemoteException;
+import javax.xml.rpc.ServiceException;
+import javax.xml.rpc.Stub;
+
+public class TxServiceGatewayProxy implements TxServiceGateway_PortType {
+    private String _endpoint = null;
+    private TxServiceGateway_PortType txServiceGateway_PortType = null;
+
+    public TxServiceGatewayProxy() {
+        _initTxServiceGatewayProxy();
+    }
+
+    public TxServiceGatewayProxy(String endpoint) {
+        this._endpoint = endpoint;
+        _initTxServiceGatewayProxy();
+    }
+
+    public TxServiceGatewayProxy(String endpoint,String url) {
+        _initTxServiceGatewayProxy(url);
+    }
+
+    private void _initTxServiceGatewayProxy(String url) {
+        try {
+            this.txServiceGateway_PortType = new TxServiceGateway_ServiceLocator(url)
+                    .getTxServiceGatewayPort();
+            if (this.txServiceGateway_PortType != null)
+                if (this._endpoint != null)
+                    ((Stub) this.txServiceGateway_PortType)._setProperty(
+                            "javax.xml.rpc.service.endpoint.address",
+                            this._endpoint);
+                else
+                    this._endpoint = ((String) ((Stub) this.txServiceGateway_PortType)
+                            ._getProperty("javax.xml.rpc.service.endpoint.address"));
+        } catch (ServiceException localServiceException) {
+        }
+    }
+
+    private void _initTxServiceGatewayProxy() {
+        try {
+            this.txServiceGateway_PortType = new TxServiceGateway_ServiceLocator()
+                    .getTxServiceGatewayPort();
+            if (this.txServiceGateway_PortType != null)
+                if (this._endpoint != null)
+                    ((Stub) this.txServiceGateway_PortType)._setProperty(
+                            "javax.xml.rpc.service.endpoint.address",
+                            this._endpoint);
+                else
+                    this._endpoint = ((String) ((Stub) this.txServiceGateway_PortType)
+                            ._getProperty("javax.xml.rpc.service.endpoint.address"));
+        } catch (ServiceException localServiceException) {
+        }
+    }
+
+    public String getEndpoint() {
+        return this._endpoint;
+    }
+
+    public void setEndpoint(String endpoint) {
+        this._endpoint = endpoint;
+        if (this.txServiceGateway_PortType != null)
+            ((Stub) this.txServiceGateway_PortType)._setProperty(
+                    "javax.xml.rpc.service.endpoint.address", this._endpoint);
+    }
+
+    public TxServiceGateway_PortType getTxServiceGateway_PortType() {
+        if (this.txServiceGateway_PortType == null)
+            _initTxServiceGatewayProxy();
+        return this.txServiceGateway_PortType;
+    }
+
+    public String send(String message) throws RemoteException {
+        if (this.txServiceGateway_PortType == null)
+            _initTxServiceGatewayProxy();
+        return this.txServiceGateway_PortType.send(message);
+    }
+}

+ 141 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGatewaySoapBindingStub.java

@@ -0,0 +1,141 @@
+package fi.cas.opplugin;
+
+import java.net.URL;
+import java.rmi.RemoteException;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Vector;
+import javax.xml.namespace.QName;
+import org.apache.axis.AxisFault;
+import org.apache.axis.NoEndPointException;
+import org.apache.axis.client.Call;
+import org.apache.axis.client.Stub;
+import org.apache.axis.constants.Style;
+import org.apache.axis.constants.Use;
+import org.apache.axis.description.OperationDesc;
+import org.apache.axis.description.ParameterDesc;
+import org.apache.axis.soap.SOAPConstants;
+import org.apache.axis.utils.JavaUtils;
+
+public class TxServiceGatewaySoapBindingStub extends Stub implements
+        TxServiceGateway_PortType {
+    private Vector cachedSerClasses;
+    private Vector cachedSerQNames;
+    private Vector cachedSerFactories;
+    private Vector cachedDeserFactories;
+    static OperationDesc[] _operations = new OperationDesc[1];
+
+    static {
+        _initOperationDesc1();
+    }
+
+    private static void _initOperationDesc1() {
+        OperationDesc oper = new OperationDesc();
+        oper.setName("send");
+        ParameterDesc param = new ParameterDesc(new QName("", "message"), (byte)1,
+                new QName("http://www.w3.org/2001/XMLSchema", "string"),
+                String.class, false, false);
+        param.setOmittable(true);
+        oper.addParameter(param);
+        oper.setReturnType(new QName("http://www.w3.org/2001/XMLSchema",
+                "string"));
+        oper.setReturnClass(String.class);
+        oper.setReturnQName(new QName("", "returnMessage"));
+        oper.setStyle(Style.WRAPPED);
+        oper.setUse(Use.LITERAL);
+        _operations[0] = oper;
+    }
+
+    public TxServiceGatewaySoapBindingStub() throws AxisFault {
+        this(null);
+    }
+
+    public TxServiceGatewaySoapBindingStub(URL endpointURL,
+                                           javax.xml.rpc.Service service) throws AxisFault {
+        this(service);
+        this.cachedEndpoint = endpointURL;
+    }
+
+    public TxServiceGatewaySoapBindingStub(javax.xml.rpc.Service service)
+            throws AxisFault {
+        this.cachedSerClasses = new Vector();
+        this.cachedSerQNames = new Vector();
+        this.cachedSerFactories = new Vector();
+        this.cachedDeserFactories = new Vector();
+
+        if (service == null)
+            this.service = new org.apache.axis.client.Service();
+        else {
+            this.service = service;
+        }
+        ((org.apache.axis.client.Service) this.service)
+                .setTypeMappingVersion("1.2");
+    }
+
+    protected Call createCall() throws RemoteException {
+        try {
+            Call _call = super._createCall();
+            if (this.maintainSessionSet) {
+                _call.setMaintainSession(this.maintainSession);
+            }
+            if (this.cachedUsername != null) {
+                _call.setUsername(this.cachedUsername);
+            }
+            if (this.cachedPassword != null) {
+                _call.setPassword(this.cachedPassword);
+            }
+            if (this.cachedEndpoint != null) {
+                _call.setTargetEndpointAddress(this.cachedEndpoint);
+            }
+            if (this.cachedTimeout != null) {
+                _call.setTimeout(this.cachedTimeout);
+            }
+            if (this.cachedPortName != null) {
+                _call.setPortName(this.cachedPortName);
+            }
+            Enumeration keys = this.cachedProperties.keys();
+            while (keys.hasMoreElements()) {
+                String key = (String) keys.nextElement();
+                _call.setProperty(key, this.cachedProperties.get(key));
+            }
+            return _call;
+        } catch (Throwable _t) {
+            throw new AxisFault("Failure trying to get the Call object", _t);
+        }
+    }
+
+    public String send(String message) throws RemoteException {
+        if (this.cachedEndpoint == null) {
+            throw new NoEndPointException();
+        }
+        Call _call = createCall();
+        _call.setOperation(_operations[0]);
+        _call.setUseSOAPAction(true);
+        _call.setSOAPActionURI("");
+        _call.setEncodingStyle(null);
+        _call.setProperty("sendXsiTypes", Boolean.FALSE);
+        _call.setProperty("sendMultiRefs", Boolean.FALSE);
+        _call.setSOAPVersion(SOAPConstants.SOAP11_CONSTANTS);
+        _call.setOperationName(new QName("http://webservice.fdlk.nstc.com",
+                "send"));
+
+        setRequestHeaders(_call);
+        setAttachments(_call);
+        try {
+            Object _resp = _call.invoke(new Object[] { message });
+
+            if (_resp instanceof RemoteException) {
+                throw ((RemoteException) _resp);
+            }
+
+            extractAttachments(_call);
+            try {
+                return ((String) _resp);
+            } catch (Exception _exception) {
+                return ((String) JavaUtils.convert(_resp, String.class));
+            }
+        } catch (AxisFault axisFaultException) {
+            throw axisFaultException;
+        }
+    }
+}

+ 8 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGateway_PortType.java

@@ -0,0 +1,8 @@
+package fi.cas.opplugin;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public abstract interface TxServiceGateway_PortType extends Remote {
+    public abstract String send(String paramString) throws RemoteException;
+}

+ 14 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGateway_Service.java

@@ -0,0 +1,14 @@
+package fi.cas.opplugin;
+import java.net.URL;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceException;
+
+public abstract interface TxServiceGateway_Service extends Service {
+    public abstract String getTxServiceGatewayPortAddress();
+
+    public abstract TxServiceGateway_PortType getTxServiceGatewayPort()
+            throws ServiceException;
+
+    public abstract TxServiceGateway_PortType getTxServiceGatewayPort(
+            URL paramURL) throws ServiceException;
+}

+ 138 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TxServiceGateway_ServiceLocator.java

@@ -0,0 +1,138 @@
+package fi.cas.opplugin;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.rmi.Remote;
+import java.util.HashSet;
+import java.util.Iterator;
+import javax.xml.namespace.QName;
+import javax.xml.rpc.ServiceException;
+import org.apache.axis.AxisFault;
+import org.apache.axis.EngineConfiguration;
+import org.apache.axis.client.Service;
+import org.apache.axis.client.Stub;
+
+public class TxServiceGateway_ServiceLocator extends Service implements
+        TxServiceGateway_Service {
+    private String TxServiceGatewayPort_address = "";
+
+    private String TxServiceGatewayPortWSDDServiceName = "TxServiceGatewayPort";
+
+    private HashSet ports = null;
+
+    public TxServiceGateway_ServiceLocator() {
+    }
+    public TxServiceGateway_ServiceLocator(String url) {
+        TxServiceGatewayPort_address = url;
+    }
+    public TxServiceGateway_ServiceLocator(EngineConfiguration config) {
+        super(config);
+    }
+
+    public TxServiceGateway_ServiceLocator(String wsdlLoc, QName sName)
+            throws ServiceException {
+        super(wsdlLoc, sName);
+    }
+
+    public String getTxServiceGatewayPortAddress() {
+        return this.TxServiceGatewayPort_address;
+    }
+
+    public String getTxServiceGatewayPortWSDDServiceName() {
+        return this.TxServiceGatewayPortWSDDServiceName;
+    }
+
+    public void setTxServiceGatewayPortWSDDServiceName(String name) {
+        this.TxServiceGatewayPortWSDDServiceName = name;
+    }
+
+    public TxServiceGateway_PortType getTxServiceGatewayPort()
+            throws ServiceException {
+        URL endpoint;
+        try {
+            endpoint = new URL(this.TxServiceGatewayPort_address);
+        } catch (MalformedURLException e) {
+            throw new ServiceException(e);
+        }
+        return getTxServiceGatewayPort(endpoint);
+    }
+
+    public TxServiceGateway_PortType getTxServiceGatewayPort(URL portAddress)
+            throws ServiceException {
+        try {
+            TxServiceGatewaySoapBindingStub _stub = new TxServiceGatewaySoapBindingStub(
+                    portAddress, this);
+            _stub.setPortName(getTxServiceGatewayPortWSDDServiceName());
+            return _stub;
+        } catch (AxisFault e) {
+        }
+        return null;
+    }
+
+    public void setTxServiceGatewayPortEndpointAddress(String address) {
+        this.TxServiceGatewayPort_address = address;
+    }
+
+    public Remote getPort(Class serviceEndpointInterface)
+            throws ServiceException {
+        try {
+            if (TxServiceGateway_PortType.class
+                    .isAssignableFrom(serviceEndpointInterface)) {
+                TxServiceGatewaySoapBindingStub _stub = new TxServiceGatewaySoapBindingStub(
+                        new URL(this.TxServiceGatewayPort_address), this);
+                _stub.setPortName(getTxServiceGatewayPortWSDDServiceName());
+                return _stub;
+            }
+        } catch (Throwable t) {
+            throw new ServiceException(t);
+        }
+        throw new ServiceException(
+                "There is no stub implementation for the interface:  "
+                        + ((serviceEndpointInterface == null) ? "null"
+                        : serviceEndpointInterface.getName()));
+    }
+
+    public Remote getPort(QName portName, Class serviceEndpointInterface)
+            throws ServiceException {
+        if (portName == null) {
+            return getPort(serviceEndpointInterface);
+        }
+        String inputPortName = portName.getLocalPart();
+        if ("TxServiceGatewayPort".equals(inputPortName)) {
+            return getTxServiceGatewayPort();
+        }
+
+        Remote _stub = getPort(serviceEndpointInterface);
+        ((Stub) _stub).setPortName(portName);
+        return _stub;
+    }
+
+    public QName getServiceName() {
+        return new QName("http://webservice.fdlk.nstc.com", "TxServiceGateway");
+    }
+
+    public Iterator getPorts() {
+        if (this.ports == null) {
+            this.ports = new HashSet();
+            this.ports.add(new QName("http://webservice.fdlk.nstc.com",
+                    "TxServiceGatewayPort"));
+        }
+        return this.ports.iterator();
+    }
+
+    public void setEndpointAddress(String portName, String address)
+            throws ServiceException {
+        if ("TxServiceGatewayPort".equals(portName)) {
+            setTxServiceGatewayPortEndpointAddress(address);
+        } else {
+            throw new ServiceException(
+                    " Cannot set Endpoint Address for Unknown Port" + portName);
+        }
+    }
+
+    public void setEndpointAddress(QName portName, String address)
+            throws ServiceException {
+        setEndpointAddress(portName.getLocalPart(), address);
+    }
+}

+ 1119 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/TypeUtils.java

@@ -0,0 +1,1119 @@
+package fi.cas.opplugin;
+
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+public class TypeUtils {
+
+
+    public static double StringToDouble(Object obj){
+        return obj==null?0.0:Double.parseDouble(obj.toString());
+    }
+
+
+
+    public static final String NODE_PATH_SPERATOR="/";
+    /**
+     * HOUR_UNIT这个常量表示单位:人时
+     *
+     * @see #HOUR_UNIT :人时
+     * @see #DAY_UNIT :人天
+     * @see #WEEK_UNIT :人周
+     * @see #MONTH_UNIT :人月
+     */
+    public final static int HOUR_UNIT = 1;
+    /**
+     * DAY_UNIT这个常量表示单位:人天
+     *
+     * @see #HOUR_UNIT :人时
+     * @see #DAY_UNIT :人天
+     * @see #WEEK_UNIT :人周
+     * @see #MONTH_UNIT :人月
+     */
+    public final static int DAY_UNIT = 2;
+    /**
+     * WEEK_UNIT这个常量表示单位:人周
+     *
+     * @see #HOUR_UNIT :人时
+     * @see #DAY_UNIT :人天
+     * @see #WEEK_UNIT :人周
+     * @see #MONTH_UNIT :人月
+     */
+    public final static int WEEK_UNIT = 3;
+    /**
+     * MONTH_UNIT这个常量表示单位:人月
+     *
+     * @see #HOUR_UNIT :人时
+     * @see #DAY_UNIT :人天
+     * @see #WEEK_UNIT :人周
+     * @see #MONTH_UNIT :人月
+     */
+    public final static int MONTH_UNIT = 4;
+
+    /**
+     * 这个常量表示分组方式:按任务分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_TASK = 1;
+    /**
+     * 这个常量表示分组方式:按资源分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_RESOURCE = 2;
+    /**
+     * 这个常量表示分组方式:按资源类型分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_RESOURCE_TYPE = 3;
+    /**
+     * 这个常量表示分组方式:按项目类型分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_PROJECT = 4;
+    /**
+     * 这个常量表示分组方式:按非项目类型分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_NON_PROJECT_TYPE = 5;
+    /**
+     * 这个常量表示分组方式:按费用类型分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_EXPENSE_TYPE = 6;
+    /**
+     * 这个常量表示分组方式:按收益类型分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_BENEFIT_TYPE = 7;
+    /**
+     * 这个常量表示分组方式:按阶段分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_PHASE = 8;
+    /**
+     * 这个常量表示分组方式:按报告分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_REPORT_BY = 9;
+    /**
+     * 这个常量表示分组方式:按一级大纲任务分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_OUTLINE = 10;// 一级大纲任务分组
+    /**
+     * 这个常量表示分组方式:按类型分组
+     *
+     * @see #BY_TASK:按任务分组
+     * @see #BY_RESOURCE:按资源分组
+     * @see #BY_RESOURCE_TYPE:按资源类型分组
+     * @see #BY_PROJECT:按项目分组
+     * @see #BY_NON_PROJECT_TYPE:按非项目类型分组
+     * @see #BY_EXPENSE_TYPE:按费用类型分组
+     * @see #BY_BENEFIT_TYPE:按收益类型分组
+     * @see #BY_PHASE:按阶段分组
+     * @see #BY_REPORT_BY:按报告分组
+     * @see #BY_OUTLINE:按一级大纲任务分组
+     * @see #BY_TYPE:按类型分组
+     */
+    public final static int BY_TYPE = 11;// 一级大纲任务分组
+    public final static int BY_PRODUCT = 12;// 工作产品
+
+    /**
+     * 这个常量表示信号灯:无信号灯
+     *
+     * @see #NONE:无信号灯
+     * @see #GREEN:绿灯
+     * @see #YELLOW:黄灯
+     * @see #RED:红灯
+     * @see #COMPLETED:已经完成
+     */
+    public final static int NONE = 1;
+    /**
+     * 这个常量表示信号灯:绿灯
+     *
+     * @see #NONE:无信号灯
+     * @see #GREEN:绿灯
+     * @see #YELLOW:黄灯
+     * @see #RED:红灯
+     * @see #COMPLETED:已经完成
+     */
+    public final static int GREEN = 2;
+    /**
+     * 这个常量表示信号灯:黄灯
+     *
+     * @see #NONE:无信号灯
+     * @see #GREEN:绿灯
+     * @see #YELLOW:黄灯
+     * @see #RED:红灯
+     * @see #COMPLETED:已经完成
+     */
+    public final static int YELLOW = 3;
+    /**
+     * 这个常量表示信号灯:红灯
+     *
+     * @see #NONE:无信号灯
+     * @see #GREEN:绿灯
+     * @see #YELLOW:黄灯
+     * @see #RED:红灯
+     * @see #COMPLETED:已经完成
+     */
+    public final static int RED = 4;
+
+    /**
+     * 这个常量表示信号灯:待我确认
+     *
+     * @see #NONE:无信号灯
+     * @see #GREEN:绿灯
+     * @see #YELLOW:黄灯
+     * @see #RED:红灯
+     * @see #PURPLE:紫色
+     * @see #LIGHT_BLUE:深蓝
+     * @see #COMPLETED:已经完成
+     */
+    public final static int PURPLE = 5;
+
+    /**
+     * 这个常量表示信号灯:被退回
+     *
+     * @see #NONE:无信号灯
+     * @see #GREEN:绿灯
+     * @see #YELLOW:黄灯
+     * @see #RED:红灯
+     * @see #COMPLETED:已经完成
+     */
+    public final static int LIGHT_BLUE = 6;
+    /**
+     * 这个常量表示信号灯:已经完成
+     *
+     * @see #NONE:无信号灯
+     * @see #GREEN:绿灯
+     * @see #YELLOW:黄灯
+     * @see #RED:红灯
+     * @see #COMPLETED:已经完成
+     */
+    public final static int COMPLETED = -1;
+    /**
+     * 这个常量是取得long数据类型的系统当前时间
+     */
+    private static long current = System.currentTimeMillis();
+
+    /**
+     * 这个获取根据时间或许系统唯一的ID
+     */
+    public static synchronized long getUniqueID() {
+        return current++;
+    }
+
+    /**
+     * 这个方法是将一个可能为<code>null</code>或者为<code>"null"</code>(忽略大小写)的
+     * <code>String</code>转换为非空的<code>String</code>.<br/>
+     * 即如果当参数<code>inString</code>为<code>null</code>时,返回值就为<code>""</code>
+     * ,如果不为空则返回inString.trim()值.
+     *
+     * @param inString
+     *            为一个可能为<code>null</code>或者为<code>"null"</code>(忽略大小写)的
+     *            <code>String</code>类型数据
+     * @return 如果当参数<code>inString</code>为<code>null</code>时,返回值就为
+     *         <code>""</code>,如果不为空则返回inString.trim()值.
+     */
+    public static String nullToString(String inString) {
+        return ((inString == null || "null".equalsIgnoreCase(inString.trim())) ? "" : inString.trim());
+    }
+
+    /**
+     * 这个方法是将一个可能为<code>null</code>或者为<code>"null"</code>(忽略大小写)的
+     * <code>String</code>数据类型<code>inString</code>, 如果转换为给定的默认值
+     * <code>defaultString</code>为<code>null</code>或者为<code>"null"</code>
+     * (忽略大小写),返回默认值,否则返回inString.trim()值.
+     *
+     * @param inString
+     *            为一个可能为<code>null</code>或者为<code>"null"</code>(忽略大小写)的
+     *            <code>String</code>类型数据.
+     * @param defaultString
+     *            为<code>String</code>类型的数据,它用于当<code>inString</code>
+     *            为空时,就将它作为返回值.
+     * @return 如果当参数<code>inString</code>为<code>null</code>时,返回值就为给定的默认值
+     *         <code>defaultString</code>,如果不为空则返回inString.trim()值.
+     */
+    public static String nullToString(String inString, String defaultString) {
+        return ((inString == null || "null".equalsIgnoreCase(inString.trim())) ? defaultString : inString.trim());
+    }
+
+    /**
+     * 这个方法是将一个可能为<code>null</code>或者为<code>"null"</code>(忽略大小写)的
+     * <code>Object</code>类型的数据转换为非空的<code>String</code>.<br/>
+     * 即如果当参数<code>inObject</code>为空时,返回值就为<code>""</code>
+     * ,如果不为空则返回inObject.toString()值.
+     *
+     * @param inObject
+     *            为一个可能为<code>null</code>或者为<code>"null"</code>(忽略大小写)的
+     *            <code>Object</code>类型数据
+     * @return 如果当参数<code>inObject</code>为空时,返回值就为<code>""</code>
+     *         ,如果不为空则返回inObject.trim()值.
+     */
+    public static String nullToString(Object inObject) {
+        return ((inObject == null || "null".equalsIgnoreCase(inObject.toString().trim())) ? "" : inObject.toString());
+    }
+
+    /**
+     * 将给定的字符串数组用分隔符加起来.<br/>
+     * 例如:<code>ss={"11","22","33"} split="," </code>其返回结果为
+     * <code>"11,22,33"</code>
+     *
+     * @param ss
+     *            为要拼的字符串数组
+     * @param split
+     *            为分隔符
+     * @return 用分隔符拼接好后的结果
+     */
+    public static String joinString(String[] ss, String split) {
+        StringBuffer sb = new StringBuffer();
+        if (ss != null && ss.length > 0) {
+            for (String s : ss) {
+                if (sb.length() > 0) {
+                    sb.append(split);
+                }
+                sb.append(s);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 将给定的<code>Object inObject</code>,如果非空或者非<code>"null"</code>
+     * ,返回UTF编码格式的inObject.toString()值,否则返回<code>""</code>.<br/>
+     *
+     * @param inObject
+     *            为一个可能为<code>null</code>或者为<code>"null"</code>(忽略大小写)的
+     *            <code>Object</code>类型数据
+     * @return inObject 的UTF编码格式的String值.
+     */
+    public static String getUTFString(Object inObject) {
+        try {
+            return ((inObject == null || "null".equalsIgnoreCase(inObject.toString().trim())) ? "" : new String(
+                    inObject.toString().getBytes("ISO8859-1")));
+        } catch (Exception e) {
+        }
+        return "";
+    }
+
+    /**
+     * 将给定的<code>Object inObject</code>,如果<code>inObject</code>
+     * 可以转换为数值,则返回转换后的int值,否则返回<code>0</code>.<br/>
+     *
+     * @param inObject
+     *            为一个<code>Object</code>类型数据
+     * @return 如果<code>inObject</code>可以转换为数值,则返回转换后的int值,否则返回int类型值
+     *         <code>0</code>.
+     */
+    public static int nullToInt(Object inObject) {
+        int iRet = 0;
+        if (inObject != null) {
+            try {
+                Double temp = new Double(inObject.toString());
+                iRet = temp.intValue();
+            } catch (Exception e) {
+                iRet = 0;
+            }
+        }
+        return iRet;
+    }
+
+
+
+    /**
+     * 将给定的<code>destStr</code>目标字符串,以新字符串<code>newStr</code>替换每一个旧字符串
+     * <code>oldStr</code>.<br/>
+     *
+     * @param destStr
+     *            为目标字符串
+     * @param oldStr
+     *            为需要被替换的旧字符串
+     * @param newStr
+     *            为要去替换的新字符串
+     * @return 返回替换好了的字符串,如果目标字符串为<code>null</code>,则返回<code>""</code>.
+     *
+     */
+    public static String strReplace(String destStr, String oldStr, String newStr) {
+        if (destStr == null){
+            return "";
+        }
+        String tmpStr = destStr;
+        int foundPos = tmpStr.indexOf(oldStr);
+        while (foundPos >= 0) {
+            tmpStr = tmpStr.substring(0, foundPos) + newStr
+                    + tmpStr.substring(foundPos + oldStr.length(), tmpStr.length());
+            foundPos = tmpStr.indexOf(oldStr, foundPos + newStr.length());
+        }
+        return tmpStr;
+    }
+
+
+
+
+
+
+
+    /**
+     * 将数据转换为html的数据格式.<br/>
+     * 例如:<code>obj="aa\r\nbb\rcc\n"</code> 替换为
+     * <code>"aa&lt;br&gt;bb&lt;br&gt;cc&lt;br&gt;"</code>
+     *
+     * @param obj
+     *            要转换的数据
+     * @return 转换完成的数据
+     */
+    public static String htmlEncoder4Print(Object obj) {
+        String sRet = htmlEncoder(obj);
+        sRet = strReplace(sRet, "\r\n", "<br>");
+        sRet = strReplace(sRet, "\r", "<br>");
+        sRet = strReplace(sRet, "\n", "<br>");
+        return sRet;
+    }
+
+    /**
+     * 将数据中的特殊字符转化为普通字符.<br/>
+     * 比如说我们可能需要将这一段代码<code>"aa&lt;br&gt;bb&lt;br&gt;cc&lt;br&gt;"</code>
+     * 显示在一个输入框内, 或者显示在页面上,我们就可以调用这个方法将那些特殊字符(&lt; &gt; &#039; &quot; )进行转换.
+     *
+     * @param obj
+     *            要转换的数据
+     * @return 转换完成的数据
+     */
+    public static String htmlEncoder(Object obj) {
+        if (obj == null){
+            return ("");
+        }
+        String value = obj.toString();
+
+        char content[] = new char[value.length()];
+        value.getChars(0, value.length(), content, 0);
+        StringBuffer result = new StringBuffer(content.length + 50);
+        for (int i = 0; i < content.length; i++) {
+            switch (content[i]) {
+                case '<':
+                    result.append("&lt;");
+                    break;
+                case '>':
+                    result.append("&gt;");
+                    break;
+                case '\'':
+                    result.append("&#039;");
+                    break;
+                // case '&':
+                // result.append("&amp;");
+                // break;
+                case '"':
+                    result.append("&quot;");
+                    break;
+                default:
+                    result.append(content[i]);
+            }
+        }
+        return (result.toString());
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+    /**
+     * 这个常量表示时间格式:yyyy-MM-dd
+     *
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIMESTAMP_FORMAT:yyyy-MM-dd HH:mm:ss
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     * @see #DEFAULT_HOUR_FORMAT:yyyy-MM-dd hha
+     */
+    public static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
+    /**
+     * 这个常量表示时间格式:yyyy-MM-dd HH:mm:ss
+     *
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIMESTAMP_FORMAT:yyyy-MM-dd HH:mm:ss
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     * @see #DEFAULT_HOUR_FORMAT:yyyy-MM-dd hha
+     */
+    public static String DEFAULT_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    /**
+     * 这个常量表示时间格式:yyyy-MM-dd HH:mm
+     *
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIMESTAMP_FORMAT:yyyy-MM-dd HH:mm:ss
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     * @see #DEFAULT_HOUR_FORMAT:yyyy-MM-dd hha
+     */
+    public static String DEFAULT_TIME_FORMAT = "yyyy-MM-dd HH:mm";
+    /**
+     * 这个常量表示时间格式:yyyy-MM-dd hha
+     *
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIMESTAMP_FORMAT:yyyy-MM-dd HH:mm:ss
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     * @see #DEFAULT_HOUR_FORMAT:yyyy-MM-dd hha
+     */
+    public static String DEFAULT_HOUR_FORMAT = "yyyy-MM-dd hha";
+
+    // public static Date getCurrentDay() {
+    // Calendar c = Calendar.getInstance();
+    // clearCalendar(c);
+    // return new java.sql.Timestamp(c.getTimeInMillis());
+    // }
+
+    // public static Date getLastSaturday() {
+    // Calendar c = Calendar.getInstance();
+    // clearCalendar(c);
+    // c.add(Calendar.DATE, -c.get(Calendar.DAY_OF_WEEK));
+    // return new java.sql.Timestamp(c.getTimeInMillis());
+    // }
+
+    /**
+     * 这个方法是设置<code>Calendar</code>的年月日三个属性,时分秒和毫秒默认为0
+     *
+     * @param c
+     *            -要设置的Calendar
+     * @param year
+     *            -参数年
+     * @param month
+     *            -参数月
+     * @param day
+     *            -参数日
+     * @return 设置好后的Calendar
+     */
+    public static Calendar setCalendar(Calendar c, int year, int month, int day) {
+        c.set(Calendar.YEAR, year);
+        c.set(Calendar.MONTH, month);
+        c.set(Calendar.DAY_OF_MONTH, day);
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 0);
+        return c;
+    }
+
+    /**
+     * 这个方法是设置<code>Calendar</code>的Time属性,时分秒和毫秒默认为0
+     *
+     * @param c
+     *            -要设置的Calendar
+     * @param date
+     *            -参数要设置的时间
+     * @return 设置好后的Calendar
+     */
+    public static Calendar setCalendar(Calendar c, Date date) {
+        c.setTime(date);
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 0);
+        return c;
+    }
+
+    /**
+     * 将日期类型转换为<code>String</code>类型
+     *
+     * @param dateValue
+     *            要转换的日期
+     * @param dateFormat
+     *            要转换的格式
+     * @return 转换后的结果
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIMESTAMP_FORMAT:yyyy-MM-dd HH:mm:ss
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     * @see #DEFAULT_HOUR_FORMAT:yyyy-MM-dd hha
+     */
+    public static String date2String(Date dateValue, String dateFormat) {
+        String sResult = "";
+        if (dateValue != null) {
+            SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
+            sResult = formatter.format(dateValue);
+        }
+        return sResult;
+    }
+
+    /**
+     * 将Date数据转换成默认日期格式或者默认时间格式的字符串
+     *
+     * @param dateValue
+     *            要转换的Date
+     * @param dateFormat
+     *            如果为0则为默认时间格式(yyyy-MM-dd HH:mm),否则为默认日期(yyyy-MM-dd)
+     * @return 转换后的字符串
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     */
+    public static String date2String(Date dateValue, int dateFormat) {
+        String f = DEFAULT_DATE_FORMAT;
+        if (dateFormat == 0) {
+            f = DEFAULT_TIME_FORMAT;
+        }
+        return date2String(dateValue, f);
+    }
+
+    /**
+     * 将Date类型的数据转换为默认时间格式(yyyy-MM-dd HH:mm)的字符串
+     *
+     * @param dateValue
+     *            要转换的Date
+     * @return 转换后的字符串
+     */
+    public static String date2String(Date dateValue) {
+        return date2String(dateValue, DEFAULT_TIME_FORMAT);
+    }
+
+    /**
+     * 这个方法将给定的字符串转换为默认的日期类型(yyyy-MM-dd)
+     *
+     * @param sDate
+     *            要转换成日期的字符串
+     * @return 转换完成的字符串
+     * @throws ParseException
+     *             字符串不能转换成日期格式时,出现转换异常
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     */
+    public static Date string2Date(String sDate) throws ParseException {
+        return string2Date(sDate, DEFAULT_DATE_FORMAT);
+    }
+
+    /**
+     * 这个方法将给定的字符串转换为指定的日期类型
+     *
+     * @param sDate
+     *            要转换成日期的字符串
+     * @param dateFormat
+     *            目标格式
+     * @return 转换后的日期
+     * @throws ParseException
+     *             转换时出现的异常,很可能是sDate格式不正确
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIMESTAMP_FORMAT:yyyy-MM-dd HH:mm:ss
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     * @see #DEFAULT_HOUR_FORMAT:yyyy-MM-dd hha
+     */
+    public static Date string2Date(String sDate, String dateFormat) throws ParseException {
+        Date tmp = null;
+        if (sDate != null && !"".equals(sDate)) {
+            SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
+            formatter.setLenient(true);
+            tmp = formatter.parse(sDate);
+        }
+        return tmp;
+    }
+
+    /**
+     * 将String数据转换成默认日期格式或者默认时间格式的时间或者日期格式
+     *
+     * @param sDate
+     *            要转换的String
+     * @param dateFormat
+     *            如果为0则为默认时间格式(yyyy-MM-dd HH:mm),否则为默认日期(yyyy-MM-dd)
+     * @return 转换后的日期
+     * @see #DEFAULT_DATE_FORMAT:yyyy-MM-dd
+     * @see #DEFAULT_TIME_FORMAT:yyyy-MM-dd HH:mm
+     */
+    public static Date string2Date(String sDate, int dateFormat) throws ParseException {
+        String f = DEFAULT_DATE_FORMAT;
+        if (dateFormat == 0) {
+            f = DEFAULT_TIME_FORMAT;
+        }
+        return string2Date(sDate, f);
+    }
+
+    /**
+     * 将Sting转换成int,如果s的值为null,"null",""则返回默认值0
+     *
+     * @param s
+     *            要转换的String
+     * @return 转换完成的int结果
+     */
+    public static int getIntFromString(String s) {
+        int iRet = 0;
+        if (s != null && !"".equals(s) && !"null".equals(s)) {
+            iRet = Integer.parseInt(s);
+        }
+        return iRet;
+    }
+
+    /**
+     * 将Sting转换成long,如果s的值为null,""则返回默认值0
+     *
+     * @param s
+     *            要转换的String
+     * @return 转换完成的long结果
+     */
+    public static long getLongFromString(String s) {
+        long iRet = 0;
+        if (s != null && !"".equals(s)) {
+            iRet = Long.parseLong(s);
+        }
+        return iRet;
+    }
+
+    /**
+     * 将Sting转换成Integer,如果s的值为null,"null",""则返回null
+     *
+     * @param s
+     *            要转换的String
+     * @return 转换完成的Integer结果
+     */
+    public static Integer getInteger(String s) {
+        if (s == null || "".equals(s)) {
+            return null;
+        }
+        return new Integer(s);
+    }
+
+    /**
+     * 默认的Decimal格式,保留两位小数
+     */
+    private static String FORMAT_PATTERN_DEFAULT = "#0.00";
+
+    /**
+     * 获取指定格式的数值,并以String数据类型返回,如果input是null或者"",返回""
+     *
+     * @param input
+     *            要转换的字符串
+     * @param pattern
+     *            要转换的格式
+     * @return 返回指定格式的String类型的数值(四舍五入)
+     */
+    public static String formatNumber(String input, String pattern) {
+        if (input == null ||"" .equals(input.trim())) {
+            return "";
+        }
+        DecimalFormat format = new DecimalFormat();
+        format.applyLocalizedPattern(pattern);
+        double d = Double.parseDouble(input);
+        return format.format(d);
+    }
+
+
+
+    /**
+     * 获取默认格式的String类型的数值
+     *
+     * @param input
+     *            要转换的String
+     * @return 转换后的数据(四舍五入)
+     */
+    public static String formatNumber(String input) {
+        return formatNumber(input, FORMAT_PATTERN_DEFAULT);
+    }
+
+
+
+    /**
+     * Format given double value to a string with specific precision. Known bug:
+     * If the significant digit count of input double value is greater than 17,
+     * the formatted value will be incorrect For example: 11111111111111111.0000
+     * will be formated to 11111111111111112.0, Double.toString(double) method
+     * will return 1.1111111111111112E16, this is the cause. Note: Don't call
+     * String.valueOf(double) to convert it to a string, which will format the
+     * number as computer science notation format when the value is larger than
+     * 10^7.
+     *
+     * @param d
+     * @return
+     */
+    public static String formatNumber(double d, int scale) {
+        DecimalFormat df = new DecimalFormat(FORMAT_PATTERN_DEFAULT);
+        df.setMaximumFractionDigits(scale);
+        return df.format(d);
+    }
+
+    /**
+     * Format given double value to a string with default precision of 2.
+     *
+     * @param d
+     * @return
+     */
+    public static String formatNumber(double d) {
+        DecimalFormat df = new DecimalFormat(FORMAT_PATTERN_DEFAULT);
+        df.setMaximumFractionDigits(2);
+        return df.format(d);
+    }
+
+    /**
+     * 默认的DECIMAL的数据格式
+     *
+     */
+    public static String DEFAULT_DECIMAL_FORMAT = "##############0.00";
+    /**
+     * 默认的WORKTIME的数据格式
+     *
+     */
+    public static String DEFAULT_WORKTIME_FORMAT = "##############0.0";
+    /**
+     * 默认的PERCENT的数据格式
+     *
+     */
+    public static String DEFAULT_PERCENT_FORMAT = "##############0";
+
+    /**
+     * percent的DecimalFormat格式
+     *
+     * @see decimalFormatter "##############0.00"
+     * @see workTimeFormatter "##############0.0"
+     * @see percentFormatter "##############0"
+     */
+
+    /**
+     * 将给定的double类型的数据,根据默认DecimalFormat格式转化成对应的String类型数值
+     *
+     * @param d
+     *            要转换的double类型数值
+     * @return 转换后的String数值
+     */
+    public static String double2String(double d) {
+        DecimalFormat decimalFormatter = new DecimalFormat(DEFAULT_DECIMAL_FORMAT);
+        return decimalFormatter.format(d).toString();
+    }
+
+    /**
+     * 将给定的double类型的数据,根据percentFormatter格式转化成对应的String类型数值
+     *
+     * @param d
+     *            要转换的double类型数值
+     * @return 转换后的String数值
+     */
+    public static String percent2String(double d) {
+        DecimalFormat percentFormatter = new DecimalFormat(DEFAULT_WORKTIME_FORMAT);
+        return percentFormatter.format(d).toString();
+    }
+
+    /**
+     * 将给定的double类型的数据,根据workTimeFormatter格式转化成对应的String类型数值
+     *
+     * @param d
+     *            要转换的double类型数值
+     * @return 转换后的String数值
+     * @see  "##############0.0"
+     */
+    public static String worktime2String(double d) {
+        DecimalFormat workTimeFormatter = new DecimalFormat(DEFAULT_WORKTIME_FORMAT);
+        return workTimeFormatter.format(d).toString();
+    }
+
+    /**
+     * 将给定的double类型的数据, 根据workTimeFormatter格式转化成对应的String类型数值,
+     * 如果sDouble为""或者为null,则返回默认值0.0
+     *
+     *            要转换的double类型数值
+     * @return 转换后的double数值
+     * @see  "##############0.0"
+     */
+    public static double string2Worktime(String sDouble) {
+        try {
+            if (sDouble != null && !"".equals(sDouble)) {
+                DecimalFormat workTimeFormatter = new DecimalFormat(DEFAULT_WORKTIME_FORMAT);
+                return workTimeFormatter.parse(sDouble).doubleValue();
+            }
+        } catch (Exception e) {
+        }
+        return 0.0;
+    }
+
+    /**
+     * 将给定的double类型的数据, 根据decimalFormatter格式转化成对应的String类型数值,
+     * 如果sDouble为""或者为null,则返回默认值0.00
+     *
+     *            要转换的double类型数值
+     * @return 转换后的double数值
+     * @see  "##############0.00"
+     */
+    public static double string2Double(String sDouble) {
+        try {
+            if (sDouble != null && !"".equals(sDouble)) {
+                DecimalFormat decimalFormatter = new DecimalFormat(DEFAULT_DECIMAL_FORMAT);
+                return decimalFormatter.parse(sDouble).doubleValue();
+            }
+        } catch (Exception e) {
+        }
+        return 0.00;
+    }
+
+    /**
+     * 需要转移
+     *
+     * @param s
+     * @return
+     * @throws Exception
+     */
+    public static String getLimitText(int limit, Object s) throws Exception {
+        String result = "";
+        String value = TypeUtils.nullToString(s);
+        if (limit == 0 || value.length() <= limit) {
+            result = value;
+        } else {
+            result = value.substring(0, limit) + "...";
+        }
+        return result;
+    }
+
+    /**
+     * 将Java的字符串转换成可执行的Javascript代码
+     *
+     * @param s
+     *            要转换的Java代码
+     * @return 转换后生成可执行的Javascript代码
+     */
+    public static String javaString2JavascriptString(String s) {
+        if (s == null) {
+            return null;
+        }
+        s = s.replace("\\", "\\\\");
+        s = s.replace("'", "\\'");
+        s = s.replace("\"", "\\\"");
+        return s;
+    }
+
+
+
+
+
+
+
+    /**
+     * 把double四舍五入到小数点后n位
+     *
+     * @param value
+     *            要转换的double类型的数值
+     * @param afterPoint
+     *            保留多少位小数点
+     * @return 转换后的值
+     */
+    public static double round(double value, int afterPoint) {
+        BigDecimal bd = new BigDecimal(value);
+        BigDecimal bd1 = bd.setScale(afterPoint, BigDecimal.ROUND_HALF_UP);
+        return bd1.doubleValue();
+    }
+
+    /**
+     * 把double四舍五入到小数点后n位,返回String
+     *
+     * @param value
+     *            要转换的double类型的数值
+     * @param afterPoint
+     *            保留多少位小数点
+     * @return 转换后的String类型的数值
+     */
+    public static String roundToString(double value, int afterPoint) {
+        BigDecimal bd = new BigDecimal(value);
+        BigDecimal bd1 = bd.setScale(afterPoint, BigDecimal.ROUND_HALF_UP);
+        NumberFormat formatter = NumberFormat.getNumberInstance();
+        formatter.setMinimumFractionDigits(afterPoint);
+        formatter.setMaximumFractionDigits(afterPoint);
+        String rtnValue = formatter.format(bd1.doubleValue());
+        return rtnValue;
+    }
+
+    /**
+     * 省略年,按MM-dd方式显示
+     *
+     * @param date
+     *            要处理的日期
+     * @return 处理后的日期(MM-dd)格式
+     */
+    public static String noShowYear(Date date) {
+        SimpleDateFormat format = new SimpleDateFormat("MM-dd");
+        return format.format(date);
+    }
+
+
+
+
+    /**
+     * 根据int类型的月份,获取资源文件中的月份key值
+     *
+     * @param month
+     *            int类型的月份值
+     * @return 对应资源文件中的月份key值
+     */
+    private static String getMonthKey(int month) {
+        String key = null;
+        switch (month) {
+            case 0:
+                key = "JAN";
+                break;
+            case 1:
+                key = "FEB";
+                break;
+            case 2:
+                key = "MAR";
+                break;
+            case 3:
+                key = "APR";
+                break;
+            case 4:
+                key = "MAY";
+                break;
+            case 5:
+                key = "JUN";
+                break;
+            case 6:
+                key = "JUL";
+                break;
+            case 7:
+                key = "AUG";
+                break;
+            case 8:
+                key = "SEP";
+                break;
+            case 9:
+                key = "OCT";
+                break;
+            case 10:
+                key = "NOV";
+                break;
+            case 11:
+                key = "DEC";
+                break;
+        }
+        return key;
+    }
+
+    /**
+     * 通过季度,得到以逗号分隔的月份字符串 例: " (0,1,2)"," (3,4,5)"," (6,7,8)"," (9,10,11)".
+     *
+     * @param quarter
+     *            int类型的季度值,可取1,2,3,4这四个值,表示一,二,三,四季度
+     * @return 返回月份的字符串.
+     */
+    public static String getInMonthStringByQuarter(int quarter) {
+        switch (quarter) {
+            case (1):
+                return " (0,1,2)";
+            case (2):
+                return " (3,4,5)";
+            case (3):
+                return " (6,7,8)";
+            case (4):
+                return " (9,10,11)";
+        }
+        return null;
+    }
+
+}

+ 148 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/opplugin/Utils.java

@@ -0,0 +1,148 @@
+package fi.cas.opplugin;
+import com.google.gson.Gson;
+import com.kingdee.bos.json.Kson;
+
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+
+
+public class Utils {
+
+    public static BigDecimal zero = new BigDecimal("0.00");
+    /**
+     * 日期格式化
+     * @param date
+     * @param format
+     * @return
+     */
+    public static Date formatDate(String date, String format) {
+        SimpleDateFormat dt = new SimpleDateFormat(format);
+        try {
+            return dt.parse(date);
+        } catch (ParseException e) {
+        }
+        return null;
+    }
+
+    /**
+     * 日期格式化
+     * @param date
+     * @param format
+     * @return
+     */
+    public static String getData(Date date, String format) {
+        SimpleDateFormat dt = new SimpleDateFormat(format);
+        return dt.format(date);
+    }
+
+    public static BigDecimal toBigDecimal(Object obj)
+    {
+        if(obj == null)
+            return BigDecimal.ZERO;
+        if(obj instanceof BigDecimal)
+            return (BigDecimal)obj;
+        if(obj instanceof Integer)
+            return new BigDecimal(((Integer)obj).toString());
+        if(obj instanceof Long)
+            return new BigDecimal(((Long)obj).toString());
+        if(obj instanceof Double)
+            return new BigDecimal(((Double)obj).doubleValue());
+        if(obj.toString() == null)
+            return BigDecimal.ZERO;
+        String str = obj.toString().trim();
+        if(str.toLowerCase().indexOf("e") > -1)
+            try
+            {
+                return new BigDecimal(str);
+            }
+            catch(NumberFormatException e)
+            {
+                return BigDecimal.ZERO;
+            }
+        if(str.matches("^[+-]?\\d+[\\.\\d]?\\d*+$"))
+            return new BigDecimal(str);
+        else
+            return BigDecimal.ZERO;
+    }
+
+    // 加
+    public static BigDecimal add(Object a, Object b,int scale) {
+
+        if (a == null)
+            a = zero;
+
+        if (b == null)
+            b = zero;
+
+        if (a instanceof BigDecimal && b instanceof BigDecimal) {
+            BigDecimal aVal = (BigDecimal) a;
+            BigDecimal bVal = (BigDecimal) b;
+            return aVal.add(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
+        }
+
+        return zero;
+    }
+
+    // 减
+    public static BigDecimal sub(Object a, Object b,int scale) {
+
+        if (a == null)
+            a = zero;
+
+        if (b == null)
+            b = zero;
+
+        if (a instanceof BigDecimal && b instanceof BigDecimal) {
+            BigDecimal aVal = (BigDecimal) a;
+            BigDecimal bVal = (BigDecimal) b;
+            return aVal.subtract(bVal).setScale(scale, BigDecimal.ROUND_HALF_UP);
+        }
+
+        return zero;
+    }
+
+
+
+    public static String convertObjectToJson(Object object)  {
+        if (object == null) {
+            return "\"\"";
+        }
+        String result = null;
+        try {
+            result = Kson.getGson().toJson(object);
+        } finally {
+        }
+
+        if (result == null) {
+            return "\"\"";
+        }
+
+        if ((object instanceof String) && (result.startsWith("\""))
+                && (result.endsWith("\""))) {
+            result = result.substring(1, result.length() - 1);
+        }
+
+        result = processJsonResult(result);
+
+        return result;
+    }
+    public static String processJsonResult(String result) {
+        if (result == null) {
+            return null;
+        }
+
+        result = result.replace("${quote_2312415321232}", "\"");
+        result = result.replace("\"${leftbracket_2312415321232}", "{");
+        result = result.replace("${leftbracket_2312415321232}", "{");
+        result = result.replace("${rightbracket_2312415321232}\"", "}");
+        result = result.replace("${rightbracket_2312415321232}", "}");
+        return result;
+    }
+
+
+}

+ 137 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/task/AgentpaybillQueryStatusTast.java

@@ -0,0 +1,137 @@
+package fi.cas.task;
+
+import com.alibaba.druid.support.logging.Log;
+import com.alibaba.druid.support.logging.LogFactory;
+import fi.cas.opplugin.PayBillToolUtil;
+import fi.cas.opplugin.TypeUtils;
+import fi.cas.opplugin.Utils;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+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.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class AgentpaybillQueryStatusTast extends AbstractTask {
+    private static final Log log = LogFactory.getLog(AgentpaybillQueryStatusTast.class);
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        //获取要查询的数据。状态为已审批,支付状态为支付中,或支付失败。理论上只需要查支付中
+        QFilter filter = new QFilter("billstatus", QCP.equals, "C");
+        Set<String> paystatusSet = new HashSet<>();
+        paystatusSet.add("2");
+        paystatusSet.add("6");
+        filter.and("nckd_paystatus", QCP.in, "2");
+        filter.and("nckd_fkcs", QCP.large_than, 0);
+        Map<Object, DynamicObject> payinfos  = BusinessDataServiceHelper.loadFromCache("cas_agentpaybill", new QFilter[] {filter});
+        DynamicObject jkpzxx = BusinessDataServiceHelper.loadSingle("nckd_jkpzxx",new QFilter[]{new QFilter("number","=","paytoJHX")});
+        String url =  jkpzxx.getString("nckd_servername");
+
+
+        for (DynamicObject dataEntity : payinfos.values()) {
+            //调用接口查询付款状态
+            JSONObject param = new JSONObject();
+            PayBillToolUtil.headJson(param);
+            JSONObject data = new JSONObject();
+            data.put("ERP_INS_ID",dataEntity.getPkValue()+"-"+dataEntity.get("nckd_bbh"));
+            param.put("data",data);
+            param.put("txDateTime",Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("batchNo",TypeUtils.nullToString(dataEntity.get("billno"))+"-"+TypeUtils.nullToString(dataEntity.get("nckd_bbh"))+"-"+Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("code","NSTC-Q001");
+
+            String bodyjson=param.toString();
+            String billNum = dataEntity.getString("billno");
+            log.info("单据号:"+billNum+"传入参数"+param.toString());
+            JSONObject cbsReturnJson =PayBillToolUtil.JHXServiceQuery(url,bodyjson);//待补充,超时返回参数待修改,整体待重构
+            log.info("单据号:"+billNum+"返回参数"+cbsReturnJson.toString());
+            if(cbsReturnJson==null||cbsReturnJson.get("data")==null){
+            }else{
+                String errcode = cbsReturnJson.get("resultCode")+"";
+                JSONObject bodyinfo = cbsReturnJson.getJSONObject("data");
+                if(bodyinfo!=null){
+                    boolean isupdate = false;
+                    if ("000000".equals(errcode)) {//已查询到,不代表支付成功
+                        String zfstatus = bodyinfo.getString("RET_CODE");//0:付款成功  -1:付款失败 -2:流程中 -3:驳回 -4:部分成功
+                        String errormsg =bodyinfo.getString("ERROR_MSG");
+                        if("-2".equals(zfstatus)){//流程中
+                            //判断原因是否有变化
+                           String sbyy =  dataEntity.getString("nckd_sbyy");
+                           if(errormsg == null || "".equals(errormsg)){//空不更新
+
+                           }else if(errormsg.equals(sbyy)){//相等不更新
+
+                           }else{
+                               dataEntity.set("nckd_sbyy",errormsg);//错误信息更新
+                               isupdate = true;
+                           }
+
+                        }else if("0".equals(zfstatus)){//成功
+                            dataEntity.set("nckd_paystatus",3);
+                            dataEntity.set("nckd_sbyy","支付成功");//错误信息更新
+                            //分录信息
+                            DynamicObjectCollection coll = dataEntity.getDynamicObjectCollection("entry");
+                            for (int i = 0; i <coll.size() ; i++) {
+                                coll.get(i).set("e_issuccess",true);//分录是否成功
+                                coll.get(i).set("bankreturnmsg","成功");//返回信息
+                            }
+                            isupdate = true;
+                        }else if("-1".equals(zfstatus)){//失败
+                            dataEntity.set("nckd_paystatus",6);//支付失败
+                            dataEntity.set("nckd_sbyy",errormsg);//错误信息更新
+                            updateEntrys(dataEntity,bodyinfo);
+                            isupdate = true;
+                        }else if("-3".equals(zfstatus)){//驳回
+                            dataEntity.set("nckd_paystatus",5);//驳回
+                            dataEntity.set("nckd_sbyy",errormsg);//错误信息更新
+                            updateEntrys(dataEntity,bodyinfo);
+                            isupdate = true;
+                        }else if("-4".equals(zfstatus)){//部分成功
+                            dataEntity.set("nckd_paystatus",7);//部分成功
+                            dataEntity.set("nckd_sbyy",errormsg);//错误信息更新
+                            updateEntrys(dataEntity,bodyinfo);
+                            isupdate = true;
+                        }
+                        if(isupdate){
+                            SaveServiceHelper.update(new DynamicObject[]{dataEntity});
+                            PayBillToolUtil.saveupdatelog(dataEntity,bodyjson,cbsReturnJson.toString());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    //更新分录
+    public void updateEntrys(DynamicObject dataEntity,JSONObject bodyinfo){
+        DynamicObjectCollection coll = dataEntity.getDynamicObjectCollection("entry");
+        JSONArray ITEM_LIST =  bodyinfo.getJSONArray("ITEM_LIST");
+        for (int i = 0; i < ITEM_LIST.length(); i++) {
+            JSONObject iteminfo =(JSONObject)ITEM_LIST.get(i);
+            String itempk = iteminfo.get("ERP_PVT_ID")+"";
+            String error_msg = iteminfo.get("ERROR_MSG")+"";
+            String result_code = iteminfo.get("RESULT_CODE")+"";
+            for (int j = 0; j <coll.size() ; j++) {
+                String itempkvalue =  coll.get(j).getPkValue()+"";
+                if(itempk.equals(itempkvalue)){
+                    if("0".equals(result_code)){
+                        coll.get(j).set("e_issuccess",true);
+                        coll.get(j).set("bankreturnmsg","成功");//返回信息
+                    }else{
+                        coll.get(j).set("e_issuccess",false);
+                        coll.get(j).set("bankreturnmsg",error_msg);//返回信息
+                    }
+                }
+            }
+        }
+    }
+}

+ 95 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/task/PayQueryStatusTast.java

@@ -0,0 +1,95 @@
+package fi.cas.task;
+
+import com.alibaba.druid.support.logging.Log;
+import com.alibaba.druid.support.logging.LogFactory;
+import fi.cas.opplugin.*;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+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.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import org.json.JSONObject;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class PayQueryStatusTast extends AbstractTask {
+    private static final Log log = LogFactory.getLog(PayQueryStatusTast.class);
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        //获取要查询的数据。状态为已审批,支付状态为支付中,或支付失败。理论上只需要查支付中
+        QFilter filter = new QFilter("billstatus", QCP.equals, "C");
+        Set<String> paystatusSet = new HashSet<>();
+        paystatusSet.add("2");
+        paystatusSet.add("6");
+        filter.and("nckd_paystatus", QCP.in, "2");
+        filter.and("nckd_fkcs", QCP.large_than, 0);
+        DynamicObject[] payinfos = BusinessDataServiceHelper.load("cas_paybill","billno,billstatus,nckd_paystatus,nckd_sbyy,nckd_fqqdrq,nckd_fkcs,nckd_bbh", new QFilter[] {filter});
+        DynamicObject jkpzxx = BusinessDataServiceHelper.loadSingle("nckd_jkpzxx",new QFilter[]{new QFilter("number","=","paytoJHX")});
+        String url =  jkpzxx.getString("nckd_servername");
+
+
+        for (DynamicObject dataEntity : payinfos) {
+            //调用接口查询付款状态
+            JSONObject param = new JSONObject();
+            PayBillToolUtil.headJson(param);
+            JSONObject data = new JSONObject();
+            data.put("ERP_INS_ID",dataEntity.getPkValue()+"-"+dataEntity.get("nckd_bbh"));
+            param.put("data",data);
+            param.put("txDateTime",Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("batchNo",TypeUtils.nullToString(dataEntity.get("billno"))+"-"+TypeUtils.nullToString(dataEntity.get("nckd_bbh"))+"-"+Utils.getData(new Date(), "yyyyMMddHHmmss"));
+            param.put("code","NSTC-Q001");
+
+            String bodyjson=param.toString();
+            String billNum = dataEntity.getString("billno");
+            log.info("单据号:"+billNum+"传入参数"+param.toString());
+            JSONObject cbsReturnJson =PayBillToolUtil.JHXServiceQuery(url,bodyjson);//待补充,超时返回参数待修改,整体待重构
+            log.info("单据号:"+billNum+"返回参数"+cbsReturnJson.toString());
+            if(cbsReturnJson==null||cbsReturnJson.get("data")==null){
+            }else{
+                String errcode = cbsReturnJson.get("resultCode")+"";
+                JSONObject bodyinfo = cbsReturnJson.getJSONObject("data");
+                if(bodyinfo!=null){
+                    boolean isupdate = false;
+                    if ("000000".equals(errcode)) {//已查询到,不代表支付成功
+                        String zfstatus = bodyinfo.getString("RET_CODE");//0:付款成功  1:付款失败 2:流程中 3:驳回 4:部分成功
+                        String errormsg =bodyinfo.getString("ERROR_MSG");
+                        if("-2".equals(zfstatus)){//流程中
+                            //判断原因是否有变化
+                           String sbyy =  dataEntity.getString("nckd_sbyy");
+                            if(errormsg == null || "".equals(errormsg)){//空不更新
+
+                            }else if(errormsg.equals(sbyy)){//相等不更新
+
+                            }else{
+                                dataEntity.set("nckd_sbyy",errormsg);//错误信息更新
+                                isupdate = true;
+                            }
+                        }else if("0".equals(zfstatus)){//成功
+                            dataEntity.set("nckd_paystatus",3);
+                            dataEntity.set("nckd_sbyy","支付成功");//错误信息更新
+                            isupdate = true;
+                        }else if("-1".equals(zfstatus)){//失败
+                            dataEntity.set("nckd_paystatus",6);//支付失败
+                            dataEntity.set("nckd_sbyy",errormsg);//错误信息更新
+                            isupdate = true;
+                        }else if("-3".equals(zfstatus)){//驳回
+                            dataEntity.set("nckd_paystatus",5);//驳回
+                            dataEntity.set("nckd_sbyy",errormsg);//错误信息更新
+                            isupdate = true;
+                        }
+                        if(isupdate){
+                            SaveServiceHelper.update(new DynamicObject[]{dataEntity});
+                            PayBillToolUtil.saveupdatelog(dataEntity,bodyjson,cbsReturnJson.toString());
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 39 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/cas/task/PayUpadteStatusTask.java

@@ -0,0 +1,39 @@
+package fi.cas.task;
+
+import com.alibaba.druid.support.logging.Log;
+import com.alibaba.druid.support.logging.LogFactory;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+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.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+
+import java.util.Map;
+
+public class PayUpadteStatusTask  extends AbstractTask {
+    private static final Log log = LogFactory.getLog(PayUpadteStatusTask.class);
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        //获取要查询的数据。状态为已审批,支付状态为支付成功。
+        QFilter filter = new QFilter("billstatus", QCP.equals, "C");
+        filter.and("nckd_paystatus", QCP.equals, 3);
+        filter.and("nckd_fkcs", QCP.large_equals, 0);
+        DynamicObject[] payinfos = BusinessDataServiceHelper.load("cas_paybill","billno", new QFilter[] {filter});
+        if(payinfos.length>0){
+            for (int i = 0; i <payinfos.length ; i++) {
+                DynamicObject payinfo = BusinessDataServiceHelper.loadSingle(payinfos[i].getPkValue(),"cas_paybill");
+                try {
+                    OperationServiceHelper.executeOperate("pay","cas_paybill",new DynamicObject[]{payinfo}, OperateOption.create());
+                }catch (Exception e){
+                    log.info("付款变更状态报错:"+payinfo.get("billno"));
+                }
+            }
+
+
+        }
+    }
+}

+ 33 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/em/opplugin/AgentpaybillOpPlugin.java

@@ -0,0 +1,33 @@
+package fi.em.opplugin;
+
+import fi.cas.opplugin.PayBillToolUtil;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeforeOperationArgs;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+
+/**
+ * @description:代发处理单,传给九恒星
+ */
+public class AgentpaybillOpPlugin extends AbstractOperationServicePlugIn {
+
+
+
+
+    @Override
+    public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
+        DynamicObject[] dynamicObjects = e.getDataEntities();
+        String operationKey = e.getOperationKey();
+        //关闭付款则将支付状态更改为支付关闭状态
+        if ("sendtojhx".equals(operationKey)){
+            String errMsg = "";
+            errMsg =  PayBillToolUtil.agentpayBillForCBSSync(dynamicObjects);
+            if(!errMsg.isEmpty()) {
+                //将成功错误信息返回到前端
+                e.setCancelMessage(errMsg);
+                e.setCancel(true);
+            }
+        }
+    }
+
+}

+ 56 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/AccountSynReturnModel.java

@@ -0,0 +1,56 @@
+package fi.er.webService;
+
+import kd.bos.openapi.common.custom.annotation.ApiParam;
+
+import java.io.Serializable;
+
+/**
+ * 银行账户同步 自定义API 返回参数 class
+ * @author @author ww
+ */
+public class AccountSynReturnModel implements Serializable {
+
+    @ApiParam(value = "银行账号", position = 1)
+    String number;
+
+    @ApiParam(value = "账户名称", position = 2)
+    String name;
+
+    @ApiParam(value = "错误代码", position = 3)
+    String code;
+
+    @ApiParam(value = "错误信息", position = 4)
+    String message;
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 55 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/BankSynReturnModel.java

@@ -0,0 +1,55 @@
+package fi.er.webService;
+
+import kd.bos.openapi.common.custom.annotation.ApiParam;
+
+import java.io.Serializable;
+/**
+ * 行名行号同步 自定义API 返回参数 class
+ * @author @author ww
+ */
+public class BankSynReturnModel implements Serializable {
+
+    @ApiParam(value = "行号", position = 1)
+    String number;
+
+    @ApiParam(value = "行名称", position = 2)
+    String name;
+
+    @ApiParam(value = "错误代码", position = 3)
+    String code;
+
+    @ApiParam(value = "错误信息", position = 4)
+    String message;
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 26 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/CustomApiResultForMy.java

@@ -0,0 +1,26 @@
+package fi.er.webService;
+
+import kd.bos.openapi.common.result.CustomApiResult;
+
+/**
+ * @author @author ww
+ */
+public class CustomApiResultForMy<T> extends CustomApiResult {
+
+
+    public static <T> CustomApiResultForMy<T> success2(T data) {
+        CustomApiResultForMy<T> result = new CustomApiResultForMy();
+        result.setStatus(true);
+        result.setData(data);
+        return result;
+    }
+
+    public static <T> CustomApiResultForMy<T> fail(T data) {
+        CustomApiResultForMy<T> result = new CustomApiResultForMy();
+        result.setData(data);
+        result.setStatus(false);
+        result.setErrorCode("500");
+        result.setMessage("失败");
+        return result;
+    }
+}

+ 274 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/SaveAccountApi.java

@@ -0,0 +1,274 @@
+package fi.er.webService;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import fi.cas.opplugin.TypeUtils;
+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.entity.operate.result.OperationResult;
+import kd.bos.openapi.common.custom.annotation.ApiController;
+import kd.bos.openapi.common.custom.annotation.ApiMapping;
+import kd.bos.openapi.common.custom.annotation.ApiParam;
+import kd.bos.openapi.common.custom.annotation.ApiPostMapping;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author zf
+ * 接收九恒星银行账户,并生成金融机构
+ */
+@ApiController(value = "account", desc = "自定义API 银行账户同步")
+@ApiMapping(value = "SaveAccountApi")
+public class SaveAccountApi implements Serializable {
+    protected static final Long DEFAULT_ORG_ID = 100000L;
+
+    /**
+     * @description 行名行号同步接口
+     * @param data
+     * @return CustomApiResult
+     */
+    @ApiPostMapping(value = "/save", desc = "同步银行账户")
+    public CustomApiResultForMy<List<AccountSynReturnModel>> saveAccount (@ApiParam(value = "九恒星银行账户") JSONArray data) {
+        StringBuilder resultString = new StringBuilder();
+        List<AccountSynReturnModel> returnList = new ArrayList<>();
+        Boolean result = true;
+
+        DynamicObject rmbinfo = BusinessDataServiceHelper.loadSingleFromCache(1L,"bd_currency");
+        //默认的国家
+        DynamicObject defaultgj = BusinessDataServiceHelper.loadSingleFromCache("1000001", "bd_country");
+
+        RequestContext rc = RequestContext.get();
+        DynamicObject user = BusinessDataServiceHelper.loadSingleFromCache(rc.getCurrUserId(), "bos_user");
+        DynamicObject defaultOrg = BusinessDataServiceHelper.loadSingle(DEFAULT_ORG_ID, "bos_org");
+        //默认金融机构类别
+        DynamicObject defaultjrjgtypeinfo = BusinessDataServiceHelper.loadSingleFromCache(615763944224700416L,"bd_finorgtype");
+
+        //默认银行类别
+        QFilter typecodeFilter = new QFilter("type_code.number","=","BC-9999");
+        DynamicObject defaulttypecodeinfo =BusinessDataServiceHelper.loadSingleFromCache("bd_bankcgsetting",new QFilter[]{typecodeFilter});
+
+
+        //循环传入的数据
+        for (int i = 0; i < data.size(); i++) {
+            JSONObject eobject = data.getJSONObject(i);
+            AccountSynReturnModel contractSynReturnModel = syncAccount(eobject,rmbinfo,defaultjrjgtypeinfo,defaultgj,defaulttypecodeinfo,defaultOrg,user);
+            if ("500".equals(contractSynReturnModel.getCode())){
+                result = false;
+            }
+            returnList.add(contractSynReturnModel);
+        }
+        return result == true
+                ? CustomApiResultForMy.success2(returnList)
+                : CustomApiResultForMy.fail(returnList);
+    }
+
+
+    /**
+     * @description 保存行名行号
+     * @param jsonObject
+     */
+    private AccountSynReturnModel syncAccount(JSONObject jsonObject,DynamicObject rmbinfo, DynamicObject defaultjrjgtypeinfo,DynamicObject defaultgj,DynamicObject defaulttypecodeinfo, DynamicObject defaultOrg,DynamicObject user) {
+        AccountSynReturnModel contractSynReturnModel = new AccountSynReturnModel();
+        Date curDate = new Date();
+        String number = jsonObject.get("accountnumber")+"";
+        String name = jsonObject.get("accountname")+"";
+        if ("".equals(number)||"".equals(name)) {
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("账户名和银行账号不能为空");
+            return contractSynReturnModel;
+        }
+
+        contractSynReturnModel.setNumber(number);
+        contractSynReturnModel.setName(name);
+
+        //查询是否存在,存在则返回。不存在更新
+        QFilter qFilter = new QFilter("number","=",number);
+        DynamicObject accountinfo =  BusinessDataServiceHelper.loadSingle("bd_accountbanks",new QFilter[]{qFilter});
+        if(accountinfo!=null){
+            //已存在
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("该银行账号已存在");
+            return contractSynReturnModel;
+        }
+        String orgname = jsonObject.get("org")+"";
+        if ("".equals(orgname)) {
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("法人主体不能为空");
+            return contractSynReturnModel;
+        }
+        //查询组织是否存在
+        QFilter orgqFilter = new QFilter("name","=",orgname);
+        DynamicObject orginfo =BusinessDataServiceHelper.loadSingleFromCache("bos_org",new QFilter[]{orgqFilter});
+        if(orginfo==null){
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("没有找到名称为:"+orgname+"的组织");
+            return contractSynReturnModel;
+        }
+
+        //账户类型
+        String acctstyle = jsonObject.get("acctstyle")+"";
+        if ("".equals(acctstyle)) {
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("账户类型不能为空");
+            return contractSynReturnModel;
+        }
+        //opendate开户日期
+        String opendate = jsonObject.get("opendate")+"";
+        if ("".equals(opendate)) {
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("开户日期不能为空");
+            return contractSynReturnModel;
+        }
+
+
+        //开户行行号
+        String banknumber = jsonObject.get("banknumber")+"";
+        if ("".equals(banknumber)) {
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("开户行行号不能为空");
+            return contractSynReturnModel;
+        }
+        //查询行名行号
+        QFilter bankqFilter = new QFilter("number","=",banknumber);
+        DynamicObject bankinfo =BusinessDataServiceHelper.loadSingleFromCache("bd_bebank",new QFilter[]{bankqFilter});
+        if (bankinfo==null) {
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("开户行行号"+banknumber+"不存在");
+            return contractSynReturnModel;
+        }
+        //通过开户行行号找到金融机构,没有就新增一个
+        QFilter jrjgqFilter = new QFilter("bebank.number","=",banknumber);
+        DynamicObject jrjginfo =BusinessDataServiceHelper.loadSingleFromCache("bd_finorginfo",new QFilter[]{jrjgqFilter});
+        if (jrjginfo==null) {
+            jrjginfo = BusinessDataServiceHelper.newDynamicObject("bd_finorginfo");
+            jrjginfo.set("finorgtype",defaultjrjgtypeinfo);
+            jrjginfo.set("number",banknumber);
+            jrjginfo.set("bebank",bankinfo);
+            jrjginfo.set("name",bankinfo.get("name")+"");
+            //根据行号前3位找到银行类别,找不到就其他
+            String typecode = banknumber.substring(0,3);
+            QFilter typecodeFilter = new QFilter("type_code.number","=",typecode);
+            DynamicObject typecodeinfo =BusinessDataServiceHelper.loadSingleFromCache("bd_bankcgsetting",new QFilter[]{typecodeFilter});
+            if(typecodeinfo==null){
+                jrjginfo.set("bank_cate",defaulttypecodeinfo);
+            }else{
+                jrjginfo.set("bank_cate",typecodeinfo);
+            }
+            //国家
+            jrjginfo.set("country",defaultgj);
+            //联行号
+            jrjginfo.set("union_number",banknumber);
+
+
+            jrjginfo.set("creator", user);
+            jrjginfo.set("createtime", curDate);
+            jrjginfo.set("enable",1);
+            jrjginfo.set("status","C");
+            //执行保存
+            StringBuilder err = new StringBuilder();
+            OperationResult result = SaveServiceHelper.saveOperate("bd_finorginfo", new DynamicObject[]{jrjginfo}, OperateOption.create());
+            if (result.getSuccessPkIds().size() > 0) {
+                jrjginfo.set("id",result.getSuccessPkIds().get(0));
+            }else{
+                for (int k = 0; k < result.getAllErrorOrValidateInfo().size(); k++) {
+                    String message = result.getAllErrorOrValidateInfo().get(k).getMessage();
+                    err.append("/").append(message);
+                }
+                contractSynReturnModel.setCode("500");
+                contractSynReturnModel.setMessage("金融机构保存失败:"+err.toString());
+                return contractSynReturnModel;
+            }
+        }
+
+
+
+
+        accountinfo =BusinessDataServiceHelper.newDynamicObject("bd_accountbanks");
+        accountinfo.set("company",orginfo);
+        accountinfo.set("openorg",orginfo);
+        accountinfo.set("finorgtype","0");
+        //开户行,即金融机构
+        accountinfo.set("bank",jrjginfo);
+        accountinfo.set("bankaccountnumber",number);
+        accountinfo.set("name",name);
+
+        //币别,多选基础资料
+        DynamicObjectCollection currencyinfos = accountinfo.getDynamicObjectCollection("currency");
+        DynamicObject bibiecollinfo = currencyinfos.addNew();
+        bibiecollinfo.set("fbasedataid",rmbinfo);
+        //默认币种
+        accountinfo.set("defaultcurrency",rmbinfo);
+
+        //acctstyle 账户类型
+        String acctstylestr = "normal";
+        if("基本存款账户".equals(acctstyle)){
+            acctstylestr = "basic";
+        }else if("临时存款账户".equals(acctstyle)){
+            acctstylestr = "temp";
+        }else if("专用存款账户".equals(acctstyle)){
+            acctstylestr = "spcl";
+        }else if("经常项目外汇账户".equals(acctstyle)){
+            acctstylestr = "fgn_curr";
+        }else if("资本项目外汇账户".equals(acctstyle)){
+            acctstylestr = "fng_fin";
+        }
+        accountinfo.set("acctstyle",acctstylestr);
+
+        accountinfo.set("accttype","in_out");
+        accountinfo.set("acctproperty",BusinessDataServiceHelper.loadSingleFromCache(2190699485795992576L,"bd_acctpurpose"));
+
+        try {
+            accountinfo.set("opendate", TypeUtils.string2Date(opendate,TypeUtils.DEFAULT_DATE_FORMAT));
+        }catch (Exception e){
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("开户日期"+opendate+"格式不对:应为yyyy-MM-dd");
+            return contractSynReturnModel;
+        }
+        accountinfo.set("acctstatus","normal");
+        accountinfo.set("elecpaymentlevel","WL01");
+        accountinfo.set("manager",user);
+
+
+        accountinfo.set("enable",1);
+        accountinfo.set("status","C");
+
+
+
+        accountinfo.set("creator", user);
+        accountinfo.set("createorg", defaultOrg);
+        accountinfo.set("org", defaultOrg);
+        accountinfo.set("createtime", curDate);
+
+        //执行保存
+        OperationResult result = SaveServiceHelper.saveOperate("bd_accountbanks", new DynamicObject[]{accountinfo}, OperateOption.create());
+
+        StringBuilder err = new StringBuilder();
+        if (result.getSuccessPkIds().size() > 0) {
+            if (result.isSuccess()) {
+                contractSynReturnModel.setCode("200");
+                contractSynReturnModel.setMessage("保存成功");
+                return contractSynReturnModel;
+            } else {
+                for (int k = 0; k < result.getAllErrorOrValidateInfo().size(); k++) {
+                    String message = result.getAllErrorOrValidateInfo().get(k).getMessage();
+                    err.append("/").append(message);
+                }
+                contractSynReturnModel.setCode("500");
+                contractSynReturnModel.setMessage(err.toString());
+                return contractSynReturnModel;
+            }
+        }else{
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("保存失败");
+            return contractSynReturnModel;
+        }
+    }
+}

+ 135 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/fi/er/webService/SaveBankApi.java

@@ -0,0 +1,135 @@
+package fi.er.webService;
+
+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.entity.operate.result.OperationResult;
+import kd.bos.openapi.common.custom.annotation.ApiController;
+import kd.bos.openapi.common.custom.annotation.ApiMapping;
+import kd.bos.openapi.common.custom.annotation.ApiParam;
+import kd.bos.openapi.common.custom.annotation.ApiPostMapping;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.bos.util.StringUtils;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author zf
+ * 接收九恒星行名行号
+ */
+@ApiController(value = "bank", desc = "自定义API 行名行号同步")
+@ApiMapping(value = "saveBankApi")
+public class SaveBankApi implements Serializable {
+    protected static final Long DEFAULT_ORG_ID = 100000L;
+
+    /**
+     * @description 行名行号同步接口
+     * @param data
+     * @return CustomApiResult
+     */
+    @ApiPostMapping(value = "/save", desc = "同步行名行号")
+    public CustomApiResultForMy<List<BankSynReturnModel>> saveBank (@ApiParam(value = "九恒星行名行号") JSONArray data) {
+        StringBuilder resultString = new StringBuilder();
+        List<BankSynReturnModel> returnList = new ArrayList<>();
+        Boolean result = true;
+
+        //默认的国家
+        DynamicObject defaultgj = BusinessDataServiceHelper.loadSingle("1000001", "bd_country");
+
+
+        RequestContext rc = RequestContext.get();
+        DynamicObject user = BusinessDataServiceHelper.loadSingleFromCache(rc.getCurrUserId(), "bos_user");
+
+        //循环传入的数据
+        for (int i = 0; i < data.size(); i++) {
+            JSONObject eobject = data.getJSONObject(i);
+            BankSynReturnModel contractSynReturnModel = syncBank(eobject,defaultgj,user);
+            if ("500".equals(contractSynReturnModel.getCode())){
+                result = false;
+            }
+            returnList.add(contractSynReturnModel);
+        }
+        return result == true
+                ? CustomApiResultForMy.success2(returnList)
+                : CustomApiResultForMy.fail(returnList);
+    }
+
+
+    /**
+     * @description 保存行名行号
+     * @param jsonObject
+     */
+    private BankSynReturnModel syncBank(JSONObject jsonObject,DynamicObject defaultgj ,DynamicObject user) {
+        BankSynReturnModel contractSynReturnModel = new BankSynReturnModel();
+        String number = jsonObject.get("banknumber")+"";
+        String name = jsonObject.get("bankname")+"";
+        if ("".equals(number)||"".equals(name)) {
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("名称和编码不能为空");
+            return contractSynReturnModel;
+        }
+
+        contractSynReturnModel.setNumber(number);
+        contractSynReturnModel.setName(name);
+
+        //查询是否存在,存在则返回。不存在更新
+        QFilter qFilter = new QFilter("number","=",number);
+        DynamicObject bebankinfo =  BusinessDataServiceHelper.loadSingle("bd_bebank",new QFilter[]{qFilter});
+        if(bebankinfo!=null){
+            //已存在
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("该行号已存在");
+            return contractSynReturnModel;
+        }
+
+        bebankinfo =BusinessDataServiceHelper.newDynamicObject("bd_bebank");
+        bebankinfo.set("number",number);
+        bebankinfo.set("name",name);
+        bebankinfo.set("country",defaultgj);
+        bebankinfo.set("union_number",number);
+        bebankinfo.set("provincetxt",jsonObject.get("province")+"");//省份
+        bebankinfo.set("citytxt",jsonObject.get("city")+"");//城市
+        bebankinfo.set("enable",1);
+        bebankinfo.set("status","C");
+
+
+        Date curDate = new Date();
+        bebankinfo.set("creator", user);
+        bebankinfo.set("createtime", curDate);
+
+        //执行保存
+        OperationResult result = SaveServiceHelper.saveOperate("bd_bebank", new DynamicObject[]{bebankinfo}, OperateOption.create());
+
+        StringBuilder err = new StringBuilder();
+        if (result.getSuccessPkIds().size() > 0) {
+            if (result.isSuccess()) {
+                contractSynReturnModel.setCode("200");
+                contractSynReturnModel.setMessage("保存成功");
+                return contractSynReturnModel;
+            } else {
+                for (int k = 0; k < result.getAllErrorOrValidateInfo().size(); k++) {
+                    String message = result.getAllErrorOrValidateInfo().get(k).getMessage();
+                    err.append("/").append(message);
+                }
+                contractSynReturnModel.setCode("500");
+                contractSynReturnModel.setMessage(err.toString());
+                return contractSynReturnModel;
+            }
+        }else{
+            contractSynReturnModel.setCode("500");
+            contractSynReturnModel.setMessage("保存失败");
+            return contractSynReturnModel;
+        }
+    }
+}

+ 187 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/business/DiDiTripDailyVehicleBillCusInvoke.java

@@ -0,0 +1,187 @@
+package nckd.jimin.jyyy.fi.business;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.exception.ErrorCode;
+import kd.bos.exception.KDBizException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.fi.er.business.trip.model.DailyVehicleBillModel;
+import kd.fi.er.business.trip.model.TripReqbillModel;
+import kd.fi.er.business.trip.supplier.didi.invoke.DiDiTripDailyVehicleBillInvoke;
+import kd.fi.er.business.trip.supplier.didi.systemexternal.DiDiServiceUtil;
+import kd.fi.er.business.trip.supplier.didi.systemexternal.DiDiTripCarRegulationUtil;
+import kd.fi.er.business.trip.util.TripCityUtil;
+import kd.fi.er.business.trip.util.TripCommonUtil;
+import kd.fi.er.business.trip.util.TripSyncDataMappingUtil;
+import org.apache.commons.lang.StringUtils;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class DiDiTripDailyVehicleBillCusInvoke extends DiDiTripDailyVehicleBillInvoke {
+    private static final Log logger = LogFactory.getLog(DiDiTripDailyVehicleBillCusInvoke.class);
+    @Override
+    protected JSONObject convertPushBill(Object info, boolean updateFlag) {
+        DailyVehicleBillModel reqbill = (DailyVehicleBillModel)info;
+        String out_approval_id = reqbill.getBillNo();
+        logger.info("商旅集成,滴滴用车申请单,推送单据,开始数据转换,出差单号:" + out_approval_id);
+        Map<String, String> supplierMap = TripCommonUtil.getTripServiceInfo(this.supplier());
+        String client_id = (String)supplierMap.get("appkey");
+        String company_id = (String)supplierMap.get("orationid");
+
+        String access_token;
+        try {
+            access_token = DiDiServiceUtil.getCacheToken(new Date());
+        } catch (KDBizException var24) {
+            this.tripSyncLogParam.setRequesturl(TripCommonUtil.getTravelNoOneApiUrl("tokenurlkey"));
+            this.tripSyncLogParam.setStatus("B");
+            throw new KDBizException(new ErrorCode("doPost", String.format(ResManager.loadKDString("执行请求过程中出现异常。%s", "DiDiTripDailyVehicleBillInvoke_0", "fi-er-business", new Object[0]), var24)), new Object[0]);
+        }
+
+        if (access_token == null) {
+            this.tripSyncLogParam.setMessage(String.format(ResManager.loadKDString("商旅集成,用车单号:%s,获取滴滴token为空,请检查配置!", "DiDiTripDailyVehicleBillInvoke_1", "fi-er-business", new Object[0]), out_approval_id));
+            this.tripSyncLogParam.setStatus("B");
+            return null;
+        } else {
+            String phone = reqbill.getApplyEmpPhone();
+            String vehicletype = reqbill.getVehicletype();
+            int approval_type = 3;
+
+            String regulation_id = DiDiTripCarRegulationUtil.getUserTripCarRegulationByVehicle(phone, approval_type);
+            if (StringUtils.isBlank(regulation_id)) {
+                this.tripSyncLogParam.setMessage(String.format(ResManager.loadKDString("商旅集成,用车单号:%s,获取出差用车制度为空,请检查配置!", "DiDiTripDailyVehicleBillInvoke_2", "fi-er-business", new Object[0]), out_approval_id));
+                this.tripSyncLogParam.setStatus("B");
+                return null;
+            } else {
+                String reason = reqbill.getDesc();
+                String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
+                HashMap<String, Object> signMap = new HashMap();
+                signMap.put("client_id", client_id);
+                signMap.put("company_id", company_id);
+                signMap.put("access_token", access_token);
+                signMap.put("regulation_id", regulation_id);
+                signMap.put("out_approval_id", out_approval_id);
+                signMap.put("phone", phone);
+                signMap.put("type", 1);
+                QFilter uFilter = new QFilter("server", "=", this.supplier());
+                uFilter.and(new QFilter("datatype", "=", "bos_org"));
+                Map<Object, Object> dataOrgMappingMap = TripSyncDataMappingUtil.getDataMappingMapByFilter(uFilter, "innerdataid", "outdataid");
+                Object budgetCenterId = null;
+                if (dataOrgMappingMap != null && dataOrgMappingMap.size() > 0) {
+                    budgetCenterId = TripSyncDataMappingUtil.getBudgetCenterId(reqbill, (TripReqbillModel)null, dataOrgMappingMap);
+                }
+
+                if (budgetCenterId != null) {
+                    signMap.put("budget_center_id", budgetCenterId);
+                }
+
+                signMap.put("approval_type", approval_type);
+                signMap.put("reason", reason.trim());
+                JSONObject jsonObject = converTravelDetailInfo(reqbill, approval_type);
+                signMap.put("business_trip_detail", gbEncoding(jsonObject.toString()));
+                signMap.put("timestamp", timestamp);
+                JSONObject tripReqObj = new JSONObject();
+                if (updateFlag) {
+                    QFilter updateFilter = new QFilter("server", "=", this.supplier());
+                    updateFilter.and(new QFilter("datatype", "=", "er_dailyvehicle"));
+                    updateFilter.and(new QFilter("number", "=", out_approval_id));
+                    Map<Object, Object> updateDataOrgMappingMap = TripSyncDataMappingUtil.getDataMappingMapByFilter(updateFilter, "number", "outdataid");
+                    logger.info("out_approval_id{}", out_approval_id);
+                    Object o = updateDataOrgMappingMap.get(out_approval_id);
+                    if (o != null) {
+                        signMap.put("approval_id", o);
+                        tripReqObj.put("approval_id", o);
+                    }
+                }
+
+                String tripreqSignKey = DiDiServiceUtil.genSign(signMap, (String)supplierMap.get("reservedfield1"));
+                tripReqObj.put("client_id", client_id);
+                tripReqObj.put("company_id", company_id);
+                tripReqObj.put("access_token", access_token);
+                tripReqObj.put("timestamp", timestamp);
+                tripReqObj.put("regulation_id", regulation_id);
+                tripReqObj.put("out_approval_id", out_approval_id);
+                tripReqObj.put("phone", phone);
+                tripReqObj.put("approval_type", approval_type);
+                tripReqObj.put("type", 1);
+                if (budgetCenterId != null) {
+                    tripReqObj.put("budget_center_id", budgetCenterId);
+                }
+
+                tripReqObj.put("reason", reason.trim());
+                tripReqObj.put("business_trip_detail", jsonObject);
+                tripReqObj.put("sign", tripreqSignKey);
+                return tripReqObj;
+            }
+        }
+    }
+
+
+    private static String gbEncoding(String s) {
+        StringBuilder buf = new StringBuilder();
+        char[] c = s.toCharArray();
+        char[] var3 = c;
+        int var4 = c.length;
+
+        for(int var5 = 0; var5 < var4; ++var5) {
+            char tmp = var3[var5];
+            if (tmp > 255) {
+                buf = buf.append("\\u").append(Integer.toHexString(tmp));
+            } else {
+                buf = buf.append(tmp);
+            }
+        }
+
+        return buf.toString();
+    }
+
+    private JSONObject converTravelDetailInfo(DailyVehicleBillModel reqbill, int approval_type) {
+        JSONObject travelDetailInfo = new JSONObject();
+        Date startDate = reqbill.getStartdate();
+        Date endDate = reqbill.getEnddate();
+//        Calendar calendar = Calendar.getInstance();
+//        calendar.setTimeInMillis(endDate.getTime());
+//        calendar.set(11, 23);
+//        calendar.set(12, 59);
+//        calendar.set(13, 59);
+//        Date time = calendar.getTime();
+
+        if (approval_type == 2) {
+            travelDetailInfo.put("start_time", TripCommonUtil.date2TimeStamp(startDate, "yyyy-MM-dd HH:mm:ss"));
+            travelDetailInfo.put("end_time", TripCommonUtil.date2TimeStamp(endDate, "yyyy-MM-dd HH:mm:ss"));
+            travelDetailInfo.put("departure_city_id", TripCityUtil.getDiDiCityId(reqbill.getVehiclecity()).get(reqbill.getVehiclecity()));
+            travelDetailInfo.put("destination_city_id", TripCityUtil.getDiDiCityId(reqbill.getVehiclecity()).get(reqbill.getVehiclecity()));
+            travelDetailInfo.put("departure_city", reqbill.getVehiclecityName());
+            travelDetailInfo.put("destination_city", reqbill.getVehiclecityName());
+            travelDetailInfo.put("trip_times", reqbill.getVehiclenumber());
+        } else if (approval_type == 3) {
+//            Calendar instance = Calendar.getInstance();
+//            instance.setTime(time);
+//            instance.add(11, 6);
+//            instance.add(13, 1);
+//            Date newEndDate = instance.getTime();
+
+            travelDetailInfo.put("start_time", TripCommonUtil.date2TimeStamp(startDate, "yyyy-MM-dd HH:mm:ss"));
+            travelDetailInfo.put("end_time", TripCommonUtil.date2TimeStamp(endDate, "yyyy-MM-dd HH:mm:ss"));
+
+            //用车城市
+            JSONArray trips = new JSONArray();
+            JSONObject trip = new JSONObject();
+
+            trip.put("city_id", TripCityUtil.getDiDiCityId(reqbill.getVehiclecity()).get(reqbill.getVehiclecity()));
+            trip.put("city", reqbill.getVehiclecityName());
+
+            trips.add(trip);
+            travelDetailInfo.put("trips", trips);
+
+            //打车次数
+            travelDetailInfo.put("trip_times", -1);
+        }
+
+        return travelDetailInfo;
+    }
+}

+ 531 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/business/DiDiTripReqBillCusInvoke.java

@@ -0,0 +1,531 @@
+package nckd.jimin.jyyy.fi.business;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.google.common.collect.Lists;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.DeleteServiceHelper;
+import kd.bos.util.CollectionUtils;
+import kd.fi.er.business.servicehelper.HttpRetryServiceHelper;
+import kd.fi.er.business.trip.exception.TripSyncLogParam;
+import kd.fi.er.business.trip.exception.TripSyncLogUtils;
+import kd.fi.er.business.trip.model.*;
+import kd.fi.er.business.trip.service.function.AbstractTripReqBillInvoke;
+import kd.fi.er.business.trip.supplier.Supplier;
+import kd.fi.er.business.trip.supplier.didi.systemexternal.DiDiServiceUtil;
+import kd.fi.er.business.trip.supplier.didi.systemexternal.DiDiTripCarRegulationUtil;
+import kd.fi.er.business.trip.util.TripCityUtil;
+import kd.fi.er.business.trip.util.TripCommonUtil;
+import kd.fi.er.business.trip.util.TripSyncConfigUtil;
+import kd.fi.er.business.trip.util.TripSyncDataMappingUtil;
+import kd.fi.er.common.ExternalConstants;
+import org.apache.commons.lang.StringUtils;
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class DiDiTripReqBillCusInvoke extends AbstractTripReqBillInvoke<JSONObject> {
+    private static final Log logger = LogFactory.getLog(DiDiTripReqBillCusInvoke.class);
+    private static int APPROVAL_TYPE = 1;
+
+    public DiDiTripReqBillCusInvoke() {
+    }
+
+    protected String supplier() {
+        return Supplier.DIDI.name();
+    }
+
+    protected Object convert(Object value) {
+        switch ((String)this.getParams().get("syncStatus")) {
+            case "1":
+            case "3":
+                return this.convertPushBill(value, false);
+            case "2":
+                return this.convertStatusChange((TripReqbillModel)value);
+            default:
+                return null;
+        }
+    }
+
+    protected JSONObject convertPushBill(Object info) {
+        return this.convertPushBill(info, false);
+    }
+
+    protected JSONObject convertPushBill(Object info, boolean updateFlag) {
+        TripReqbillModel reqbill = (TripReqbillModel)info;
+        String out_approval_id = reqbill.getBillNo();
+        logger.info("商旅集成,滴滴出差申请单,推送单据,开始数据转换,出差单号:" + out_approval_id);
+        Map<String, String> supplierMap = TripCommonUtil.getTripServiceInfo(this.supplier());
+        String client_id = (String)supplierMap.get("appkey");
+        String company_id = (String)supplierMap.get("orationid");
+        String access_token = DiDiServiceUtil.getCacheToken(new Date());
+        if (access_token == null) {
+            this.tripSyncLogParam.setMessage(String.format(ResManager.loadKDString("商旅集成,出差单号:%s,获取滴滴token为空,请检查配置!", "DiDiTripReqBillInvoke_0", "fi-er-business", new Object[0]), out_approval_id));
+            this.tripSyncLogParam.setStatus("B");
+            return null;
+        } else {
+            String phone = reqbill.getApplyEmpPhone();
+            String regulation_id = DiDiTripCarRegulationUtil.getUserTripCarRegulation(phone, "2");
+            if (StringUtils.isBlank(regulation_id)) {
+                this.tripSyncLogParam.setMessage(String.format(ResManager.loadKDString("商旅集成,出差单号:%s,获取出差用车制度为空,请检查配置!", "DiDiTripReqBillInvoke_1", "fi-er-business", new Object[0]), out_approval_id));
+                this.tripSyncLogParam.setStatus("B");
+                return null;
+            } else {
+                int approval_type = APPROVAL_TYPE;
+                String reason = reqbill.getDesc();
+                String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
+                HashMap<String, Object> signMap = new HashMap();
+                signMap.put("client_id", client_id);
+                signMap.put("company_id", company_id);
+                signMap.put("access_token", access_token);
+                signMap.put("regulation_id", regulation_id);
+                signMap.put("out_approval_id", out_approval_id);
+                signMap.put("phone", phone);
+                signMap.put("type", 1);
+                QFilter uFilter = new QFilter("server", "=", this.supplier());
+                uFilter.and(new QFilter("datatype", "=", "bos_org"));
+                Map<Object, Object> dataOrgMappingMap = TripSyncDataMappingUtil.getDataMappingMapByFilter(uFilter, "innerdataid", "outdataid");
+                Object budgetCenterId = null;
+                if (dataOrgMappingMap.size() > 0) {
+                    budgetCenterId = TripSyncDataMappingUtil.getBudgetCenterId((DailyVehicleBillModel)null, reqbill, dataOrgMappingMap);
+                }
+
+                if (budgetCenterId != null) {
+                    signMap.put("budget_center_id", budgetCenterId);
+                }
+
+                signMap.put("approval_type", approval_type);
+                signMap.put("reason", reason.trim());
+                JSONObject travelDetailInfo = this.converTravelDetailInfo(reqbill);
+                signMap.put("travel_detail", gbEncoding(travelDetailInfo.toString()));
+                signMap.put("timestamp", timestamp);
+                JSONArray companions = this.setCompanions(reqbill);
+                signMap.put("passenger_list", gbEncoding(companions.toString()));
+                JSONObject tripReqObj = new JSONObject();
+                if (updateFlag) {
+                    QFilter updateFilter = new QFilter("server", "=", this.supplier());
+                    updateFilter.and(new QFilter("datatype", "=", "er_tripreq"));
+                    updateFilter.and(new QFilter("number", "=", out_approval_id));
+                    Map<Object, Object> updateDataOrgMappingMap = TripSyncDataMappingUtil.getDataMappingMapByFilter(updateFilter, "number", "outdataid");
+                    Object o = updateDataOrgMappingMap.get(out_approval_id);
+                    if (o != null) {
+                        signMap.put("approval_id", o);
+                        tripReqObj.put("approval_id", o);
+                    } else if (null != this.params.get("approval_id")) {
+                        signMap.put("approval_id", this.params.get("approval_id"));
+                        tripReqObj.put("approval_id", this.params.get("approval_id"));
+                    }
+                }
+
+                String tripreqSignKey = DiDiServiceUtil.genSign(signMap, (String)supplierMap.get("reservedfield1"));
+                tripReqObj.put("client_id", client_id);
+                tripReqObj.put("company_id", company_id);
+                tripReqObj.put("access_token", access_token);
+                tripReqObj.put("timestamp", timestamp);
+                tripReqObj.put("regulation_id", regulation_id);
+                tripReqObj.put("out_approval_id", out_approval_id);
+                tripReqObj.put("phone", phone);
+                tripReqObj.put("approval_type", approval_type);
+                tripReqObj.put("type", 1);
+                if (budgetCenterId != null) {
+                    tripReqObj.put("budget_center_id", budgetCenterId);
+                }
+
+                tripReqObj.put("reason", reason.trim());
+                tripReqObj.put("travel_detail", travelDetailInfo);
+                tripReqObj.put("passenger_list", companions);
+                tripReqObj.put("sign", tripreqSignKey);
+                return tripReqObj;
+            }
+        }
+    }
+
+    private JSONArray setCompanions(TripReqbillModel reqbill) {
+        boolean paramValue = TripSyncConfigUtil.getBoolean("Reservation_ personnel_range", Boolean.FALSE);
+        JSONArray jsonArray = new JSONArray();
+        if (paramValue) {
+            List<JourneyModel> journeyModelList = reqbill.getJourneyModelList();
+            int size = journeyModelList.size();
+            List<String> userNumberList = Lists.newArrayListWithCapacity(16);
+
+            for(int i = 0; i < size; ++i) {
+                JourneyModel journeyModel = (JourneyModel)journeyModelList.get(i);
+                Set<DynamicObject> travelers = journeyModel.getTravelers();
+                Set<String> travelNumberSet = (Set)travelers.stream().filter((traveler) -> {
+                    return StringUtils.isNotEmpty(traveler.getString("number"));
+                }).map((traveler) -> {
+                    return traveler.getString("number");
+                }).collect(Collectors.toSet());
+                userNumberList.addAll(travelNumberSet);
+            }
+
+            if (!userNumberList.contains(reqbill.getCreatEmpNum())) {
+                userNumberList.add(reqbill.getCreatEmpNum());
+            }
+
+            if (!userNumberList.contains(reqbill.getApplyEmpNum())) {
+                userNumberList.add(reqbill.getApplyEmpNum());
+            }
+
+            if (CollectionUtils.isEmpty(userNumberList)) {
+                return jsonArray;
+            }
+
+            DynamicObjectCollection users = QueryServiceHelper.query("bos_user", "number,name,id", new QFilter[]{new QFilter("number", "in", userNumberList)});
+            Iterator var15 = users.iterator();
+
+            while(var15.hasNext()) {
+                DynamicObject user = (DynamicObject)var15.next();
+                JSONObject jsonObject = new JSONObject();
+                jsonObject.put("member_type", "1");
+                jsonObject.put("passenger_type", "0");
+                jsonObject.put("employee_number", user.getString("number"));
+                jsonObject.put("passenger_name", user.getString("name"));
+                jsonArray.add(jsonObject);
+            }
+        } else {
+            String creatEmpNum = reqbill.getCreatEmpNum();
+            String applyEmpNum = reqbill.getApplyEmpNum();
+            JSONObject jsonObject;
+            if (StringUtils.isNotEmpty(creatEmpNum) && StringUtils.isNotEmpty(applyEmpNum) && creatEmpNum.equals(applyEmpNum)) {
+                jsonObject = new JSONObject();
+                jsonObject.put("member_type", "1");
+                jsonObject.put("passenger_type", "0");
+                jsonObject.put("employee_number", creatEmpNum);
+                jsonObject.put("passenger_name", reqbill.getCreatEmpName());
+                jsonArray.add(jsonObject);
+            } else {
+                jsonObject = new JSONObject();
+                jsonObject.put("member_type", "1");
+                jsonObject.put("passenger_type", "0");
+                jsonObject.put("employee_number", creatEmpNum);
+                jsonObject.put("passenger_name", reqbill.getCreatEmpName());
+                jsonArray.add(jsonObject);
+                jsonObject = new JSONObject();
+                jsonObject.put("member_type", "1");
+                jsonObject.put("passenger_type", "0");
+                jsonObject.put("employee_number", applyEmpNum);
+                jsonObject.put("passenger_name", reqbill.getApplyEmpName());
+                jsonArray.add(jsonObject);
+            }
+        }
+
+        return jsonArray;
+    }
+
+    private JSONObject converTravelDetailInfo(TripReqbillModel reqbill) {
+        JSONObject travelDetailInfo = new JSONObject();
+        List<JourneyModel> tripentryList = reqbill.getJourneyModelList();
+        if (tripentryList != null && tripentryList.size() > 0) {
+            Date firstStartDate = ((JourneyModel)tripentryList.get(0)).getStartDate();
+            Date endStartDate = ((JourneyModel)tripentryList.get(tripentryList.size() - 1)).getEndDate();
+            DynamicObject tripControlsetting = TripCommonUtil.getTripControlSettings(reqbill.getCompanyId(), this.supplier());
+            int start_city_rule = 1;
+            int end_city_rule = 1;
+            if (null != tripControlsetting && null != tripControlsetting.getString("startcityrule")) {
+                start_city_rule = Integer.parseInt(tripControlsetting.getString("startcityrule"));
+            }
+
+            if (null != tripControlsetting && null != tripControlsetting.getString("endcityrule")) {
+                end_city_rule = Integer.parseInt(tripControlsetting.getString("endcityrule"));
+            }
+
+            HashMap<String, Object> paramMap = new HashMap();
+            paramMap.put("start_date", TripCommonUtil.date2TimeStamp(firstStartDate, "yyyy-MM-dd"));
+            paramMap.put("end_date", TripCommonUtil.date2TimeStamp(endStartDate, "yyyy-MM-dd"));
+            JSONArray trips = this.getTrips(new JSONArray(), tripentryList, paramMap);
+            travelDetailInfo.put("start_date", TripCommonUtil.date2TimeStamp(firstStartDate, "yyyy-MM-dd"));
+            travelDetailInfo.put("end_date", TripCommonUtil.date2TimeStamp(endStartDate, "yyyy-MM-dd"));
+            travelDetailInfo.put("trips", trips);
+            travelDetailInfo.put("start_city_rule", start_city_rule);
+            travelDetailInfo.put("end_city_rule", end_city_rule);
+        }
+
+        return travelDetailInfo;
+    }
+
+    private JSONArray getTrips(JSONArray trips, List<JourneyModel> tripentryList, Map<String, Object> paramMap) {
+        int dtrip_to_citys = TripSyncConfigUtil.getIntValue("dtrip_to_citys", 0);
+        JSONObject tripObj;
+        if (dtrip_to_citys == 1) {
+            tripObj = new JSONObject();
+            if (tripentryList == null || tripentryList.size() == 0) {
+                logger.info("商旅集成,滴滴出差申请单,tripentryList为空");
+                return trips;
+            }
+
+            JourneyModel tripentry = (JourneyModel)tripentryList.get(0);
+            tripObj.put("departure_city", tripentry.getFromCity());
+            tripObj.put("departure_city_id", TripCityUtil.getDiDiCityId(tripentry.getFromCityID()).get(tripentry.getFromCityID()));
+            tripObj.put("start_date", paramMap.get("start_date"));
+            tripObj.put("end_date", paramMap.get("end_date"));
+            tripObj.put("trip_type", "0");
+            tripObj.put("to_citys", this.getToCitys(tripentryList));
+            trips.add(tripObj);
+        } else {
+            for(int i = 0; i < tripentryList.size(); ++i) {
+                tripObj = new JSONObject();
+                JourneyModel tripentry = (JourneyModel)tripentryList.get(i);
+                tripObj.put("departure_city_id", TripCityUtil.getDiDiCityId(tripentry.getFromCityID()).get(tripentry.getFromCityID()));
+                tripObj.put("destination_city_id", TripCityUtil.getDiDiCityId(tripentry.getToCityID()).get(tripentry.getToCityID()));
+                tripObj.put("departure_city", tripentry.getFromCity());
+                tripObj.put("destination_city", tripentry.getToCity());
+                tripObj.put("start_date", TripCommonUtil.date2TimeStamp(tripentry.getStartDate(), "yyyy-MM-dd"));
+                tripObj.put("end_date", TripCommonUtil.date2TimeStamp(tripentry.getEndDate(), "yyyy-MM-dd"));
+                tripObj.put("trip_type", "0");
+                trips.add(tripObj);
+            }
+
+            if (!trips.getJSONObject(0).getString("departure_city").equals(trips.getJSONObject(trips.size() - 1).getString("destination_city"))) {
+                tripObj = new JSONObject();
+                tripObj.put("departure_city_id", trips.getJSONObject(trips.size() - 1).getString("destination_city_id"));
+                tripObj.put("destination_city_id", trips.getJSONObject(0).getString("departure_city_id"));
+                tripObj.put("departure_city", trips.getJSONObject(trips.size() - 1).getString("destination_city"));
+                tripObj.put("destination_city", trips.getJSONObject(0).getString("departure_city"));
+                tripObj.put("start_date", trips.getJSONObject(trips.size() - 1).getString("end_date"));
+                tripObj.put("end_date", trips.getJSONObject(trips.size() - 1).getString("end_date"));
+                tripObj.put("trip_type", "0");
+                trips.add(tripObj);
+            }
+        }
+
+        return trips;
+    }
+
+    private Object getToCitys(List<JourneyModel> tripentryList) {
+        JSONArray to_citys = new JSONArray();
+        HashSet<Long> toCitySet = new HashSet();
+        Iterator var4 = tripentryList.iterator();
+
+        while(true) {
+            Set mulwaytos;
+            do {
+                if (!var4.hasNext()) {
+                    QFilter filter = new QFilter("id", "in", toCitySet);
+                    Map<Object, DynamicObject> cities = BusinessDataServiceHelper.loadFromCache("er_city", "id,didicityid,admindivisionid.name", new QFilter[]{filter});
+                    if (cities == null) {
+                        return to_citys;
+                    }
+
+                    Iterator var12 = cities.values().iterator();
+
+                    while(var12.hasNext()) {
+                        DynamicObject city = (DynamicObject)var12.next();
+                        DynamicObject admindivisionid = city.getDynamicObject("admindivisionid");
+                        if (admindivisionid != null && StringUtils.isNotBlank(admindivisionid.getString("name"))) {
+                            JSONObject jsonObject = new JSONObject();
+                            jsonObject.put("id", city.getLong("didicityid"));
+                            jsonObject.put("name", admindivisionid.getString("name"));
+                            to_citys.add(jsonObject);
+                        }
+                    }
+
+                    return to_citys;
+                }
+
+                JourneyModel journeyModel = (JourneyModel)var4.next();
+                toCitySet.add(journeyModel.getFromCityID());
+                toCitySet.add(journeyModel.getToCityID());
+                mulwaytos = journeyModel.getMulwaytos();
+            } while(mulwaytos == null);
+
+            Iterator var7 = mulwaytos.iterator();
+
+            while(var7.hasNext()) {
+                Object obj = var7.next();
+                if (obj != null) {
+                    MulwaytoModel mulwayto = (MulwaytoModel)obj;
+                    toCitySet.add(mulwayto.getToCityID());
+                }
+            }
+        }
+    }
+
+    private JSONObject convertStatusChange(TripReqbillModel reqbill) {
+        String out_approval_id = reqbill.getBillNo();
+        logger.info("商旅集成,滴滴出差申请单,取消单据,开始数据转换,出差单号:" + out_approval_id);
+        Map<String, String> supplierMap = TripCommonUtil.getTripServiceInfo(this.supplier());
+        String client_id = (String)supplierMap.get("appkey");
+        String company_id = (String)supplierMap.get("orationid");
+        String access_token = DiDiServiceUtil.getCacheToken(new Date());
+        if (access_token == null) {
+            this.tripSyncLogParam.setMessage(String.format(ResManager.loadKDString("商旅集成,出差单号:%s,获取滴滴token为空,请检查配置!", "DiDiTripReqBillInvoke_0", "fi-er-business", new Object[0]), out_approval_id));
+            this.tripSyncLogParam.setStatus("B");
+            return null;
+        } else {
+            QFilter uFilter = new QFilter("server", "=", this.supplier());
+            uFilter.and(new QFilter("datatype", "=", "er_tripreq"));
+            Map<Object, Object> dataTripReqMappingMap = TripSyncDataMappingUtil.getDataMappingMapByFilter(uFilter, "number", "outdataid");
+            Object tripReqBillId = dataTripReqMappingMap.get(out_approval_id);
+            if (dataTripReqMappingMap != null && dataTripReqMappingMap.size() > 0 && tripReqBillId != null) {
+                String approval_id = String.valueOf(tripReqBillId);
+                if (approval_id != null && !StringUtils.isEmpty(approval_id)) {
+                    String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
+                    HashMap<String, Object> signMap = new HashMap();
+                    signMap.put("client_id", client_id);
+                    signMap.put("company_id", company_id);
+                    signMap.put("access_token", access_token);
+                    signMap.put("approval_id", approval_id);
+                    signMap.put("timestamp", timestamp);
+                    String tripreqCloseSignKey = DiDiServiceUtil.genSign(signMap, (String)supplierMap.get("reservedfield1"));
+                    JSONObject tripreqCloseObj = new JSONObject(signMap);
+                    tripreqCloseObj.put("sign", tripreqCloseSignKey);
+                    return tripreqCloseObj;
+                } else {
+                    this.tripSyncLogParam.setMessage(String.format(ResManager.loadKDString("商旅集成,出差单号:%s,获取滴滴侧出差申请单id为空,该单据尚未推送,暂不需要取消!", "DiDiTripReqBillInvoke_2", "fi-er-business", new Object[0]), out_approval_id));
+                    this.tripSyncLogParam.setStatus("A");
+                    return null;
+                }
+            } else {
+                return null;
+            }
+        }
+    }
+
+    protected String batPushProcess(Object value) {
+        String jsonStr;
+        if (value == null) {
+            jsonStr = "200";
+            if (this.tripSyncLogParam.getStatus().equals("B")) {
+                jsonStr = "300";
+            }
+
+            return jsonStr;
+        } else {
+            jsonStr = JSON.toJSONString(value, new SerializerFeature[]{SerializerFeature.DisableCircularReferenceDetect});
+            String url = "";
+            String syncStatus = (String)this.getParams().get("syncStatus");
+            switch ((String)this.getParams().get("syncStatus")) {
+                case "1":
+                case "3":
+                    url = (String) ExternalConstants.DIDIURLMAP.get("approvalAddKey");
+                    break;
+                case "2":
+                    url = (String)ExternalConstants.DIDIURLMAP.get("approvalCancelKey");
+            }
+
+            this.tripSyncLogParam.setRequestdata(value);
+            this.tripSyncLogParam.setRequesturl(url);
+            String result = HttpRetryServiceHelper.PostData(url, jsonStr);
+            this.tripSyncLogParam.setResponsedata(result);
+            JSONObject resultJsonObject = JSONObject.parseObject(result);
+            List dataMappingList = new ArrayList();
+            if (resultJsonObject != null && (resultJsonObject.getIntValue("errno") == 0 || resultJsonObject.getIntValue("errno") == 50506)) {
+                String outdataid;
+                if (resultJsonObject.getIntValue("errno") == 50506) {
+                    logger.info("didi update api");
+                    String errmsg = resultJsonObject.getString("errmsg");
+                    if (null == errmsg) {
+                        logger.info("商旅集成,滴滴出差申请单同步:{}", resultJsonObject.toJSONString());
+                        return "300";
+                    } else {
+                        errmsg = errmsg.substring(errmsg.lastIndexOf("("), errmsg.lastIndexOf(")"));
+                        if (null == errmsg) {
+                            logger.info("商旅集成,滴滴出差申请单同步:{}", resultJsonObject.toJSONString());
+                            return "300";
+                        } else {
+                            StringBuilder sb = new StringBuilder();
+                            char[] var24 = errmsg.toCharArray();
+                            int var26 = var24.length;
+
+                            for(int var12 = 0; var12 < var26; ++var12) {
+                                char c = var24[var12];
+                                if (Character.isDigit(c)) {
+                                    sb.append(c);
+                                }
+                            }
+
+                            this.dealData(jsonStr);
+                            TripSyncDataMappingModel TripSyncDataMappingObj = new TripSyncDataMappingModel("er_tripreq", this.supplier());
+                            outdataid = sb.toString();
+                            JSONObject reqJson = JSONObject.parseObject(jsonStr);
+                            String out_approval_id = reqJson.getString("out_approval_id");
+                            TripSyncDataMappingObj.setNumber(out_approval_id);
+                            TripSyncDataMappingObj.setOutdataid(Long.parseLong(outdataid));
+                            dataMappingList.add(TripSyncDataMappingObj);
+                            TripSyncDataMappingUtil.saveTripSyncDataMapping(dataMappingList);
+                            Object updateValue = this.redealJson();
+                            String updateJsonStr = JSON.toJSONString(updateValue, new SerializerFeature[]{SerializerFeature.DisableCircularReferenceDetect});
+                            TripSyncLogParam updateTripSyncLogParam = new TripSyncLogParam(RequestContext.get().getTraceId(), this.supplier(), this.function());
+                            String updateUrl = (String)ExternalConstants.DIDIURLMAP.get("approvalUpdateKey");
+                            updateTripSyncLogParam.setRequestdata(updateValue);
+                            Object billId = this.getParams().get("billId");
+                            updateTripSyncLogParam.setBillno(String.valueOf(billId));
+                            updateTripSyncLogParam.setRequesturl(updateUrl);
+                            String updateResult = HttpRetryServiceHelper.PostData(updateUrl, updateJsonStr);
+                            updateTripSyncLogParam.setResponsedata(updateResult);
+                            JSONObject updateResultJsonObject = JSONObject.parseObject(updateResult);
+                            if (updateResultJsonObject != null && updateResultJsonObject.getIntValue("errno") == 0) {
+                                updateTripSyncLogParam.setStatus("A");
+                            } else {
+                                updateTripSyncLogParam.setStatus("B");
+                            }
+
+                            TripSyncLogUtils.saveErrorLog(Collections.singletonList(updateTripSyncLogParam));
+                            return "200";
+                        }
+                    }
+                } else {
+                    this.tripSyncLogParam.setStatus("A");
+                    if (StringUtils.equals(syncStatus, "1") || StringUtils.equals(syncStatus, "3")) {
+                        this.dealData(jsonStr);
+                        TripSyncDataMappingModel TripSyncDataMappingObj = new TripSyncDataMappingModel("er_tripreq", this.supplier());
+                        JSONObject data = JSON.parseObject(JSON.toJSONString(resultJsonObject.get("data")));
+                        outdataid = data.getString("approval_id");
+                        outdataid = JSON.parseObject(JSON.toJSONString(value)).getString("out_approval_id");
+                        TripSyncDataMappingObj.setNumber(outdataid);
+                        TripSyncDataMappingObj.setOutdataid(Long.parseLong(outdataid));
+                        dataMappingList.add(TripSyncDataMappingObj);
+                    }
+
+                    TripSyncDataMappingUtil.saveTripSyncDataMapping(dataMappingList);
+                    return "200";
+                }
+            } else {
+                this.tripSyncLogParam.setStatus("B");
+                return "300";
+            }
+        }
+    }
+
+    private void dealData(String jsonStr) {
+        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
+        if (jsonObject != null) {
+            String applyNumber = jsonObject.getString("out_approval_id");
+            DeleteServiceHelper.delete("er_tripsync_datamapping", new QFilter[]{new QFilter("server", "=", this.supplier()), new QFilter("number", "=", applyNumber)});
+        }
+
+    }
+
+    private static String gbEncoding(String s) {
+        StringBuilder buf = new StringBuilder();
+        char[] c = s.toCharArray();
+        char[] var3 = c;
+        int var4 = c.length;
+
+        for(int var5 = 0; var5 < var4; ++var5) {
+            char tmp = var3[var5];
+            if (tmp > 255) {
+                buf = buf.append("\\u").append(Integer.toHexString(tmp));
+            } else {
+                buf = buf.append(tmp);
+            }
+        }
+
+        return buf.toString();
+    }
+
+    private Object redealJson() {
+        Object innerData = this.getInnerData();
+        return this.convertPushBill(innerData, true);
+    }
+}

+ 97 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/common/FinanceCommonUtils.java

@@ -0,0 +1,97 @@
+package nckd.jimin.jyyy.fi.common;
+
+import kd.bos.dataentity.entity.DynamicObject;
+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.servicehelper.BusinessDataServiceHelper;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 财务帮助类
+ * @author wanghaiwu_kd
+ * @date 2025/04/29
+ */
+public class FinanceCommonUtils {
+
+    private static final Log logger = LogFactory.getLog(FinanceCommonUtils.class);
+
+    /**
+     * 校验出差申请单、外办单是否存在与参数startDate, endDate存在时间交叉的记录
+     * @param startDate
+     * @param endDate
+     * @return
+     */
+    public static String checkDateIsExists(Long billId, Long userId, Date startDate, Date endDate){
+        String checkMsg = "";
+
+        String selectFields = "id, billno";
+
+        QFilter qFilter = buildSearchFilter("er_tripreqbill", billId, userId, startDate, endDate);
+        //出差申请单
+        DynamicObject[] tripReqBillArray = BusinessDataServiceHelper.load("er_tripreqbill", selectFields, qFilter.toArray());
+
+        qFilter = buildSearchFilter("er_dailyvehiclebill", billId, userId, startDate, endDate);
+        //外办单
+        DynamicObject[] vehicleBillArray = BusinessDataServiceHelper.load("er_dailyvehiclebill", selectFields, qFilter.toArray());
+
+        String tripReqBills = "";
+        if(tripReqBillArray.length > 0){
+            List<String> numberList = (List) Arrays.stream(tripReqBillArray).map((o) -> {
+                return o.getString("billno");
+            }).collect(Collectors.toList());
+
+            tripReqBills = String.join(",", numberList);
+        }
+        String vehicleBills = "";
+        if(vehicleBillArray.length > 0){
+            List<String> numberList = (List) Arrays.stream(vehicleBillArray).map((o) -> {
+                return o.getString("billno");
+            }).collect(Collectors.toList());
+
+            vehicleBills = String.join(",", numberList);
+        }
+
+        if(tripReqBills.length() > 0){
+            checkMsg += "出差申请单:" + tripReqBills;
+        }
+        if(vehicleBills.length() > 0){
+            checkMsg += "外办单:" + vehicleBills;
+        }
+
+        return checkMsg;
+    }
+
+    /**
+     * 构造查询条件
+     * @param entityName
+     * @param startDate
+     * @param endDate
+     * @return
+     */
+    public static QFilter buildSearchFilter(String entityName, Long billId, Long userId, Date startDate, Date endDate){
+        String prefix = "";
+
+        if("er_tripreqbill".equals(entityName)){
+            prefix = "tripentry.";
+        }
+
+        QFilter qFilter = new QFilter("billstatus", QCP.equals, "A");
+        qFilter.and(new QFilter("id", QCP.not_equals, billId));
+        qFilter.and(new QFilter("applier", QCP.equals, userId));
+
+        QFilter startFilter = new QFilter(prefix + "startDate", QCP.less_equals, startDate);
+        startFilter.and(new QFilter(prefix + "endDate", QCP.large_equals, startDate));
+
+        QFilter endFilter = new QFilter(prefix + "startDate", QCP.less_equals, endDate);
+        endFilter.and(new QFilter(prefix + "endDate", QCP.large_equals, endDate));
+
+        qFilter.and(startFilter.or(endFilter));
+
+        return qFilter;
+    }
+}

+ 49 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/DailyApplyBillEditPlugin.java

@@ -0,0 +1,49 @@
+package nckd.jimin.jyyy.fi.plugin.form;
+
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.list.ListFilterParameter;
+import kd.bos.list.ListShowParameter;
+import kd.bos.orm.query.QFilter;
+
+import java.util.EventObject;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 单据标识:费用申请单(nckd_er_dailyapplybil_ext)
+ * @author wanghaiwu_kd
+ * @date 2025/04/28
+ */
+public class DailyApplyBillEditPlugin extends AbstractBillPlugIn implements BeforeF7SelectListener {
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+
+        BasedataEdit expenseitemF7 = (BasedataEdit) this.getControl("expenseitem");
+        expenseitemF7.addBeforeF7SelectListener(this);
+    }
+
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent evt) {
+        String property = evt.getProperty().getName();
+        String entityId = ((BasedataProp) evt.getProperty()).getBaseEntityId();
+        int curRowIndex = evt.getRow();
+
+        if("expenseitem".equals(property)) {
+            ListShowParameter showParameter = (ListShowParameter) evt.getFormShowParameter();
+            ListFilterParameter filterParam = showParameter.getListFilterParameter();
+            List<QFilter> qFilters = filterParam.getQFilters();
+
+            Map<String, Object> customParams = this.getView().getFormShowParameter().getCustomParams();
+            if(customParams.get("nckd_viewTypeFilter") != null){
+                QFilter viewTypeFilter = QFilter.fromSerializedString(customParams.get("nckd_viewTypeFilter").toString());
+
+                qFilters.add(viewTypeFilter);
+            }
+
+        }
+    }
+}

+ 52 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/ExpenseItemFilterFormPlugin.java

@@ -0,0 +1,52 @@
+package nckd.jimin.jyyy.fi.plugin.form;
+
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.list.ListFilterParameter;
+import kd.bos.list.ListShowParameter;
+import kd.bos.orm.query.QFilter;
+import java.util.EventObject;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 单据标识:公共单据插件,处理费用项目过滤问题。
+ * @author wanghaiwu_kd
+ * @date 2025/05/06
+ */
+public class ExpenseItemFilterFormPlugin extends AbstractBillPlugIn implements BeforeF7SelectListener {
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+
+        Boolean havaExpenseItem = this.getModel().getDataEntityType().getProperties().containsKey("expenseitem");
+        if(havaExpenseItem) {
+            BasedataEdit expenseitemF7 = (BasedataEdit) this.getControl("expenseitem");
+            expenseitemF7.addBeforeF7SelectListener(this);
+        }
+    }
+
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent evt) {
+        String property = evt.getProperty().getName();
+        String entityId = ((BasedataProp) evt.getProperty()).getBaseEntityId();
+        int curRowIndex = evt.getRow();
+
+        if ("expenseitem".equals(property)) {
+            ListShowParameter showParameter = (ListShowParameter) evt.getFormShowParameter();
+            ListFilterParameter filterParam = showParameter.getListFilterParameter();
+            List<QFilter> qFilters = filterParam.getQFilters();
+
+            Map<String, Object> customParams = this.getView().getFormShowParameter().getCustomParams();
+            if (customParams.get("nckd_viewTypeFilter") != null) {
+                QFilter viewTypeFilter = QFilter.fromSerializedString(customParams.get("nckd_viewTypeFilter").toString());
+
+                qFilters.add(viewTypeFilter);
+            }
+
+        }
+    }
+}

+ 58 - 38
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/PayBigCategoryFormPlugin.java

@@ -1,20 +1,20 @@
 package nckd.jimin.jyyy.fi.plugin.form;
 
+import com.kingdee.util.StringUtils;
 import kd.bos.bill.BillOperationStatus;
 import kd.bos.bill.BillShowParameter;
 import kd.bos.bill.OperationStatus;
 import kd.bos.form.ShowType;
 import kd.bos.form.control.Control;
-import kd.bos.form.control.Image;
 import kd.bos.form.control.events.ItemClickEvent;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
-import java.util.Arrays;
-import java.util.EventObject;
-import java.util.List;
+import nckd.base.helper.CommonHelperUtils;
+
+import java.util.*;
 
 /**
  * 插件说明:表单插件
@@ -24,19 +24,35 @@ import java.util.List;
  */
 public class PayBigCategoryFormPlugin extends AbstractFormPlugin {
     private static final Log logger = LogFactory.getLog(PayBigCategoryFormPlugin.class);
-    private static final List<String> operatorKeys = Arrays.asList(
-            "nckd_imageap5", "nckd_imageap51"
-    );
+    private static Map<String, String> mapEntity = null;
+
+    private static Map<String, String> mapFilter = null;
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+
+        getBtnImgValues();
+    }
+
+    private void getBtnImgValues(){
+        mapEntity = CommonHelperUtils.getCommonParams("fi-paycategoryentity");
+        mapFilter = CommonHelperUtils.getCommonParams("fi-paycategoryfilter");
+    }
+
 
-    private static final List<String> neetDefaultFilterKeys = Arrays.asList(
-            ""
-    );
 
     @Override
     public void registerListener(EventObject e) {
         super.registerListener(e);
 
-        this.addClickListeners(operatorKeys.toArray(new String[]{}));
+        List<String> btnImages = new ArrayList<>();
+
+        mapEntity.forEach((key, value) -> btnImages.add(key));
+
+        this.addClickListeners(btnImages.toArray(new String[]{}));
+//        Image image1 = this.getControl("nckd_imageap5");
+//        image1.addClickListener(this);
     }
 
     @Override
@@ -46,24 +62,29 @@ public class PayBigCategoryFormPlugin extends AbstractFormPlugin {
         String imageKey = source.getKey();
 
         //图片按钮
-        if(operatorKeys.contains(imageKey)){
-            String formId = getFormId(imageKey);
-            BillShowParameter parameter = new BillShowParameter();
+        if(mapEntity != null && mapEntity.containsKey(imageKey)){
+            String formId = mapEntity.get(imageKey);
+            if(!StringUtils.isEmpty(formId)){
+                BillShowParameter parameter = new BillShowParameter();
 
-            parameter.setFormId(formId);
-            parameter.setBillStatus(BillOperationStatus.ADDNEW);
-            parameter.setStatus(OperationStatus.ADDNEW);
+                parameter.setFormId(formId);
+                parameter.setBillStatus(BillOperationStatus.ADDNEW);
+                parameter.setStatus(OperationStatus.ADDNEW);
 
-            if(neetDefaultFilterKeys.contains(imageKey)) {
-                QFilter defaultFilter = getDefaultQFilter(imageKey);
-                parameter.setCustomParam("defaultFilter", defaultFilter);
-            }
+                if(mapFilter != null && mapFilter.containsKey(imageKey)) {
+                    QFilter viewTypeQFilter = getViewTypeQFilter(imageKey);
 
-            parameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
+                    //费用大类过滤
+                    if(viewTypeQFilter != null) {
+                        parameter.setCustomParam("nckd_viewTypeFilter", viewTypeQFilter.toSerializedString());
+                    }
+                }
 
-            this.getView().showForm(parameter);
-        }
+                parameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
 
+                this.getView().showForm(parameter);
+            }
+        }
     }
 
     @Override
@@ -74,23 +95,22 @@ public class PayBigCategoryFormPlugin extends AbstractFormPlugin {
     public String getFormId(String openType){
         String formId = "";
 
-        switch(openType){
-            case "nckd_imageap5":
-                //出差申请单
-                formId = "er_tripreqbill";
-                break;
-            case "nckd_imageap51":
-                //差旅报销单
-                formId = "er_tripreimbursebill";
-                break;
-        }
-
         return formId;
     }
 
-    public QFilter getDefaultQFilter(String openType){
-        QFilter qFilter = new QFilter("enbale", QCP.equals, "1");
+    public QFilter getViewTypeQFilter(String openType){
+        if(mapFilter == null){
+            return null;
+        }
+
+        String filterValue = mapFilter.get(openType);
+        if(StringUtils.isEmpty(filterValue)) {
+            return null;
+        }
+        String[] typeStrings = filterValue.split(",");
+
+        QFilter filer = new QFilter("nckd_payviewtype.number", QCP.in, typeStrings);
 
-        return qFilter;
+        return filer;
     }
 }

+ 50 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/PublicReimburseBillFormPlugin.java

@@ -0,0 +1,50 @@
+package nckd.jimin.jyyy.fi.plugin.form;
+
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.list.ListFilterParameter;
+import kd.bos.list.ListShowParameter;
+import kd.bos.orm.query.QFilter;
+
+import java.util.EventObject;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 单据标识:对公报销单(nckd_er_publicreimbur_ext)
+ * @author wanghaiwu_kd
+ * @date 2025/04/28
+ */
+public class PublicReimburseBillFormPlugin extends AbstractBillPlugIn implements BeforeF7SelectListener {
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+
+        BasedataEdit expenseitemF7 = (BasedataEdit) this.getControl("expenseitem");
+        expenseitemF7.addBeforeF7SelectListener(this);
+    }
+
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent evt) {
+        String property = evt.getProperty().getName();
+        String entityId = ((BasedataProp) evt.getProperty()).getBaseEntityId();
+        int curRowIndex = evt.getRow();
+
+        if ("expenseitem".equals(property)) {
+            ListShowParameter showParameter = (ListShowParameter) evt.getFormShowParameter();
+            ListFilterParameter filterParam = showParameter.getListFilterParameter();
+            List<QFilter> qFilters = filterParam.getQFilters();
+
+            Map<String, Object> customParams = this.getView().getFormShowParameter().getCustomParams();
+            if (customParams.get("nckd_viewTypeFilter") != null) {
+                QFilter viewTypeFilter = QFilter.fromSerializedString(customParams.get("nckd_viewTypeFilter").toString());
+
+                qFilters.add(viewTypeFilter);
+            }
+
+        }
+    }
+}

+ 49 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/form/TripReqMobFormPlugin.java

@@ -0,0 +1,49 @@
+package nckd.jimin.jyyy.fi.plugin.form;
+
+import kd.bos.bill.AbstractMobBillPlugIn;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.IFormView;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import java.util.Date;
+
+/**
+ * 出差申请移动端添加行程
+ * 表单标识:添加行程(nckd_er_tripreqsectio_ext)
+ * @author wanghaiwu_kd
+ *
+ */
+public class TripReqMobFormPlugin extends AbstractMobBillPlugIn {
+    private static final Log log = LogFactory.getLog(TripReqMobFormPlugin.class);
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+
+        switch (e.getProperty().getName()) {
+            case "nckd_startdatetime":
+                setStandardDateFieldValue("nckd_startdatetime", "startdate");
+                break;
+            case "nckd_enddatetime":
+                setStandardDateFieldValue("nckd_enddatetime", "enddate");
+                break;
+        }
+
+    }
+
+    /**
+     * 根据二开的开始时间、结束时间设置标准的开始日期、结束日期的字段值
+     */
+    public void setStandardDateFieldValue(String fieldName, String standardFieldName){
+        if(this.getModel().getValue(fieldName) == null){
+            this.getModel().setValue("standardFieldName", null);
+            return;
+        }
+
+        Date dateValue = (Date) this.getModel().getValue(fieldName);
+
+        this.getModel().setValue(standardFieldName, dateValue);
+//        IFormView parentView = this.getView().getParentView();
+//        parentView.updateView(standardFieldName);
+    }
+}

+ 92 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/operate/DailyVehicleBillSubmitOpPlugin.java

@@ -0,0 +1,92 @@
+package nckd.jimin.jyyy.fi.plugin.operate;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
+import kd.bos.entity.plugin.args.BeforeOperationArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import nckd.jimin.jyyy.fi.common.FinanceCommonUtils;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 表单标识:外办单(用车申请单nckd_er_dailyvehicleb_ext)
+ * @author wanghaiwu_kd
+ * @date 2025/04/29
+ */
+public class DailyVehicleBillSubmitOpPlugin extends AbstractOperationServicePlugIn {
+    private static final Log logger = LogFactory.getLog(DailyVehicleBillSubmitOpPlugin.class);
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+
+        List<String> fieldKeys = e.getFieldKeys();
+
+        fieldKeys.add("applier");
+        fieldKeys.add("startdate");
+        fieldKeys.add("enddate");
+    }
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+
+        e.addValidator(new AbstractValidator() {
+            @Override
+            public void validate() {
+                ExtendedDataEntity[] dataEntitys = this.getDataEntities();
+                for (ExtendedDataEntity dataEntity : dataEntitys) {
+                    if(dataEntity == null){
+                        continue;
+                    }
+                    DynamicObject vehicleReqBillInfo = dataEntity.getDataEntity();
+
+                    Date startDate = vehicleReqBillInfo.getDate("startdate");
+                    Date endDate = vehicleReqBillInfo.getDate("enddate");
+
+                    if(startDate == null || endDate == null){
+                        this.addErrorMessage(dataEntity, "开始时间、结束时间不能为空!");
+                    }
+
+                    Long billId = vehicleReqBillInfo.getLong("id");
+                    Long userId = vehicleReqBillInfo.getDynamicObject("applier").getLong("id");
+
+                    String checkMsg = FinanceCommonUtils.checkDateIsExists(billId, userId, startDate, endDate);
+
+                    if(checkMsg.length() > 0) {
+                        this.addErrorMessage(dataEntity, "存在开始时间、结束时间重叠的单据!" + checkMsg);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
+        super.beforeExecuteOperationTransaction(e);
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        super.beginOperationTransaction(e);
+    }
+
+    @Override
+    public void endOperationTransaction(EndOperationTransactionArgs e) {
+        super.endOperationTransaction(e);
+    }
+
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+        super.afterExecuteOperationTransaction(e);
+    }
+}

+ 99 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/plugin/operate/TripReqBillSubmitOpPlugin.java

@@ -0,0 +1,99 @@
+package nckd.jimin.jyyy.fi.plugin.operate;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
+import kd.bos.entity.plugin.args.BeforeOperationArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import java.util.Date;
+import java.util.List;
+
+import nckd.jimin.jyyy.fi.common.FinanceCommonUtils;
+
+/**
+ * 表单标识:出差申请单(nckd_er_tripreqbill_ext)
+ * @author wanghaiwu_kd
+ * @date 2025/04/29
+ */
+public class TripReqBillSubmitOpPlugin extends AbstractOperationServicePlugIn {
+    private static final Log logger = LogFactory.getLog(TripReqBillSubmitOpPlugin.class);
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+
+        List<String> fieldKeys = e.getFieldKeys();
+
+//        fieldKeys.add("tripentry");
+        fieldKeys.add("applier");
+        fieldKeys.add("tripentry.startdate");
+        fieldKeys.add("tripentry.enddate");
+    }
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+
+        e.addValidator(new AbstractValidator() {
+            @Override
+            public void validate() {
+                ExtendedDataEntity[] dataEntitys = this.getDataEntities();
+                for (ExtendedDataEntity dataEntity : dataEntitys) {
+                    if(dataEntity == null){
+                        continue;
+                    }
+                    DynamicObject tripReqInfo = dataEntity.getDataEntity();
+
+                    DynamicObjectCollection tripentry = tripReqInfo.getDynamicObjectCollection("tripentry");
+
+                    for(DynamicObject entry : tripentry){
+                        Date startDate = entry.getDate("startdate");
+                        Date endDate = entry.getDate("enddate");
+
+                        if(startDate == null || endDate == null){
+                            this.addErrorMessage(dataEntity, "开始时间、结束时间不能为空!");
+                            continue;
+                        }
+
+                        Long billId = tripReqInfo.getLong("id");
+                        Long userId = tripReqInfo.getDynamicObject("applier").getLong("id");
+
+                        String checkMsg = FinanceCommonUtils.checkDateIsExists(billId, userId, startDate, endDate);
+
+                        if(checkMsg.length() > 0) {
+                            this.addErrorMessage(dataEntity, "存在开始时间、结束时间重叠的单据!" + checkMsg);
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
+        super.beforeExecuteOperationTransaction(e);
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        super.beginOperationTransaction(e);
+    }
+
+    @Override
+    public void endOperationTransaction(EndOperationTransactionArgs e) {
+        super.endOperationTransaction(e);
+    }
+
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+        super.afterExecuteOperationTransaction(e);
+    }
+}

+ 110 - 57
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/AttachmentFileUtil.java

@@ -3,19 +3,24 @@ package nckd.jimin.jyyy.fi.webapi;
 import kd.bos.cache.CacheFactory;
 import kd.bos.cache.TempFileCache;
 import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.entity.MainEntityType;
 import kd.bos.fileservice.FileItem;
 import kd.bos.fileservice.FileService;
 import kd.bos.fileservice.FileServiceFactory;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
+import kd.bos.orm.ORM;
 import kd.bos.servicehelper.AttachmentServiceHelper;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.MetadataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.bos.servicehelper.user.UserServiceHelper;
 import kd.bos.util.FileNameUtils;
-import org.apache.commons.net.ftp.FTP;
-import org.apache.commons.net.ftp.FTPClient;
-import org.apache.commons.net.ftp.FTPReply;
-import nckd.jimin.jyyy.bd.common;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import nckd.base.helper.CommonHelperUtils;
 
 import java.io.*;
 import java.net.HttpURLConnection;
@@ -48,66 +53,68 @@ public class AttachmentFileUtil {
         Map<String, Object> attachItem = new HashMap<>();
         Map<String, Object> result = new HashMap<>();
         attachItem.put("name", fileName);
-        attachItem.put("uid", uid1);
+        attachItem.put("uid", getUid());
         InputStream inputStream = null;
         ByteArrayOutputStream outStream = null;
-        HttpURLConnection conn = null;
         String tempUrl = null;
         int size = 0;
-        FTPClient ftpClient = null;
+        ChannelSftp ftpClient = null;
+        Session sshSession = null;
         try {
-            ftpClient = new FTPClient();
+            JSch jsch = new JSch();
             // 连接到FTP服务器
-            Map<String, String> conf = CommonHelperUtils.getCommonParams("ftp");
-            ftpClient.connect(conf.get("IP"), Integer.parseInt(conf.get("PORT")));
-            ftpClient.login(conf.get("USER"), conf.get("PASSWD"));
-            if(!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){
-                ftpClient.disconnect();
-                return null;
-            }
-
-            // 设置文件类型为二进制
-            ftpClient.type(FTP.BINARY_FILE_TYPE);
-            ftpClient.enterLocalPassiveMode();  // 切换到被动模式
-            fileUrl = encode(fileUrl,"UTF-8");
-            logger.info("fileUrl:" + fileUrl);
-            String dir = ftpClient.printWorkingDirectory();
-            System.out.println(dir);
-            //ftpClient.changeWorkingDirectory("Files/CMB");
-            System.out.println(ftpClient.printWorkingDirectory());
-            //fileUrl = dir + fileUrl;
-
-            inputStream = ftpClient.retrieveFileStream(fileUrl);
-            logger.info("inputStream -- size:"+inputStream.available());
+            Map<String, String> conf = CommonHelperUtils.getCommonParams("FTP");
+            String loginName = conf.get("USER");
+            String loginPassword = conf.get("PASSWD");
+            String server = conf.get("IP");
+            Integer port = Integer.parseInt(conf.get("PORT"));
+            logger.info("FTP:"+loginName+server+conf.get("PORT"));
+            ChannelSftp.LsEntry isEntity = null;
+            // 获取sshSession
+            sshSession = jsch.getSession(loginName, server, port);
+            // 添加s密码
+            sshSession.setPassword(loginPassword);
+            Properties sshConfig = new Properties();
+            sshConfig.put("StrictHostKeyChecking", "no");
+            sshSession.setConfig(sshConfig);
+            // 开启sshSession链接
+            sshSession.connect();
+            // 获取sftp通道
+            ftpClient = (ChannelSftp) sshSession.openChannel("sftp");
+            // 开启
+            ftpClient.connect();
+
+            inputStream = ftpClient.get(fileUrl);
+            logger.info("FTP inputStream -- size:"+inputStream.available());
             System.out.println("inputStream:"+inputStream);
 
-            outStream = new ByteArrayOutputStream();
-            byte[] buffer = new byte[1024];
-            int len = 0;
-            while( (len = inputStream.read(buffer)) != -1 ){
-                outStream.write(buffer, 0, len);
-            }
-            byte[] bt =  outStream.toByteArray();
+            // outStream = new ByteArrayOutputStream();
+            // byte[] buffer = new byte[1024];
+            // int len = 0;
+            // while( (len = inputStream.read(buffer)) != -1 ){
+            //     outStream.write(buffer, 0, len);
+            // }
+            // byte[] bt =  outStream.toByteArray();
 
-            if(null != bt && bt.length > 0){
-                DecimalFormat df = new DecimalFormat("#");
-                size = Integer.parseInt(df.format((double) bt.length));
+            // if(null != bt && bt.length > 0){
+            //     DecimalFormat df = new DecimalFormat("#");
+            //     size = Integer.parseInt(df.format((double) bt.length));
 
-                System.out.println("文件大小=:" + size);
-            }else{
-                System.out.println("没有从该连接获得内容");
-            }
+            //     System.out.println("文件大小=:" + size);
+            // }else{
+            //     System.out.println("没有从该连接获得内容");
+            // }
 
-            attachItem.put("size",  size);
+            // attachItem.put("size",  size);
 //            苍穹自带
             TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
             tempUrl = cache.saveAsFullUrl((String) attachItem.get("name"), inputStream, 1600);
-            logger.info("tempUrl -- inputStream -- size:" + CacheFactory.getCommonCacheFactory().getTempFileCache().getInputStream(tempUrl).available());
+            logger.info("FTP tempUrl -- inputStream -- size:" + CacheFactory.getCommonCacheFactory().getTempFileCache().getInputStream(tempUrl).available());
             System.out.println(":tempUrl"+tempUrl);
         } catch (Exception e) {
-            logger.info("附件上传失败,堆栈信息:",e);
+            logger.info("FTP 附件上传失败,堆栈信息:",e.getMessage());
             result.put("isSuccess", "false");
-            result.put("msg", "转文件流异常"+e);
+            result.put("msg", "转文件流异常"+e.getMessage());
             return result;
         } finally {
             try {
@@ -117,9 +124,8 @@ public class AttachmentFileUtil {
                 if(outStream !=null){
                     outStream.close();
                 }
-                if (ftpClient.isConnected()) {
-                    ftpClient.logout();
-                    ftpClient.disconnect();
+                if(ftpClient.getSession().isConnected()){
+                    ftpClient.getSession().disconnect();
                 }
             } catch (Exception e) {
                 logger.info("附件上传失败,堆栈信息01:",e.getMessage());
@@ -144,28 +150,27 @@ public class AttachmentFileUtil {
             String uuid = UUID.randomUUID().toString().replace("-", "");
             String pathParam = FileNameUtils.getAttachmentFileName(requestContext.getTenantId(),
                     requestContext.getAccountId(), uuid, fileName);
-            System.out.println("pathParam"+pathParam);
+            System.out.println("FTP pathParam"+pathParam);
 
             result.put("pathParam", pathParam);
             FileItem fileItem = new FileItem(fileName, pathParam, in);
 
             //从临时上传至 文件服务器
             String downUrl =service.upload(fileItem);
-            logger.info("downUrl:"+downUrl);
+            logger.info("FTP downUrl:"+downUrl);
             System.out.println("downUrl:"+downUrl);
 
             attachItem.put("url", actUrl);
+            result.put("url", actUrl);
             attachments.add(attachItem);
             //绑定单据
             AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
 
         }catch(Exception e1){
-            logger.info("附件上传失败,堆栈信息e1:",e1);
+            logger.info("FTP 附件上传失败,堆栈信息e1:",e1.getMessage());
             result.put("isSuccess", "false");
-            result.put("msg", "上传服务器异常:"+e1);
+            result.put("msg", "上传服务器异常:"+e1.getMessage());
             return result;
-        }finally {
-
         }
         result.put("isSuccess", "true");
         result.put("msg", "附件上传成功");
@@ -203,6 +208,7 @@ public class AttachmentFileUtil {
             attachItem.put("url", actUrl);
 
             attachments.add(attachItem);
+            attToAttachmentFile(attachItem);
             //        绑定单据
             AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
         }catch (Exception e){
@@ -212,6 +218,44 @@ public class AttachmentFileUtil {
         return "ss";
     }
 
+    
+    /**
+     * 将给定的附件属性映射转换为附件实体对象
+     * 此方法主要用于将包含附件信息的映射转换为系统中的附件文件对象,包括设置基本属性、唯一标识、状态以及关联的元数据
+     *
+     * @param attachment 包含附件信息的映射,如名称、大小、类型等
+     * @return DynamicObject 表示附件文件的对象,包含完整的附件属性
+     */
+    public static DynamicObject attToAttachmentFile(Map<String, Object> attachment) {
+
+        //创建一条基础资料数据-附件字段
+        DynamicObject attObj = BusinessDataServiceHelper.newDynamicObject("bd_attachment");
+        attObj.set("name", attachment.get("name"));
+        attObj.set("size", 0);
+        attObj.set("uid", attachment.get("uid"));
+        attObj.set("url", attachment.get("uid"));
+        String fileType = attachment.get("name").toString();
+        if (fileType.contains(".")) {
+            fileType = fileType.substring(fileType.lastIndexOf(".") + 1);
+        }
+        attObj.set("type", fileType);
+        //tempfile=1表示持久化附件对象
+        attObj.set("tempfile", 1);
+        ORM orm = ORM.create();
+        long id = orm.genLongId("bd_attachment");
+        attObj.set("id", id);
+        attObj.set("pageid", "");
+        attObj.set("number", UUID.randomUUID().toString());
+        attObj.set("status", "B");
+        Date now = new Date();
+        attObj.set("modifytime", now.getTime());
+        attObj.set("createtime", now.getTime());
+        attObj.set("creator", UserServiceHelper.getCurrentUserId());
+        SaveServiceHelper.save(new DynamicObject[]{attObj});
+
+        return attObj;
+    }
+
     /**
      * 根据地址获得数据的字节流并转换成大小
      * @param strUrl 网络连接地址
@@ -306,6 +350,15 @@ public class AttachmentFileUtil {
         return b.toString();
     }
 
+    public static StringBuilder getUid() {
+        StringBuilder uid = new StringBuilder("rc-upload-");
+        uid.append((new Date()).getTime());
+        uid.append("-");
+        int index = (int) (1.0D + Math.random() * 10.0D);
+        uid.append(index);
+        return uid;
+    }
+
     public static void downloadFile(String fileUrl, String saveDir) throws IOException {
         URL url = new URL(fileUrl);
         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@@ -350,4 +403,4 @@ public class AttachmentFileUtil {
         connection.disconnect();
     }
 
-}
+}

+ 299 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/ContractbillApiPlugin.java

@@ -0,0 +1,299 @@
+package nckd.jimin.jyyy.fi.webapi;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.cache.CacheFactory;
+import kd.bos.cache.TempFileCache;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.BillEntityType;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.id.ID;
+import kd.bos.openapi.common.custom.annotation.ApiController;
+import kd.bos.openapi.common.custom.annotation.ApiMapping;
+import kd.bos.openapi.common.custom.annotation.ApiParam;
+import kd.bos.openapi.common.custom.annotation.ApiPostMapping;
+import kd.bos.openapi.common.result.CustomApiResult;
+import kd.bos.openapi.common.result.OpenApiFile;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.AttachmentServiceHelper;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 提供给合同系统的新增/更新接口,对应星瀚合同台账单er_contractbill
+ * api编码:contract/uploadFileTemp (不用,用标品的uploadFile.do)
+ * api编码:contract/saveContract
+ *
+ * @author chengchaohua
+ * @since 2025/05/06
+ */
+@ApiController(value = "hetong", desc = "合同台账单接口")
+@ApiMapping("/contract")
+public class ContractbillApiPlugin implements Serializable {
+    private static final Logger log = LoggerFactory.getLogger(ContractbillApiPlugin.class);
+
+    @ApiPostMapping("/uploadFileTemp")
+    public CustomApiResult<Map<String,Object>> uploadFileTemp(@ApiParam(value = "文件流",required = true) OpenApiFile file) {
+        byte[] fileData = file.getFileData();
+        String fileName = file.getFileName();
+        Map<String,Object> map = new HashMap<>();
+        TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
+        String tempUrl = cache.saveAsFullUrl(fileName, fileData,3600);
+        CustomApiResult<Map<String,Object>> customApiResult = new CustomApiResult<>();
+        map.put("tempurl",tempUrl);
+        map.put("fileName",fileName);
+        map.put("size",file.getFileData().length);
+        customApiResult.setData(map);
+        return customApiResult;
+    }
+
+
+    @ApiPostMapping(value = "/saveContract", desc = "保存合同台账单")
+    public CustomApiResult<Boolean> saveContract(@ApiParam("单据信息") Map<String, Object> billData
+            ,@ApiParam("附件面板") Map<String, List<Map<String,Object>>> allAttachmentsData
+    ) {
+        // 接口返回结果
+        CustomApiResult<Boolean> result = new CustomApiResult<>();
+        // 0)数据校验
+        if(!"1".equals(billData.get("fcontracttype"))) { // 合同类型
+            result.setMessage("合同类型不是1,星瀚不接收");
+            return result;
+        }
+
+        String fapplierid = (String)billData.get("fapplierid");// fapplierid 经办人:员工编码_名称
+        String gonghao = fapplierid.split("_")[0]; // 提取员工工号
+        DynamicObject applicatuser = BusinessDataServiceHelper.loadSingle("bos_user","id,name,number",new QFilter[]{new QFilter("number",QCP.equals,gonghao)});
+
+        String fcontractcode = (String)billData.get("fcontractcode"); // 合同号(原始)
+        String fcontractcodenew = (String)billData.get("fcontractcodenew"); // 合同号(最新)
+        String fcontractname = (String)billData.get("fcontractname"); // 合同名称
+        String fdescription = (String)billData.get("fdescription"); // 合同说明
+
+        String fbizdate = (String)billData.get("fbizdate"); // 申请日期
+        String fsigndate = (String)billData.get("fsigndate"); // 签订日期
+        String fstartdate = (String)billData.get("fstartdate"); // 起始日期
+        String fenddate = (String)billData.get("fenddate"); // 截止日期
+
+        String contractcurrency = (String)billData.get("contractcurrency"); // 币种
+
+        // 甲方纳税号
+        String fjiafangxinyongcode = (String)billData.get("fjiafangxinyongcode"); // 甲方统一社会信用代码
+
+        String fjiafangcontactperson = (String)billData.get("fjiafangcontactperson"); // 甲方联系人
+
+        // 签约方:乙方集合
+        JSONArray contractpartyAry = (JSONArray) billData.get("contractparty");
+
+        // 付款计划集合
+        JSONArray fukuanplanAry = (JSONArray) billData.get("fukuanplan");
+
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+
+        // 1)单据组装
+        String entityNumber = "er_contractbill";
+        QFilter qFilter = new QFilter("contractcode", QCP.equals,fcontractcode); // 合同号(原始)
+        DynamicObject dynamicObject = null;
+        if(QueryServiceHelper.exists(entityNumber,new QFilter[]{qFilter})){
+            // 存在
+            dynamicObject = BusinessDataServiceHelper.loadSingle(entityNumber,new QFilter[]{qFilter});
+        }else {
+            // 不存在,创建对象
+            dynamicObject = BusinessDataServiceHelper.newDynamicObject(entityNumber); // 单据标识
+            dynamicObject.set("id", ID.genLongId()); // 创建id值
+
+            dynamicObject.set("creator",applicatuser); // 创建人
+            dynamicObject.set("createtime",new Date()); // 创建时间
+        }
+        long pkid = dynamicObject.getLong("id");
+
+        BillEntityType dataEntityType = (BillEntityType) dynamicObject.getDataEntityType();
+        String appId = dataEntityType.getAppId(); // 获取单据的应用id
+
+        dynamicObject.set("billno",billData.get("billno")); // 单据编号
+        dynamicObject.set("billstatus","A"); // 单据状态, A-暂存,E-审核通过
+        //单据其他业务字段赋值
+        // 甲方:ftaxregnum 纳税识别号
+        DynamicObject company = BusinessDataServiceHelper.loadSingle("bos_org","id,name",new QFilter[]{new QFilter("ftaxregnum",QCP.equals,fjiafangxinyongcode)});
+        dynamicObject.set("company",company); // 公司
+
+        DynamicObject stdbilltype = BusinessDataServiceHelper.loadSingle("bos_billtype","id,name",new QFilter[]{new QFilter("number",QCP.equals,"er_contractbill_BT_S")});
+        dynamicObject.set("stdbilltype",stdbilltype); // 单据类型:基础资料 合同台账
+
+        dynamicObject.set("detailtype","biztype_applybill"); //(影响列表记录显示) 单据类型:biztype_applybill 合同台账 ,biztype_changebill 合同变更,biztype_stopbill 合同终止
+
+        DynamicObject contracttype = BusinessDataServiceHelper.loadSingle("pmct_conttype","id,name",new QFilter[]{new QFilter("number",QCP.equals,"FYHT")});
+        dynamicObject.set("contracttype",contracttype); // 合同类型
+        dynamicObject.set("contractcode",fcontractcode); // 合同号
+        dynamicObject.set("contractname",fcontractname); // 合同名称
+
+        dynamicObject.set("costcompany",company); // 核算组织
+        try {
+            dynamicObject.set("signdate",sdf.parse(fsigndate)); // 签订日期
+            dynamicObject.set("startdate",sdf.parse(fstartdate)); // 起始日期
+            dynamicObject.set("enddate",sdf.parse(fenddate)); // 截止日期
+//            dynamicObject.set("changedate",sdf.parse(fstartdate)); // 变更日期
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+
+        dynamicObject.set("changedate",new Date()); // 变更日期
+        dynamicObject.set("description",fdescription);  // 合同说明
+//        dynamicObject.set("nckd_is_important_contrac","true"); // 是否重要合同
+        dynamicObject.set("partbtype","bd_supplier"); // 乙方类型(隐藏字段)
+
+        dynamicObject.set("iscurrency",true); // 默认设置多币种
+
+        DynamicObject bizhong = BusinessDataServiceHelper.loadSingle("bd_currency","id,name",new QFilter[]{new QFilter("number",QCP.equals,contractcurrency)});
+        dynamicObject.set("contractcurrency",bizhong); // 币种
+
+        DynamicObject CNY = BusinessDataServiceHelper.loadSingle("bd_currency","id,name",new QFilter[]{new QFilter("number",QCP.equals,"CNY")});
+
+        // orgcur 原币,cur 目标币(指定人民币),effectdate 生效日期
+        DynamicObject[] huilvAry = BusinessDataServiceHelper.load("bd_exrate_tree","id,orgcur,cur,excval,effectdate",
+                new QFilter[]{new QFilter("orgcur",QCP.equals,bizhong.getLong("id"))
+                        .and("cur",QCP.equals,CNY.getLong("id"))
+                        .and("enable",QCP.equals,CNY.getLong("id"))},"effectdate desc");
+
+        BigDecimal huilv = new BigDecimal(0);
+        if(huilvAry.length > 0) {
+            huilv = huilvAry[0].getBigDecimal("excval"); // 直接汇率值
+        }
+        dynamicObject.set("changerate",huilv); // 汇率(需根据币别查询最新汇率)
+
+        dynamicObject.set("org",company);// 经办人部门
+        dynamicObject.set("costdept",company);// 费用承担部门
+        dynamicObject.set("applier",applicatuser); // 经办人
+        dynamicObject.set("modifier",applicatuser); // 修改人
+        dynamicObject.set("modifytime",new Date()); // 修改时间
+
+        // 1.2)签约方分录
+        DynamicObjectCollection newColl = dynamicObject.getDynamicObjectCollection("contractpartyentry"); // 单据体标识
+        newColl.clear();
+        // 甲方
+        DynamicObject newEntry = new DynamicObject(newColl.getDynamicObjectType());
+        newEntry.set("signcontract", "0"); // 签约方,甲方-0,乙方-1,其他方-2
+        newEntry.set("partytype", "bos_org"); // 签约方类型:bos_org 公司,bd_supplier 供应商,bd_customer 客户
+        newEntry.set("contractparty", company); // 签约方名称
+        newEntry.set("contactperson", fjiafangcontactperson); // 联系人,文本
+        newColl.add(newEntry);
+        // 乙方
+        for (Object item : contractpartyAry) {
+            JSONObject jsb = (JSONObject)item;
+            String fxinyongcode = jsb.getString("fxinyongcode"); // 统一社会信用代码
+            String fcontactperson = jsb.getString("fcontactperson"); // 乙方联系人
+            DynamicObject newEntry2 = new DynamicObject(newColl.getDynamicObjectType());
+            newEntry2.set("signcontract", "1"); // 签约方,甲方-0,乙方-1,其他方-2
+            newEntry2.set("partytype", "bd_supplier"); // 签约方类型:bos_org 公司,bd_supplier 供应商,bd_customer 客户
+            DynamicObject supplier = BusinessDataServiceHelper.loadSingle("bd_supplier","id,name",new QFilter[]{new QFilter("societycreditcode",QCP.equals,fxinyongcode)});
+            newEntry2.set("contractparty", supplier); // 签约方名称
+            newEntry2.set("contactperson", fcontactperson); // 联系人,文本
+            newColl.add(newEntry2);
+        }
+        dynamicObject.set("contractpartyentry", newColl); // 签约方分录
+
+        // 1.3)付款计划分录
+        DynamicObjectCollection plannewColl = dynamicObject.getDynamicObjectCollection("expenseentryentity"); // 单据体标识
+        plannewColl.clear();
+        BigDecimal hetongjinetotalfist = new BigDecimal(0); // 合同总额(初始)
+        for (Object item : fukuanplanAry) {
+            JSONObject jsb = (JSONObject)item;
+            String fpayterms = jsb.getString("fpayterms"); // 付款条件
+            BigDecimal fexpapplyamount = jsb.getBigDecimal("fexpapplyamount"); // 含税金额
+            String std_project = jsb.getString("fprojectid"); // 项目
+
+            DynamicObject newEntry3 = new DynamicObject(plannewColl.getDynamicObjectType());
+            DynamicObject fukuantype = BusinessDataServiceHelper.loadSingle("cas_paymentbilltype","id,name",new QFilter[]{new QFilter("number",QCP.equals,"201")});
+            newEntry3.set("paymenttypeid",fukuantype); // 付款类型
+            newEntry3.set("payterms",fpayterms); // 付款条件
+            try {
+                newEntry3.set("happendate",sdf.parse("2999-12-31")); // 预计付款日期
+            } catch (ParseException e) {
+                throw new RuntimeException(e);
+            }
+            newEntry3.set("entrycostdept",company); // 费用承担部门
+            newEntry3.set("entrycostcompany",company); // 费用承担公司
+            // 固定值
+            DynamicObject feiyongproject = BusinessDataServiceHelper.loadSingle("er_expenseitemedit","id,name",new QFilter[]{new QFilter("number",QCP.equals,"FYXM0001")});
+            newEntry3.set("expenseitem",feiyongproject); // 费用项目
+            newEntry3.set("expenseamount",fexpapplyamount); // 含税金额
+            newEntry3.set("orientryamount",fexpapplyamount); // 不含税金额
+            hetongjinetotalfist = hetongjinetotalfist.add(fexpapplyamount);
+
+            newEntry3.set("exchangerate",huilv); // 汇率
+
+            DynamicObject project = BusinessDataServiceHelper.loadSingle("bd_project","id,name",new QFilter[]{new QFilter("number",QCP.equals,std_project)});
+            newEntry3.set("std_project",project); // 项目
+
+            newEntry3.set("entrycurrency",bizhong); // 分录币别(和头表一致)
+
+            plannewColl.add(newEntry3);
+        }
+        dynamicObject.set("expenseentryentity", plannewColl); // 付款计划分录
+
+        dynamicObject.set("contractamount", hetongjinetotalfist); // 合同总额(初始)
+        dynamicObject.set("oriapplyamount", hetongjinetotalfist); // 合同总额(变更后)
+        dynamicObject.set("originalamount", hetongjinetotalfist); // 合同总额(不含税)
+        dynamicObject.set("orinotpayamount", hetongjinetotalfist); // 未付金额
+
+        // 先单据保存
+        OperationResult opResult = SaveServiceHelper.saveOperate(entityNumber, new DynamicObject[]{dynamicObject}, OperateOption.create());
+
+        // 2)删除历史附件
+       List<Map<String, Object>> atts = AttachmentServiceHelper.getAttachments(entityNumber, dynamicObject.getPkValue(),"attachmentpanel");
+        if (atts.size() > 0) {
+            // 获取全部附件
+            Iterator<Map<String, Object>> iterator = atts.iterator();
+            // 遍历所有附件
+            while (iterator.hasNext()) {
+                Map map2 = iterator.next();
+                String formId = map2.get("entityNum").toString();
+                Object pkId = map2.get("billPkId"); // 单据id
+                Object fileUid = map2.get("uid");
+                //从数据库中删除上一次保存的附件
+                AttachmentServiceHelper.remove(formId, pkId, fileUid);
+            }
+        }
+
+        // 3)附件保存入库
+        Map<String, Object> attachmentInfos = new HashMap<>();
+        for (Map.Entry<String, List<Map<String,Object>>> entry : allAttachmentsData.entrySet()) {
+            if ("attachmentpanel".equals(entry.getKey())) {
+                // 取‘附件面板’的附件集合
+                List<Map<String, Object>> fileList = entry.getValue();
+                List<Map<String, Object>> attachments = new ArrayList<>();
+                for (int i= 0; i < fileList.size(); i++) {
+                    Map<String, Object> map = fileList.get(i);
+                    StringBuffer uid = new StringBuffer();
+                    uid.append("rc-upload-").append(new Date().getTime()).append("-");
+                    Map<String,Object> attachmentInfo = new HashMap<>();
+                    attachmentInfo.put("entityNumber", entityNumber);
+                    attachmentInfo.put("name", map.get("fileName"));
+                    attachmentInfo.put("url", map.get("tempurl"));
+                    attachmentInfo.put("size", map.get("size"));
+                    attachmentInfo.put("status", map.get("status"));
+                    attachmentInfo.put("uid", uid.toString() + i);
+                    attachments.add(attachmentInfo);
+                }
+                attachmentInfos.put("attachmentpanel",attachments);
+            }
+        }
+
+        AttachmentServiceHelper.saveTempAttachments(entityNumber, pkid, appId, attachmentInfos);
+
+        result.setMessage("成功");
+        return result;
+    }
+
+}

+ 8 - 2
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/TransDetailApiPlugin.java

@@ -20,6 +20,7 @@ import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.operation.DeleteServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.data.rsa.helper.CodeRuleHelper;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
@@ -317,8 +318,9 @@ public class TransDetailApiPlugin implements Serializable {
             long Id = DB.genLongId("t_bei_elecreceipt");
             elecreceiptDyn.set("id", Id);
 
+            String billNo = CodeRuleHelper.generateNumber(BeiElecreceiptConstantInfo.ENTITYID, elecreceiptDyn, null, null);
             elecreceiptDyn.set(BeiElecreceiptConstantInfo.DETAILID, transDetail.get(BeiTransdetailConstantInfo.DETAILID));
-            elecreceiptDyn.set(BeiElecreceiptConstantInfo.BILLNO, transDetail.get(BeiTransdetailConstantInfo.BILLNO));
+            elecreceiptDyn.set(BeiElecreceiptConstantInfo.BILLNO, billNo);
             elecreceiptDyn.set(BeiElecreceiptConstantInfo.COMPANY, transDetail.get(BeiTransdetailConstantInfo.COMPANY));
             elecreceiptDyn.set(BeiElecreceiptConstantInfo.ACCOUNTBANK, transDetail.get(BeiTransdetailConstantInfo.ACCOUNTBANK));
             elecreceiptDyn.set(BeiElecreceiptConstantInfo.CURRENCY, transDetail.get(BeiTransdetailConstantInfo.CURRENCY));
@@ -362,7 +364,7 @@ public class TransDetailApiPlugin implements Serializable {
         if(EmptyUtils.isNotEmpty(electricAddress)){
             String address = electricAddress;
             String filename = extractFilename(address);
-            elecreceiptDyn.set(BeiElecreceiptConstantInfo.UPLOADFILENAME,filename);//文件名称
+            //elecreceiptDyn.set(BeiElecreceiptConstantInfo.UPLOADFILENAME,filename);//文件名称
 
             address=address.split("Files")[1];
             address=address.replace("\\", "/");
@@ -383,6 +385,10 @@ public class TransDetailApiPlugin implements Serializable {
                 if(StringUtils.isNotEmpty(pathParam)){
                     elecreceiptDyn.set(BeiElecreceiptConstantInfo.FILEPATH, pathParam);
                 }
+                String url = reMap.get("url").toString();
+                if(StringUtils.isNotEmpty(url)){
+                    elecreceiptDyn.set(BeiElecreceiptConstantInfo.UPLOADFILENAME, url);
+                }
             }
             elecreceiptDyn.set(BeiElecreceiptConstantInfo.FILEFLAG, "1"); // 是否已上传
         }

+ 91 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/opplugin/web/position/AutoEndPartTimeTask.java

@@ -0,0 +1,91 @@
+package nckd.jimin.jyyy.hr.hrmp.hbpm.opplugin.web.position;
+
+import kd.bos.algo.DataSet;
+import kd.bos.algo.Row;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.db.DB;
+import kd.bos.db.DBRoute;
+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.hr.hdm.business.domain.parttime.ParttimeServiceHelper;
+import kd.hr.hdm.business.domain.transfer.service.external.PersonExternalService;
+import kd.sdk.plugin.Plugin;
+import nckd.jimin.jyyy.hr.wtc.wtabm.opplugin.web.vaapply.VaApplyBillUtil;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 自动取消兼岗调度插件
+ * Tyx 2025-05-06
+ * 查询 同时存在主职和兼职的岗位,取消该岗位的所有兼职,需排除长假场景(长假员工的基本信息中的员工状态为长假,但实际主职岗位不发生变化,这种场景视作该岗位上没有主职
+ */
+public class AutoEndPartTimeTask extends AbstractTask implements Plugin {
+    private static final Log log = LogFactory.getLog(AutoEndPartTimeTask.class);
+    private static String ermanFile_entity = "hspm_ermanfile";
+
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        log.info(" -------- 自动取消兼岗开始 -------- ");
+        StringBuilder sb = new StringBuilder();
+        sb.append(" /*dialect*/ select a.fpositionid,max(a.fisprimary) maxp,min(a.fisprimary) minp \n");
+        sb.append(" from t_hrpi_empposorgrel a \n");
+        sb.append(" left join t_hrpi_pernontsprop b on a.fpersonid = b.fpersonid and b.fiscurrentversion = '1' \n");
+        sb.append(" left join t_hbss_laborrelstatus c on c.fid = b.fk_nckd_ygzt \n");
+        sb.append(" where a.fiscurrentversion = '1' \n");
+        sb.append("   and a.fbusinessstatus = '1' \n");
+        sb.append("   and (c.fnumber <> '9010_S' or c.fnumber is null) \n");
+        sb.append(" group by a.fpositionid");
+        log.info(" -------- sql : " +sb.toString()+ " -------- ");
+        DataSet dataSet = DB.queryDataSet(this.getClass().getName(), DBRoute.of("hr"), sb.toString());
+
+        List<Long> positionIds = new ArrayList<Long>();
+        while(dataSet.hasNext()) {
+            Row rowData = dataSet.next();
+            //取同时有兼职和主职的岗位
+            if(rowData.getInteger("maxp") == 1 && rowData.getInteger("minp") == 0) {
+                positionIds.add(rowData.getLong("fpositionid"));
+            }
+        }
+
+        //取出岗位下所有兼职
+        if(positionIds.size() > 0) {
+            //获取档案
+            DynamicObject[] ermanFiles = VaApplyBillUtil.getErmanFilesByPosition(positionIds);
+            //转成List<Long>
+            List<Long> ermanFileIds = Arrays.stream(ermanFiles).map(dyx -> dyx.getLong("id")).collect(Collectors.toList());
+            //调用标准方法获取ermanFile
+            List<Map<String, Object>> erManFiles = PersonExternalService.getInstance().invokeGetCardFields(ermanFileIds);
+            //actionId 默认201100_S
+            QFilter filter = new QFilter("number", "=", "201100_S");
+            DynamicObject action = BusinessDataServiceHelper.loadSingle("hpfs_chgaction",new QFilter[]{filter});
+            Date partEndDate = new Date();
+            //调用标准终止兼职方法
+            log.info(" -------- begin 调用标品终止兼职方法 --------");
+            ParttimeServiceHelper.batchEndParttime(action.getLong("id"), partEndDate, erManFiles);
+            log.info(" -------- after 调用标品终止兼职方法 --------");
+        }
+
+    }
+
+    /**
+     * 组装查询兼职档案的过滤条件
+     * @param positionIds
+     * @return
+     */
+    public QFilter getQFilter(List<Long> positionIds) {
+        QFilter filter = new QFilter("depemp.iscurrentversion", QCP.equals, "1");
+        filter.and("depemp.businessstatus", QCP.equals, "1");
+        filter.and("depemp.postype.number",QCP.equals, "1020_S");
+        filter.and("depemp.position", QCP.in, positionIds);
+        filter.and("iscurrentversion", QCP.equals, "1");
+        filter.and("businessstatus", QCP.equals, "1");
+        return filter;
+    }
+}

+ 82 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/opplugin/web/position/PosEndPartTimeConfirmPlugin.java

@@ -0,0 +1,82 @@
+package nckd.jimin.jyyy.hr.hrmp.hbpm.opplugin.web.position;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.control.Button;
+import kd.bos.form.control.Control;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hdm.business.domain.parttime.ParttimeServiceHelper;
+import kd.hr.hdm.business.domain.transfer.service.external.PersonExternalService;
+import kd.sdk.plugin.Plugin;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Tyx 2025-04-29
+ * 岗位终止兼职表单插件
+ * 元数据标识:nckd_posendparttime
+ */
+public class PosEndPartTimeConfirmPlugin extends AbstractFormPlugin implements Plugin {
+
+    private static String ermanFile_entity = "hspm_ermanfile";
+    private static final Log log = LogFactory.getLog(PosEndPartTimeConfirmPlugin.class);
+    public void registerListener(EventObject eventObject) {
+        super.registerListener(eventObject);
+        Button button = (Button)this.getControl("btnok");
+        button.addClickListener(this);
+    }
+
+    @Override
+    public void click(EventObject evt) {
+        super.click(evt);
+        Control control = (Control)evt.getSource();
+        String key = control.getKey();
+        if ("btnok".equals(key)) {
+            FormShowParameter formShowParameter = this.getView().getFormShowParameter();
+            //父页面传过来的岗位ID,根据这些ID查找岗位下的兼职
+            List<Long> selectIds = (List)formShowParameter.getCustomParam("selectIds");
+            QFilter filter = getQFilter(selectIds);
+            HRBaseServiceHelper helper = HRBaseServiceHelper.create(ermanFile_entity);
+            DynamicObject[] ermanFiles = helper.query(new QFilter[]{filter});
+            if(ermanFiles.length == 0) {
+                this.getView().showMessage("岗位下不存在兼职!");
+            }
+            else {
+                //转成List<Long>
+                List<Long> ermanFileIds = Arrays.stream(ermanFiles).map(dyx -> dyx.getLong("id")).collect(Collectors.toList());
+                //调用标准方法获取ermanFile
+                List<Map<String, Object>> erManFiles = PersonExternalService.getInstance().invokeGetCardFields(ermanFileIds);
+                DynamicObject action = (DynamicObject)this.getModel().getValue("affaction");
+                Date partEndDate = (Date)this.getModel().getValue("partenddate");
+                //调用标准终止兼职方法
+                ParttimeServiceHelper.batchEndParttime(action.getLong("id"), partEndDate, erManFiles);
+                this.getView().getParentView().showSuccessNotification(ResManager.loadKDString("兼职终止成功,共终止" + ermanFileIds.size() + "条记录", "EndParttimePlugin_2", "hr-hdm-formplugin", new Object[0]));
+                this.getView().sendFormAction(this.getView().getParentView());
+                this.getView().close();
+            }
+        }
+    }
+
+    /**
+     * 组装查询兼职档案的过滤条件
+     * @param positionIds
+     * @return
+     */
+    public QFilter getQFilter(List<Long> positionIds) {
+        QFilter filter = new QFilter("depemp.iscurrentversion", QCP.equals, "1");
+        filter.and("depemp.businessstatus", QCP.equals, "1");
+        filter.and("depemp.postype.number",QCP.equals, "1020_S");
+        filter.and("depemp.position", QCP.in, positionIds);
+        filter.and("iscurrentversion", QCP.equals, "1");
+        filter.and("businessstatus", QCP.equals, "1");
+        return filter;
+    }
+
+}

+ 68 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/opplugin/web/position/PositionEndPartTimePlugin.java

@@ -0,0 +1,68 @@
+package nckd.jimin.jyyy.hr.hrmp.hbpm.opplugin.web.position;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.entity.datamodel.ListSelectedRow;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.form.CloseCallBack;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.mvc.list.ListView;
+import kd.hr.hbp.common.util.HRJSONUtils;
+import kd.hr.hbp.common.util.HRStringUtils;
+import kd.hr.hdm.business.domain.parttime.external.IParttimePersonService;
+import kd.sdk.plugin.Plugin;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Tyx 2025-04-28
+ * 根据岗位终止兼职操作插件
+ * 根据选择的岗位Id,找到这个岗位所有兼职的人事档案ID,再调标准方法终止
+ */
+public class PositionEndPartTimePlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate op = (FormOperate)args.getSource();
+        String operateKey = op.getOperateKey();
+        if (HRStringUtils.equals(operateKey, "endparttime")) {
+            ListView listView = (ListView)this.getView();
+            List<Long> selectPkIds = this.getListSelectedPkIds(listView);
+            this.showPosEndPartTimeConfirm(selectPkIds);
+            args.setCancel(true);
+        }
+    }
+
+    private List<Long> getListSelectedPkIds(ListView listView) {
+        ListSelectedRowCollection selectedRows = listView.getSelectedRows();
+        List<Long> selectPkIds = Lists.newArrayListWithExpectedSize(selectedRows.size());
+        Iterator it = selectedRows.iterator();
+
+        while(it.hasNext()) {
+            ListSelectedRow selectedRow = (ListSelectedRow)it.next();
+            Long primaryKeyValue = HRJSONUtils.getLongValOfCustomParam(selectedRow.getPrimaryKeyValue());
+            selectPkIds.add(primaryKeyValue);
+        }
+
+        return selectPkIds;
+    }
+
+    private void showPosEndPartTimeConfirm(List<Long> selectIds) {
+        FormShowParameter formShowParameter = new FormShowParameter();
+        formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+        formShowParameter.setFormId("nckd_posendparttime");
+        formShowParameter.setCustomParam("selectIds", selectIds);
+        formShowParameter.setCloseCallBack(new CloseCallBack(this, "posendparttime"));
+        this.getView().showForm(formShowParameter);
+    }
+}

+ 1 - 1
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/haos/staff/plugin/task/PositionTree.java → code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/PositionTree.java

@@ -1,4 +1,4 @@
-package nckd.jimin.jyyy.hr.haos.staff.plugin.task;
+package nckd.jimin.jyyy.hr.hrmp.hbpm.task;
 
 import java.io.Serializable;
 import java.util.ArrayList;

+ 10 - 23
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/haos/staff/plugin/task/SyncAdminOrgTask.java → code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncAdminOrgTask.java

@@ -1,4 +1,4 @@
-package nckd.jimin.jyyy.hr.haos.staff.plugin.task;
+package nckd.jimin.jyyy.hr.hrmp.hbpm.task;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -111,32 +111,18 @@ public class SyncAdminOrgTask extends AbstractTask implements Plugin {
                 buildPersonJSON(personOb, totalOrgSet, bosOrgMap);
                 //获取调用接口地址
                 String url = SyncUtil.getUrl("org_url");
-                log.info("-------- 组织同步调用url : " + url + " --------");
-                //调用接口
-                JSONObject response = SyncUtil.doPostByHttpClient(url, ob);
-                //处理返回结果
-                String status = SyncUtil.dealResponseStatus(response);
-                //记录日志
-                SyncUtil.createLog(status, startTime, endTime, ob.toJSONString(), response.toJSONString(), SyncUtil.SyncOrg);
+                SyncUtil.batchPost(url, ob, SyncUtil.SyncOrg, startTime, endTime);
+
+                //组织下级岗位同步:
                 if(posOb.getJSONArray("obj").size() > 0) {
                     url = SyncUtil.getUrl("position_url");
-                    log.info("-------- 组织同步下级岗位调用url : " + url + " --------");
-                    //调用接口
-                    response = SyncUtil.doPostByHttpClient(url, posOb);
-                    //处理返回结果
-                    status = SyncUtil.dealResponseStatus(response);
-                    //记录日志
-                    SyncUtil.createLog(status, startTime, endTime, posOb.toJSONString(), response.toJSONString(), SyncUtil.SyncOrg_Position);
+                    SyncUtil.batchPost(url, posOb, SyncUtil.SyncOrg_Position, startTime, endTime);
                 }
+
+                //组织下级员工同步:
                 if(personOb.getJSONArray("obj").size() > 0) {
                     url = SyncUtil.getUrl("person_url");
-                    log.info("-------- 组织同步下级人员调用url : " + url + " --------");
-                    //调用接口
-                    response = SyncUtil.doPostByHttpClient(url, personOb);
-                    //处理返回结果
-                    status = SyncUtil.dealResponseStatus(response);
-                    //记录日志
-                    SyncUtil.createLog(status, startTime, endTime, personOb.toJSONString(), response.toJSONString(), SyncUtil.SyncOrg_Person);
+                    SyncUtil.batchPost(url, personOb, SyncUtil.SyncOrg_Person, startTime, endTime);
                 }
             }
         } catch (ParseException e) {
@@ -166,7 +152,8 @@ public class SyncAdminOrgTask extends AbstractTask implements Plugin {
             //组织名称
             data.put("MD_DESCRIPTION", org.getString("name"));
             //上级行政组织ID 看是否有easid 有就传EASID 否则传星瀚ID
-            data.put("ADM_PARENT_NUMER", org.getString("parentorg.nckd_easid"));
+            String parent_primary_key = StringUtils.isBlank(org.getString("parentorg.nckd_easid")) ? String.valueOf(org.getLong("parentorg.id")) : org.getString("parentorg.nckd_easid");
+            data.put("ADM_PARENT_NUMER", parent_primary_key);
             //上级组织名称
             data.put("ADM_PARENT_NAME", org.getString("parentorg.name"));
             //行政组织长名称 orglongname没值 去平台那边取

+ 5 - 8
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/haos/staff/plugin/task/SyncPersonTask.java → code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncPersonTask.java

@@ -1,4 +1,4 @@
-package nckd.jimin.jyyy.hr.haos.staff.plugin.task;
+package nckd.jimin.jyyy.hr.hrmp.hbpm.task;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -58,12 +58,8 @@ public class SyncPersonTask extends AbstractTask implements Plugin {
                 SyncUtil.createLog(SyncUtil.v_success, startTime, endTime, "未查询到变化人员", "未调用", SyncUtil.SyncPerson);
                 return;
             }
-            //调用接口
-            JSONObject response = SyncUtil.doPostByHttpClient(url, ob);
-            //处理返回结果
-            String status = SyncUtil.dealResponseStatus(response);
-            //记录日志
-            SyncUtil.createLog(status, startTime, endTime, ob.toJSONString(), response.toJSONString(), SyncUtil.SyncPerson);
+            //Tyx 2025-05-07 改成分批传输
+            SyncUtil.batchPost(url, ob, SyncUtil.SyncPerson, startTime, endTime);
         } catch (ParseException e) {
             SyncUtil.createLog(SyncUtil.v_error, startTime, endTime, null, e.getMessage(), SyncUtil.SyncPerson);
         } catch (IOException e) {
@@ -116,7 +112,8 @@ public class SyncPersonTask extends AbstractTask implements Plugin {
         sb.append("   (to_char(g.fmodifytime,'yyyy-MM-dd hh24:mi:ss') <= '"+endTime+"' and to_char(g.fmodifytime,'yyyy-MM-dd hh24:mi:ss') >=  '"+startTime+"' ) or \n");
         sb.append("   (to_char(g1.fmodifytime,'yyyy-MM-dd hh24:mi:ss') <= '"+endTime+"' and to_char(g1.fmodifytime,'yyyy-MM-dd hh24:mi:ss') >=  '"+startTime+"' ) or \n");
         sb.append("   (to_char(h.fmodifytime,'yyyy-MM-dd hh24:mi:ss') <= '"+endTime+"' and to_char(h.fmodifytime,'yyyy-MM-dd hh24:mi:ss') >=  '"+startTime+"' ) or \n");
-        sb.append("   (to_char(m.fmodifytime,'yyyy-MM-dd hh24:mi:ss') <= '"+endTime+"' and to_char(m.fmodifytime,'yyyy-MM-dd hh24:mi:ss') >=  '"+startTime+"' ) \n");
+        sb.append("   (to_char(m.fmodifytime,'yyyy-MM-dd hh24:mi:ss') <= '"+endTime+"' and to_char(m.fmodifytime,'yyyy-MM-dd hh24:mi:ss') >=  '"+startTime+"' ) or \n");
+        sb.append("   (a.fid in (select fpersonid from t_hrpi_ermanfile where to_char(fmodifytime,'yyyy-MM-dd hh24:mi:ss') <= '"+endTime+"' and to_char(fmodifytime,'yyyy-MM-dd hh24:mi:ss') >= '"+startTime+"')) \n");
         sb.append("   )");
         log.info("-------- 查询人员sql :" + sb.toString() + " -------- ");
         DataSet dataSet = DB.queryDataSet(this.getClass().getName(), DBRoute.of("hr"), sb.toString());

+ 3 - 9
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/haos/staff/plugin/task/SyncPositionTask.java → code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncPositionTask.java

@@ -1,4 +1,4 @@
-package nckd.jimin.jyyy.hr.haos.staff.plugin.task;
+package nckd.jimin.jyyy.hr.hrmp.hbpm.task;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -8,11 +8,9 @@ import kd.bos.dataentity.entity.DynamicObjectCollection;
 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.orm.util.CollectionUtils;
 import kd.bos.schedule.executor.AbstractTask;
-import kd.bos.servicehelper.QueryServiceHelper;
 import kd.bos.util.StringUtils;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.sdk.plugin.Plugin;
@@ -83,12 +81,8 @@ public class SyncPositionTask extends AbstractTask implements Plugin {
                 log.info("-------- 岗位同步调用url : " + url + " --------");
                 //构建入参
                 buildJSON(ob, posDyArr, changeOperateMap, orgDyxMap);
-                //调用接口
-                JSONObject response = SyncUtil.doPostByHttpClient(url, ob);
-                //处理返回结果
-                String status = SyncUtil.dealResponseStatus(response);
-                //记录日志
-                SyncUtil.createLog(status, startTime, endTime, ob.toJSONString(), response.toJSONString(), SyncUtil.SyncPosition);
+                // 2025-05-07 Tyx 改为分批传输 默认300一批
+                SyncUtil.batchPost(url, ob, SyncUtil.SyncPosition, startTime, endTime);
             }
         } catch (ParseException e) {
             SyncUtil.createLog(SyncUtil.v_error, startTime, endTime, e.getMessage(), "未调用", SyncUtil.SyncPosition);

+ 47 - 5
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/haos/staff/plugin/task/SyncUtil.java → code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/hrmp/hbpm/task/SyncUtil.java

@@ -1,4 +1,4 @@
-package nckd.jimin.jyyy.hr.haos.staff.plugin.task;
+package nckd.jimin.jyyy.hr.hrmp.hbpm.task;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -8,7 +8,6 @@ import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.db.DB;
 import kd.bos.db.DBRoute;
-import kd.bos.exception.KDException;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.orm.query.QCP;
@@ -17,7 +16,6 @@ import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.QueryServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.bos.util.HttpClientUtils;
-import kd.bos.workflow.exception.WFErrorCode;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 
 import java.io.IOException;
@@ -189,6 +187,51 @@ public class SyncUtil {
         });
     }
 
+    /**
+     * 分批调用MDM接口
+     * @param url 接口地址
+     * @param bodyData 入参
+     * @param type 同步类型
+     * @param startTime 变动开始时间
+     * @param endTime 变动结束时间
+     * @throws IOException
+     */
+    public static void batchPost(String url, JSONObject bodyData, String type, String startTime, String endTime) throws IOException {
+        int size = getBatchSize();
+        JSONArray oldArr = bodyData.getJSONArray("obj");
+        int totalSize = bodyData.getJSONArray("obj").size();    //总条数
+        JSONObject newOb = new JSONObject();
+        int totalPage = totalSize % size == 0 ? totalSize / size : totalSize / size + 1;    //总页数
+        for (int i = 1; i <= totalPage; i++) {
+            int startIndex = (i - 1) * size;
+            int endIndex = Math.min(startIndex + size, totalSize);
+            JSONArray newArr = new JSONArray();
+            for (int m = startIndex; m < endIndex; m++) {
+                newArr.add(oldArr.get(m));
+            }
+            newOb.put("obj", newArr);
+            //调用接口
+            JSONObject response = SyncUtil.doPostByHttpClient(url, newOb);
+            //处理返回结果
+            String status = SyncUtil.dealResponseStatus(response);
+            //记录日志
+            SyncUtil.createLog(status, startTime, endTime, newOb.toJSONString(), response.toJSONString(), type);
+        }
+    }
+
+    /**
+     * 获取分页条数
+     * @return
+     */
+    public static int getBatchSize () {
+        QFilter filter = new QFilter("number", QCP.equals, "MDM");
+        filter.and("nckd_entryentity.nckd_key",QCP.equals, "size");
+        DynamicObject bill = QueryServiceHelper.queryOne("nckd_commonparams", "nckd_entryentity.nckd_value", new QFilter[]{filter});
+        return Integer.valueOf(bill.getString("nckd_entryentity.nckd_value"));
+    }
+
+
+
     /**
      *
      * @param url
@@ -201,8 +244,7 @@ public class SyncUtil {
         headers.put("Accept", "*/*");
         logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
         System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
-
-        String responseEntify = HttpClientUtils.postjson(url, headers, bodyData.toJSONString());
+        String responseEntify = HttpClientUtils.postjson(url, headers, bodyData.toJSONString(), 10000, 10000);
 
         logger.info(responseEntify);
         JSONObject result = (JSONObject)JSONObject.parse(responseEntify);

+ 695 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/CasRecrApplyFormPlugin.java

@@ -0,0 +1,695 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.form;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.bill.BillShowParameter;
+import kd.bos.bill.OperationStatus;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.datamodel.events.*;
+import kd.bos.exception.KDBizException;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.MessageBoxResult;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.MessageBoxClosedEvent;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.form.plugin.importentry.resolving.ImportEntryData;
+import kd.bos.list.ListShowParameter;
+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.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.org.OrgUnitServiceHelper;
+import kd.hr.hbp.business.openservicehelper.hrpi.HRPIPersonServiceHelper;
+import nckd.jimin.jyyy.hr.tsrsc.plugin.util.RecUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-临时招聘申请
+ * Description      :临时招聘申请单据插件
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_casrecrapply
+ */
+
+
+
+public class CasRecrApplyFormPlugin extends AbstractBillPlugIn implements BeforeF7SelectListener {
+
+    private static Log logger = LogFactory.getLog(CasRecrApplyFormPlugin.class);
+
+    // 公司类型
+    private final List<String> COMPANY_LIST = Arrays.asList(new String[]{"1020_S","1050_S","1060_S","1070_S"});
+
+    private final List<String> COMPANY_LIST2 = Arrays.asList(new String[]{"Orgform01","Orgform01-100","Orgform02","Orgform03"});
+
+    // 定义日期格式
+    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+    private final String SUBMIT = "submit";
+
+    private static String OPPARAM_AFTERCONFIRM = "afterconfirm";
+
+
+
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        super.afterCreateNewData(e);
+//        DispatchServiceHelper.invokeService("kd.hrmp.haos.servicehelper","haos","IHAOSStaffService","queryUseStaffInfo",objects);
+    }
+
+    @Override
+    public void beforeBindData(EventObject e) {
+        super.beforeBindData(e);
+        Object billstatus = this.getModel().getValue("billstatus");
+        // 暂存状态才发生变化
+        if(ObjectUtils.equals(billstatus,"A")){
+            DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+            updateStaffCount();
+            // 实际人数
+            this.getModel().setValue("nckd_relnum", RecUtils.getStaffCount(org.getPkValue()));
+        }
+    }
+
+    private void updateStaffCount(){
+
+        DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+        //  组织id
+        Long pkValue = (Long) org.getPkValue();
+        List<Long> longs = new ArrayList<Long>();
+        longs.add(pkValue);
+        QFilter qFilter = new QFilter("boid", QCP.equals, pkValue);
+        // 获取组织历史查询
+        DynamicObjectCollection query = QueryServiceHelper.query("haos_adminorgdetail", "id,boid,hisversion", new QFilter[]{qFilter}, "hisversion desc");
+        if(ObjectUtils.isNotEmpty(query)){
+            long boid = query.get(0).getLong("id");
+            // 获取填写的年度 nckd_year
+            Object nckdYear =  this.getModel().getValue("nckd_year");
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
+
+            if(ObjectUtils.isEmpty(nckdYear)){
+                nckdYear = new Date();
+            }else{
+                nckdYear = (Date) nckdYear;
+            }
+            String dateStr = sdf.format(nckdYear);
+//            QFilter qFilter2 = new QFilter("staff.year", QCP.like, dateStr + "%");
+            QFilter qFilter1 = new QFilter("dutyorg.id", QCP.equals, boid);
+
+            DynamicObject[] haosDutyorgdetail = BusinessDataServiceHelper.load( "haos_dutyorgdetail","id,dutyorg,staff,staffcount",new QFilter[]{qFilter1},"staff.year desc");
+            if(ObjectUtils.isNotEmpty(haosDutyorgdetail)){
+                DynamicObject dynamicObject = haosDutyorgdetail[0];
+                int staffcount = dynamicObject.getInt("staffcount");
+                this.getModel().setValue("nckd_sftaffcount",staffcount);
+                this.getModel().setValue("nckd_sftaff",dynamicObject.getLong("staff.id"));
+//                for (DynamicObject dynamicObject : haosDutyorgdetail) {
+//                    String format = sdf.format(dynamicObject.getDate("staff.year"));
+//                    if(dateStr.equals(format)){
+//                        int staffcount = dynamicObject.getInt("staffcount");
+//                        this.getModel().setValue("nckd_sftaffcount",staffcount);
+//                        return;
+//                    }
+//                }
+            }
+            this.getModel().setValue("nckd_sftaffcount",null);
+
+//            int staffcount = ObjectUtils.isNotEmpty(haosDutyorgdetail) ? haosDutyorgdetail.getInt("staffcount"):null;
+//            this.getModel().setValue("nckd_sftaffcount",staffcount);
+
+        }
+
+    }
+
+    private List<String> getPostNumber(){
+        DynamicObjectCollection entryentity = this.getModel().getDataEntity(true).getDynamicObjectCollection("entryentity");
+        List<String> postNumber = new ArrayList<>();
+        for (DynamicObject dynamicObject : entryentity) {
+            if(ObjectUtils.isNotEmpty(dynamicObject.get("nckd_recruitpost"))){
+                postNumber.add(dynamicObject.getString("nckd_recruitpost.number"));
+            }
+        }
+        return postNumber;
+    }
+
+    @Override
+    public void beforeImportEntry(BeforeImportEntryEventArgs e) {
+        // 临时招聘 导入数据
+//        super.beforeImportEntry(e);
+        logger.info("临时招聘导入数据--------");
+        QFilter qFilter = new QFilter("status", QCP.equals, "C")
+                .and("enable", QCP.equals, "1")
+                .and("iscurrentversion", QCP.equals, "1");
+        Map<String, List<Object>> entryDataMap = e.getEntryDataMap();
+        ObjectMapper objectMapper = new ObjectMapper();
+        List<String> postNumber = getPostNumber();
+        DynamicObject nckdRecruitcompany = (DynamicObject)this.getModel().getValue("org");
+
+        List<Long> longs = new ArrayList<Long>();
+        Long pkValue = (Long) nckdRecruitcompany.getPkValue();
+        longs.add(pkValue);
+        List<Long> allSubordinateOrgIds = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs, true);
+        Integer index = 0;
+        try {
+            String jsonString = objectMapper.writeValueAsString(entryDataMap);
+            logger.info("jsonString:{}",jsonString);
+            JSONObject jsonObject = (JSONObject) JSONObject.parse(jsonString);
+            JSONArray entryentity = jsonObject.getJSONArray("entryentity");
+            JSONObject jsonObject1 = entryentity.getJSONObject(0);
+            index =jsonObject1.getInteger("rowIndex");
+        } catch (JsonProcessingException ex) {
+            throw new RuntimeException(ex);
+        }
+
+
+        Map<String, List<ImportEntryData>> source = (Map)e.getSource();
+        Set<Map.Entry<String, List<ImportEntryData>>> entries = source.entrySet();
+        Iterator var4 = entries.iterator();
+        while (var4.hasNext()){
+            Map.Entry<String, List<ImportEntryData>> entry = (Map.Entry)var4.next();
+            String key = entry.getKey();
+            logger.info("entryentity,key:{}",key);
+            if("entryentity".equals(key)){
+                List<ImportEntryData> entryValue = (List) entry.getValue();
+                List<ImportEntryData> entryValue2 = entryValue;
+                logger.info("获取到导入数据");
+                logger.info("获取到导入数据.size:{}",entryValue2.size());
+                if(entryValue2.size() > 0){
+                    StringBuilder errorBuilder = new StringBuilder();
+                    logger.info("分录数据不为空");
+                    List<Object> listQuerOrg = new ArrayList<>();
+                    List<Object> listQuerPost = new ArrayList<>();
+                    String orgQuery = null;
+                    String postQuery = null;
+                    logger.info("开始构建查询条件");
+                    for (int i = 0; i < entryValue2.size(); i++) {
+                        // 部门
+                        JSONObject nckdRecruitorg = entryValue2.get(i).getData().getJSONObject("nckd_recruitorg");
+                        // 岗位
+                        JSONObject nckdRecruitpost = entryValue2.get(i).getData().getJSONObject("nckd_recruitpost");
+
+                        if(i == 0){
+                            orgQuery = nckdRecruitorg.getString("importprop");
+                            postQuery = nckdRecruitpost.getString("importprop");
+                        }
+                        listQuerOrg.add(nckdRecruitorg.get(orgQuery));
+                        listQuerPost.add(nckdRecruitpost.get(postQuery));
+                    }
+                    logger.info("查询条件listQuerOrg:{},listQuerPost:{}",listQuerOrg,listQuerPost);
+                    QFilter qFilterorg = new QFilter(orgQuery, QCP.in, listQuerOrg);
+                    QFilter qFilterpost = new QFilter(postQuery, QCP.in, listQuerPost);
+                    QFilter qFilterbelongcompany = new QFilter("belongcompany", QCP.in,allSubordinateOrgIds);
+                    DynamicObject[] haosAdminorgf7s = BusinessDataServiceHelper.load("haos_adminorgf7", "id,name,number,status,enable,iscurrentversion", new QFilter[]{qFilter, qFilterorg,qFilterbelongcompany});
+//                    logger.info("查询结果haosAdminorgf7s:{}",haosAdminorgf7s);
+                    String finalOrgQuery = orgQuery;
+                    Map<String, DynamicObject> map1 =
+                            Arrays.stream(haosAdminorgf7s)
+                                    .collect(Collectors.toMap(
+                                            detail -> detail.get(finalOrgQuery).toString(),
+                                            detail -> detail,
+                                            (existing, replacement) -> existing // 保留前面的值
+                                    ));
+
+                    DynamicObject[] hbpmPositionhrs = BusinessDataServiceHelper.load("hbpm_positionhr", "id,name,number,status,enable,iscurrentversion", new QFilter[]{qFilter, qFilterpost});
+//                    logger.info("查询结果hbpmPositionhrs:{}",hbpmPositionhrs);
+                    String finalOrgQuery2 = postQuery;
+                    Map<String, Object> map2 =
+                            Arrays.stream(hbpmPositionhrs)
+                                    .collect(Collectors.toMap(
+                                            detail -> detail.get(finalOrgQuery2).toString(),
+                                            detail -> detail.get("id"),
+                                            (existing, replacement) -> existing // 保留前面的值
+                                    ));
+
+                    String finalPostQuery = postQuery;
+
+                    for (int i = 0; i < entryValue.size(); i++) {
+                        ImportEntryData importEntryData = entryValue.get(i);
+                        int i1 = index + i;
+                        logger.info("修改前importEntryData:{},jsondata:{}",importEntryData.getEntryName(),importEntryData.getData().toString());
+                        // 部门
+                        JSONObject nckdRecruitorg = importEntryData.getData().getJSONObject("nckd_recruitorg");
+                        String imoportprop = nckdRecruitorg.getString("importprop");
+                        Object o = nckdRecruitorg.get(imoportprop);
+                        if(ObjectUtils.isNotEmpty(o)){
+                            DynamicObject o1 = map1.get(o);
+                            JSONObject jsonObject = new JSONObject();
+                            if(ObjectUtils.isEmpty(o1)){
+                                errorBuilder.append("第"+i1+"行"+"部门"+o+"在组织"+nckdRecruitcompany.getString("name")+"下未找到!" + "\n");
+                            }else{
+                                jsonObject.put("importprop","id");
+                                jsonObject.put("id",o1.getPkValue());
+                                importEntryData.getData().remove("nckd_recruitorg");
+                                importEntryData.getData().put("nckd_recruitorg",jsonObject);
+                                // 岗位
+                                JSONObject nckdRecruitpost = importEntryData.getData().getJSONObject("nckd_recruitpost");
+                                String imoportprop2 = nckdRecruitpost.getString("importprop");
+                                Object o2 = nckdRecruitpost.get(imoportprop2);
+                                if(ObjectUtils.isNotEmpty(o)){
+                                    List<Long> longs2 = new ArrayList<Long>();
+                                    longs2.add((Long) o1.getPkValue());
+                                    List<Long> allSubordinateOrgIds2 = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs2, true);
+                                    QFilter qFilter1 = new QFilter("adminorg.id", QCP.in, allSubordinateOrgIds2);
+                                    QFilter qFilter2 = new QFilter(finalPostQuery, QCP.equals, o2);
+                                    DynamicObject hbpmPositionhr = BusinessDataServiceHelper.loadSingle("hbpm_positionhr", "id,name,number,status,enable,iscurrentversion", new QFilter[]{qFilter, qFilterpost, qFilter1,qFilter2});
+                                    if(ObjectUtils.isEmpty(hbpmPositionhr)){
+                                        ((List)source.get("entryentity")).clear();
+                                        errorBuilder.append("第"+i1+"行:"+o2 +"岗位不存在!" + "\n");
+                                    }else{
+                                        if(postNumber.contains(hbpmPositionhr.getString("number"))){
+                                            errorBuilder.append("第"+i1+"行:"+o2 +"岗位重复!"+"\n");
+                                        }else{
+                                            postNumber.add(hbpmPositionhr.getString("number"));
+                                            JSONObject jsonObject2 = new JSONObject();
+                                            jsonObject2.put("importprop","id");
+                                            jsonObject2.put("id",hbpmPositionhr.getPkValue());
+                                            importEntryData.getData().remove("nckd_recruitpost");
+                                            importEntryData.getData().put("nckd_recruitpost",jsonObject2);
+                                        }
+                                    }
+                                }
+                            }
+
+                        }
+                    }
+                    if(ObjectUtils.isNotEmpty(errorBuilder)){
+                        ((List)source.get("entryentity")).clear();
+                        throw new KDBizException(errorBuilder.toString());
+                    }
+                }
+
+
+            }
+
+        }
+
+    }
+
+    @Override
+    public void afterImportData(ImportDataEventArgs e) {
+        super.afterImportData(e);
+    }
+
+    @Override
+    public void loadData(LoadDataEventArgs e) {
+        super.loadData(e);
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+        String key = e.getProperty().getName();
+        ChangeData[] changeData = e.getChangeSet();
+        Object newValue = changeData[0].getNewValue();
+        Object oldValue = changeData[0].getOldValue();
+        int iRow = changeData[0].getRowIndex();
+        switch (key) {
+            case "nckd_year":
+                updateStaffCount();
+                break;
+            case "nckd_recruitcompany":
+                // 公司为空清除部门岗位
+                if(!isNotEmpty(newValue)){
+                    this.getModel().setValue("nckd_recruitorg", null,iRow);
+                    this.getModel().setValue("nckd_recruitpost", null,iRow);
+                }
+                break;
+            case "nckd_recruitorg":
+                // 部门,判断是否存企业,如果不存在企业则将部门的所属公司带入到企业中
+                // 修改部门,岗位置为null
+                this.getModel().setValue("nckd_recruitpost", null,iRow);
+                this.getModel().setValue("nckd_compilation", null,iRow);
+                this.getModel().setValue("nckd_currentnum", null,iRow);
+                this.getModel().setValue("nckd_majortype", null,iRow);
+                this.getModel().setValue("nckd_education", null,iRow);
+                this.getModel().setValue("nckd_payrangemin", null,iRow);
+                this.getModel().setValue("nckd_payrange", null,iRow);
+                this.getModel().setValue("nckd_employcategory", null,iRow);
+                this.getModel().setValue("nckd_recruittype", null,iRow);
+                this.getModel().setValue("nckd_employmentreasons", null,iRow);
+                this.getModel().setValue("nckd_approvednum", null,iRow);
+                this.getModel().setValue("nckd_recruitnum", 0,iRow);
+                break;
+            case "nckd_recruitpost":
+                // 岗位,判断是否存企业,如果不存在企业则将部门的所属公司带入到企业中
+                if(isNotEmpty(newValue)){
+                    DynamicObject newValue1 = (DynamicObject) newValue;
+                    // 校验是否有相同岗位
+                    if(!checkPosition(newValue1,iRow)){
+                        this.getView().showErrorNotification("已录入相同岗位!"+newValue1.getString("name")+newValue1.getString("number"));
+                        this.getModel().setValue("nckd_recruitpost", null,iRow);
+                        return;
+                    }
+                    // 获取行政组织,和行政组织的所属公司
+                    // 行政组织
+                    DynamicObject nckdRecruitcompany = (DynamicObject)this.getModel().getValue("nckd_recruitorg", iRow);
+                    if(ObjectUtils.isEmpty(nckdRecruitcompany)){
+                        DynamicObject adminorg = newValue1.getDynamicObject("adminorg");
+                        DynamicObjectCollection entryentity = this.getModel().getDataEntity().getDynamicObjectCollection("entryentity");
+                        for (DynamicObject object : entryentity) {
+                            if(newValue1.getString("number").equals(object.getString("nckd_recruitpost.number"))){
+                                object.set("nckd_recruitorg",adminorg);
+                                break;
+                            }
+                        }
+                    }
+                    this.getModel().setValue("nckd_compilation",getFieldValue(newValue1),iRow);
+                    long id = newValue1.getLong("id");
+                    List<Long> longs = new ArrayList<Long>();
+                    longs.add(id);
+                    Map<Long, Set<Long>> allUsersOfPosition = HRPIPersonServiceHelper.getAllUsersOfPosition("1010_S", longs);
+                    int num = 0;
+                    if(ObjectUtils.isNotEmpty(allUsersOfPosition)){
+                        Set<Long> longSet = allUsersOfPosition.get(id);
+                        List<String> zaizhiStatus = Arrays.asList(new String[]{"1020_S","1010_S","1190_S","1050_S","1140_S","1060_S","1120_S","1210_S"});
+                        QFilter qFilter = new QFilter("person.id", QCP.in, longSet)
+                                .and("iscurrentversion",QCP.equals,"1")
+                                .and("businessstatus",QCP.equals,"1")
+                                .and("labrelstatusprd.number",QCP.in,zaizhiStatus);
+
+                        DynamicObject[] hrpiEmpentrels = BusinessDataServiceHelper.load("hrpi_empentrel", "id,person", qFilter.toArray());
+                        num = hrpiEmpentrels.length;
+                    }
+                    this.getModel().setValue("nckd_currentnum",num,iRow);
+                }else{
+                    this.getModel().setValue("nckd_compilation",null,iRow);
+                    this.getModel().setValue("nckd_currentnum",null,iRow);
+                }
+                this.getModel().setValue("nckd_recruitnum",0,iRow);
+                break;
+            case "nckd_recruitnum":
+                // 人数字段统计
+                setSumRecruitnum(newValue,iRow);
+                checkRecruitnum(newValue,iRow);
+                break;
+            case "nckd_payrangemin":
+                changePayrangemin(newValue,oldValue,iRow);
+                break;
+            case "nckd_payrange":
+                changepayrange(newValue,oldValue,iRow);
+                break;
+            default:
+                break;
+        }
+
+    }
+
+    // 校验岗位人数是否超编制
+    private void checkRecruitnum(Object recruitnum,int row) {
+        if(recruitnum instanceof Integer){
+            // 获取编制人数
+            Object nckdCompilation = this.getModel().getValue("nckd_compilation",row);
+            if(ObjectUtils.isNotEmpty(nckdCompilation)){
+                Integer integer =  (Integer)nckdCompilation;
+                Integer nckdCurrentnum = (Integer)this.getModel().getValue("nckd_currentnum", row);
+                Integer recruitnum1 =  (Integer)recruitnum;
+                if (integer < (nckdCurrentnum + recruitnum1)){
+                    this.getView().showErrorNotification("最高薪资不能低于最低薪资!");
+                }
+            }
+        }
+    }
+
+    // 校验分录的最高薪资和最低薪资大小关系
+    private String vaildatorPayrange(){
+        DynamicObjectCollection entryentity = this.getModel().getDataEntity(true).getDynamicObjectCollection("entryentity");
+        StringBuilder errorBuilder = new StringBuilder();
+        for (DynamicObject object : entryentity) {
+            int nckdPayrange = object.getInt("nckd_payrange");
+            int nckdPayrangemin = object.getInt("nckd_payrangemin");
+            if(nckdPayrange < nckdPayrangemin){
+                errorBuilder.append(object.get("seq"));
+            }
+        }
+        if(ObjectUtils.isNotEmpty(errorBuilder)){
+            errorBuilder.append("行,最高薪资不能低于最低薪资!");
+        }
+        return errorBuilder.toString();
+
+    }
+
+    private void changePayrangemin(Object newValue,Object oldValue,int row){
+        if(newValue instanceof Integer){
+            // 最大值
+            Integer nckdPayrange = (Integer)this.getModel().getValue("nckd_payrange",row);
+            int comparisonResult = nckdPayrange.compareTo( (Integer) newValue);
+            if(comparisonResult < 0){
+                this.getView().showErrorNotification("最高薪资不能低于最低薪资!");
+                this.getModel().setValue("nckd_payrangemin",oldValue,row);
+            }
+        }
+    }
+    private void changepayrange(Object newValue,Object oldValue,int row){
+        if(newValue instanceof Integer){
+            // 最大值
+            Integer nckdPayrange = (Integer)this.getModel().getValue("nckd_payrangemin",row);
+            int comparisonResult = ((Integer) newValue).compareTo( (Integer) nckdPayrange);
+            if(comparisonResult < 0){
+                this.getView().showErrorNotification("最高薪资不能低于最低薪资!");
+                this.getModel().setValue("nckd_payrange",oldValue,row);
+            }
+        }
+    }
+
+    private boolean checkPosition(DynamicObject  newValue,int row) {
+        DynamicObjectCollection entryentity = this.getModel().getDataEntity(true).getDynamicObjectCollection("entryentity");
+        for (int i = 0; i < entryentity.size(); i++) {
+            if(row == i){
+                break;
+            }
+            if(ObjectUtils.isNotEmpty(entryentity.get(i).get("nckd_recruitpost"))){
+                if(entryentity.get(i).get("nckd_recruitpost.number").equals(newValue.get("number"))){
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    // 公司,部门,岗位选择过滤
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent e) {
+        String fieldKey = e.getProperty().getName();
+        switch (fieldKey){
+            case "nckd_recruitcompany":
+                // 企业名称
+                ListShowParameter showParameter = (ListShowParameter)e.getFormShowParameter();
+                //是否展示审核的改为false
+                QFilter qFilter = new QFilter("adminorgtype.number", "in", COMPANY_LIST);
+                showParameter.getListFilterParameter().setFilter(qFilter);
+                break;
+            case "nckd_recruitorg":
+                // 组织名称
+                ListShowParameter showParameter2 = (ListShowParameter)e.getFormShowParameter();
+                // 展示部门,如果选择了企业,展示企业下的部门,添加企业筛选条件
+                DynamicObject nckdRecruitcompany = (DynamicObject)this.getModel().getValue("org");
+
+                List<Long> longs = new ArrayList<Long>();
+                Long pkValue = (Long) nckdRecruitcompany.getPkValue();
+                longs.add(pkValue);
+                List<Long> allSubordinateOrgIds = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs, true);
+                // 使用流处理过滤掉指定的值
+//                List<Long> filteredOrgIds = allSubordinateOrgIds.stream()
+//                        .filter(orgId -> !orgId.equals(pkValue)) // 过滤掉值
+//                        .collect(Collectors.toList());
+
+                // 获取组织编码
+//                QFilter belongcompanyFilter = new QFilter("belongcompany", "in", allSubordinateOrgIds);
+                QFilter qFilter2 = new QFilter("belongcompany", QCP.in,allSubordinateOrgIds);
+                showParameter2.getListFilterParameter().setFilter(qFilter2);
+
+                break;
+            case "nckd_recruitpost":
+                // 岗位名称
+                ListShowParameter showParameter3 = (ListShowParameter)e.getFormShowParameter();
+                // 展示部门,如果选择了企业,展示企业下的部门
+                EntryGrid treeEntryEntity2 = this.getControl("entryentity");
+                int[] rows2 = treeEntryEntity2.getSelectRows();
+                DynamicObject nckdRecruitcompany2 = (DynamicObject)this.getModel().getValue("org");
+                DynamicObject nckdRecruitorg = (DynamicObject)this.getModel().getValue("nckd_recruitorg", rows2[0]);
+                List<Long> longs2 = new ArrayList<Long>();
+                longs2.add((Long)nckdRecruitcompany2.getPkValue());
+                List<Long> allSubordinateOrgIds2 = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs2, true);
+                QFilter qFilter1 = new QFilter("adminorg.id", QCP.in, allSubordinateOrgIds2);
+                if(ObjectUtils.isNotEmpty(nckdRecruitorg)){
+                    qFilter1.and("adminorg.id", QCP.equals, nckdRecruitorg.getPkValue());
+                }
+                showParameter3.getListFilterParameter().setFilter(qFilter1);
+                break;
+            case "org":
+                ListShowParameter showParameter4 = (ListShowParameter)e.getFormShowParameter();
+                // 去除部门
+                QFilter qFilter4 = new QFilter("orgpattern.number", "in", COMPANY_LIST2);
+                showParameter4.getListFilterParameter().setFilter(qFilter4);
+                break;
+            default:
+                break;
+        }
+    }
+
+
+    // 获取岗位对应编制人数
+    public Object getFieldValue(DynamicObject nckd_recruitpost) {
+        Object num = null;
+        if(ObjectUtils.isNotEmpty(nckd_recruitpost)){
+            Object nckdSftaff = this.getModel().getValue("nckd_sftaff");
+
+            DynamicObject haosStaff = null;
+            if(ObjectUtils.isNotEmpty(nckdSftaff)){
+                haosStaff = BusinessDataServiceHelper.loadSingle(nckdSftaff,"haos_staff");
+            }else{
+                QFilter qFilter = new QFilter("enable", QCP.equals, "1");
+                DynamicObject[] haosStaffs = BusinessDataServiceHelper.load("haos_staff", "id,name,number", new QFilter[]{qFilter},"year desc");
+                if (haosStaffs != null && haosStaffs.length > 0) {
+                    haosStaff = haosStaffs[0];
+                } else {
+                    return null;
+                }
+                this.getModel().setValue("nckd_sftaff",haosStaff.getPkValue());
+            }
+
+            Object pkValue = nckd_recruitpost.get("id");
+            QFilter qFilter3 = new QFilter("staff.id", QCP.equals, haosStaff.getPkValue())
+                    .and("enable", QCP.not_equals, "0")
+                    .and("datastatus",QCP.not_equals,"-2")
+                    .and("datastatus",QCP.not_equals,"2")
+                    .and("datastatus",QCP.not_equals,"-1")
+                    .and("dutyworkrole.boid",QCP.equals,pkValue);
+            DynamicObject[] haosDutyorgdetails = BusinessDataServiceHelper.load("haos_muldimendetail", "id,staff,dutyworkrole,dutyworkrole.boid,yearstaff", new QFilter[]{qFilter3});
+            num = haosDutyorgdetails[0].get("yearstaff");
+        }
+        return num;
+    }
+
+
+    @Override
+    public void registerListener(EventObject e) {
+        BasedataEdit fieldEdit = (BasedataEdit) this.getView().getControl("nckd_recruitcompany");
+        BasedataEdit fieldEdit2 = (BasedataEdit) this.getView().getControl("nckd_recruitorg");
+        BasedataEdit fieldEdit3 = (BasedataEdit) this.getView().getControl("nckd_recruitpost");
+        BasedataEdit fieldEdit4 = this.getView().getControl("org");
+        fieldEdit.addBeforeF7SelectListener(this);
+        fieldEdit.addBeforeF7SelectListener(this);
+        fieldEdit2.addBeforeF7SelectListener(this);
+        fieldEdit3.addBeforeF7SelectListener(this);
+        fieldEdit4.addBeforeF7SelectListener(this);
+    }
+
+
+    public static boolean isNotEmpty(Object  key) {
+        // 基础资料判空
+        if(ObjectUtils.isEmpty(key) || ObjectUtils.isEmpty(((DynamicObject)key).getDataStorage())){
+            return false;
+        }
+        return true;
+    }
+
+
+    public void setSumRecruitnum(Object newValue,int row){
+        // 计算招聘人数,获取出所有分录,然后统计所有分录的招聘人数累加
+        DynamicObjectCollection entryEntity = this.getModel().getEntryEntity("entryentity");
+        int num = 0;
+        for (int i = 0; i < entryEntity.size(); i++) {
+            if(row == i){
+                num = num + (Integer) newValue;
+            }else{
+                num = num + (Integer) entryEntity.get(i).get("nckd_recruitnum");
+            }
+        }
+        this.getModel().setValue("nckd_applynum", num);
+    }
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate opreate = (FormOperate) args.getSource();
+        switch (opreate.getOperateKey()) {
+            case "submit":
+                String errorMessage = vaildatorPayrange();
+                if(StringUtils.isNotEmpty(errorMessage)){
+                    this.getView().showErrorNotification(errorMessage);
+                    args.setCancel(true);
+                    return;
+                }
+                // 在此添加处理逻辑
+                Object nckdSftaffcount1 = this.getModel().getValue("nckd_sftaffcount");
+                if(ObjectUtils.isNotEmpty(nckdSftaffcount1)){
+                    int nckdSftaffcount = (int) this.getModel().getValue("nckd_sftaffcount");
+                    // 实际人数
+                    int nckdRelnum = (int) this.getModel().getValue("nckd_relnum");
+                    // 申请人数
+                    int nckdApplynum = (int) this.getModel().getValue("nckd_applynum");
+                    if(nckdApplynum > 0){
+                        if(nckdSftaffcount < nckdRelnum + nckdApplynum){
+                            // 判断是否处理过
+                            String isDealed = this.getView().getPageCache().get("isDealed");
+                            if (!"true".equals(isDealed)) {
+                                // 取消原来的操作
+                                args.setCancel(true);
+                                // 在用户点击确认框上的按钮后,系统会调用confirmCallBack方法
+                                ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener("isExceed", this);
+                                // 设置页面确认框,参数为:标题,选项框类型,回调监听
+                                this.getView().showConfirm("请注意,申请人数超编,是否继续提报?", MessageBoxOptions.YesNo, confirmCallBackListener);
+                                // 只执行一次
+                                this.getView().getPageCache().put("isDealed", "true");
+                            }
+                        }
+                    }
+
+                }
+
+                break;
+            case "save":
+                String errorMessage2 = vaildatorPayrange();
+                if(StringUtils.isNotEmpty(errorMessage2)){
+                    this.getView().showErrorNotification(errorMessage2);
+                    args.setCancel(true);
+                    return;
+                }
+            default:
+                break;
+        }
+    }
+
+
+
+
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+        this.getView().getPageCache().remove("isDealed");
+    }
+
+    @Override
+    public void confirmCallBack(MessageBoxClosedEvent messageBoxClosedEvent) {
+        //判断回调参数id
+        if ("isExceed".equals(messageBoxClosedEvent.getCallBackId())) {
+            if (MessageBoxResult.Yes.equals(messageBoxClosedEvent.getResult())) {
+                this.getView().invokeOperation("submit");
+            } else if (MessageBoxResult.No.equals(messageBoxClosedEvent.getResult())) {
+                // 点击否也清除
+                this.getView().getPageCache().remove("isDealed");
+            }
+        }
+    }
+
+
+
+}

+ 103 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/CasRecrApplyListPlugin.java

@@ -0,0 +1,103 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.form;
+
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.EntityType;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.MessageBoxResult;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.MessageBoxClosedEvent;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import org.apache.commons.lang3.ObjectUtils;
+import kd.bos.list.BillList;
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-临时招聘申请
+ * Description      :临时招聘申请列表操作插件
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_casrecrapply
+ */
+
+
+
+public class CasRecrApplyListPlugin extends AbstractListPlugin {
+
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate opreate = (FormOperate) args.getSource();
+        switch (opreate.getOperateKey()) {
+            case "submit":
+                ListSelectedRowCollection selectCols = args.getListSelectedData();
+                StringBuffer exceedMsg = new StringBuffer();
+                Object[] primaryKeyValues  = selectCols.getPrimaryKeyValues();
+                BillList billlistap = this.getView().getControl("billlistap");
+                EntityType entityType = billlistap.getEntityType();
+                //获取完整数据
+                DynamicObject[] casPaybillArr = BusinessDataServiceHelper.load(primaryKeyValues, entityType);
+                for (int i = 0; i < casPaybillArr.length; i++) {
+                    // 在此添加处理逻辑
+                    DynamicObject dynamicObject = casPaybillArr[i];
+                    Object nckdSftaffcount1 = dynamicObject.get("nckd_sftaffcount");
+                    if(ObjectUtils.isNotEmpty(nckdSftaffcount1)){
+                        int nckdSftaffcount = dynamicObject.getInt("nckd_sftaffcount");
+                        // 实际人数
+                        int nckdRelnum = dynamicObject.getInt("nckd_relnum");
+                        // 申请人数
+                        int nckdApplynum = dynamicObject.getInt("nckd_applynum");
+
+                        if(nckdSftaffcount < nckdRelnum + nckdApplynum){
+                            // 判断是否处理过
+                            String isDealed = this.getView().getPageCache().get("isDealed");
+                            if (!"true".equals(isDealed)) {
+                                if(ObjectUtils.isEmpty(exceedMsg)){
+                                    exceedMsg.append("单据:");
+                                }
+                                exceedMsg.append(dynamicObject.getString("billno")+",");
+                            }
+                        }
+                    }
+                }
+                if(ObjectUtils.isNotEmpty(exceedMsg)){
+                    args.setCancel(true);
+                    exceedMsg.append("请注意,申请人数超编,是否继续提报?");
+                    ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener("isExceed", this);
+                    // 设置页面确认框,参数为:标题,选项框类型,回调监听
+                    this.getView().showConfirm(exceedMsg.toString(), MessageBoxOptions.YesNo, confirmCallBackListener);
+                    // 只执行一次
+                    this.getView().getPageCache().put("isDealed", "true");
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+        // 清除
+        this.getView().getPageCache().remove("isDealed");
+    }
+
+    @Override
+    public void confirmCallBack(MessageBoxClosedEvent messageBoxClosedEvent) {
+        //判断回调参数id
+        if ("isExceed".equals(messageBoxClosedEvent.getCallBackId())) {
+            if (MessageBoxResult.Yes.equals(messageBoxClosedEvent.getResult())) {
+                this.getView().invokeOperation("submit");
+            } else if (MessageBoxResult.No.equals(messageBoxClosedEvent.getResult())) {
+                // 点击否也清除
+                this.getView().getPageCache().remove("isDealed");
+            }
+        }
+    }
+
+}

+ 781 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyFormPlugin.java

@@ -0,0 +1,781 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.form;
+
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import kd.bos.algo.DataSet;
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.db.DBRoute;
+import kd.bos.entity.datamodel.events.BeforeImportEntryEventArgs;
+import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.LoadDataEventArgs;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.exception.KDBizException;
+import kd.bos.form.*;
+import kd.bos.form.control.EntryGrid;
+import kd.bos.form.control.events.BeforeItemClickEvent;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.MessageBoxClosedEvent;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.form.plugin.importentry.resolving.ImportEntryData;
+import kd.bos.list.ListShowParameter;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.ORM;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.org.OrgUnitServiceHelper;
+import kd.hr.hbp.business.openservicehelper.hrpi.HRPIPersonServiceHelper;
+import kd.hr.hbp.common.util.HRDBUtil;
+import nckd.jimin.jyyy.hr.tsrsc.plugin.util.RecUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import scala.Int;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-年度招聘申请
+ * Description      :年度招聘申请单据插件
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_yearapply
+ */
+
+
+
+public class YearCrApplyFormPlugin extends AbstractBillPlugIn implements BeforeF7SelectListener {
+
+    private static Log logger = LogFactory.getLog(YearCrApplyFormPlugin.class);
+
+    // 公司类型
+    private final List<String> COMPANY_LIST = Arrays.asList(new String[]{"1020_S","1050_S","1060_S","1070_S"});
+
+    private final List<String> COMPANY_LIST2 = Arrays.asList(new String[]{"Orgform01","Orgform01-100","Orgform02","Orgform03"});
+
+    // 定义日期格式
+    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+
+
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        super.afterCreateNewData(e);
+//        DispatchServiceHelper.invokeService("kd.hrmp.haos.servicehelper","haos","IHAOSStaffService","queryUseStaffInfo",objects);
+    }
+
+    @Override
+    public void beforeBindData(EventObject e) {
+        super.beforeBindData(e);
+
+        Object billstatus = this.getModel().getValue("billstatus");
+        // 暂存状态才发生变化
+        if(ObjectUtils.equals(billstatus,"A")){
+            DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+            updateStaffCount();
+            // 实际人数
+            this.getModel().setValue("nckd_relnum", RecUtils.getStaffCount(org.getPkValue()));
+        }
+//        DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+//        //  组织id
+//        Long pkValue = (Long) org.getPkValue();
+//        updateStaffCount();
+        /*
+        List<Long> longs = new ArrayList<Long>();
+        longs.add(pkValue);
+        QFilter qFilter = new QFilter("boid", QCP.equals, pkValue);
+        // 获取组织历史查询
+        DynamicObjectCollection query = QueryServiceHelper.query("haos_adminorgdetail", "id,boid,hisversion", new QFilter[]{qFilter}, "hisversion desc");
+        if(ObjectUtils.isNotEmpty(query)){
+            long boid = query.get(0).getLong("id");
+            QFilter qFilter1 = new QFilter("dutyorg.id", QCP.equals, boid);
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
+            String dateStr = sdf.format(new Date());
+            QFilter qFilter2 = new QFilter("staff.year", QCP.like, dateStr + "%");
+
+            DynamicObject haosDutyorgdetail = BusinessDataServiceHelper.loadSingle( "haos_dutyorgdetail","id,dutyorg,staff,staffcount",new QFilter[]{qFilter1,qFilter2});
+            int staffcount = ObjectUtils.isNotEmpty(haosDutyorgdetail) ? haosDutyorgdetail.getInt("staffcount"):0;
+            this.getModel().setValue("nckd_sftaffcount",staffcount);
+
+//            QFilter qFilter1 = new QFilter("useorgbo", QCP.equals, boid);
+//            DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle("haos_useorgdetail", "id,useorgbo,useorg.id,yearstaff", new QFilter[]{qFilter1});
+//            if(ObjectUtils.isNotEmpty(dynamicObject)){
+//                this.getModel().setValue("nckd_sftaffcount",dynamicObject.get("yearstaff"));
+//            }
+
+        }
+        */
+
+//        this.getModel().setValue("nckd_relnum",getStaffCount(org.getPkValue()));
+
+    }
+
+    private List<String> getPostNumber(){
+        DynamicObjectCollection entryentity = this.getModel().getDataEntity(true).getDynamicObjectCollection("entryentity");
+        List<String> postNumber = new ArrayList<>();
+        for (DynamicObject dynamicObject : entryentity) {
+            if(ObjectUtils.isNotEmpty(dynamicObject.get("nckd_recruitpost"))){
+                postNumber.add(dynamicObject.getString("nckd_recruitpost.number"));
+            }
+        }
+        return postNumber;
+    }
+
+
+    @Override
+    public void beforeImportEntry(BeforeImportEntryEventArgs e) {
+        // 临时招聘 导入数据
+//        super.beforeImportEntry(e);
+        logger.info("年度招聘导入数据--------");
+        QFilter qFilter = new QFilter("status", QCP.equals, "C")
+                .and("enable", QCP.equals, "1")
+                .and("iscurrentversion", QCP.equals, "1");
+        Map<String, List<Object>> entryDataMap = e.getEntryDataMap();
+        ObjectMapper objectMapper = new ObjectMapper();
+        List<String> postNumber = getPostNumber();
+        DynamicObject nckdRecruitcompany = (DynamicObject)this.getModel().getValue("org");
+
+        List<Long> longs = new ArrayList<Long>();
+        Long pkValue = (Long) nckdRecruitcompany.getPkValue();
+        longs.add(pkValue);
+        List<Long> allSubordinateOrgIds = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs, true);
+        Integer index = 0;
+        try {
+            String jsonString = objectMapper.writeValueAsString(entryDataMap);
+            logger.info("jsonString:{}",jsonString);
+            JSONObject jsonObject = (JSONObject) JSONObject.parse(jsonString);
+            JSONArray entryentity = jsonObject.getJSONArray("entryentity");
+            JSONObject jsonObject1 = entryentity.getJSONObject(0);
+            index =jsonObject1.getInteger("rowIndex");
+        } catch (JsonProcessingException ex) {
+            throw new RuntimeException(ex);
+        }
+
+
+        Map<String, List<ImportEntryData>> source = (Map)e.getSource();
+        Set<Map.Entry<String, List<ImportEntryData>>> entries = source.entrySet();
+        Iterator var4 = entries.iterator();
+        while (var4.hasNext()){
+            Map.Entry<String, List<ImportEntryData>> entry = (Map.Entry)var4.next();
+            String key = entry.getKey();
+            if("entryentity".equals(key)){
+                List<ImportEntryData> entryValue = (List) entry.getValue();
+                List<ImportEntryData> entryValue2 = entryValue;
+
+                if(entryValue2.size() > 0){
+                    StringBuilder errorBuilder = new StringBuilder();
+                    logger.info("分录数据不为空");
+                    List<Object> listQuerOrg = new ArrayList<>();
+                    List<Object> listQuerPost = new ArrayList<>();
+                    String orgQuery = null;
+                    String postQuery = null;
+                    logger.info("开始构建查询条件");
+                    for (int i = 0; i < entryValue2.size(); i++) {
+                        // 部门
+                        JSONObject nckdRecruitorg = entryValue2.get(i).getData().getJSONObject("nckd_recruitorg");
+                        // 岗位
+                        JSONObject nckdRecruitpost = entryValue2.get(i).getData().getJSONObject("nckd_recruitpost");
+
+                        if(i == 0){
+                            orgQuery = nckdRecruitorg.getString("importprop");
+                            postQuery = nckdRecruitpost.getString("importprop");
+                        }
+                        listQuerOrg.add(nckdRecruitorg.get(orgQuery));
+                        listQuerPost.add(nckdRecruitpost.get(postQuery));
+                    }
+                    logger.info("查询条件listQuerOrg:{},listQuerPost:{}",listQuerOrg,listQuerPost);
+                    QFilter qFilterorg = new QFilter(orgQuery, QCP.in, listQuerOrg);
+                    QFilter qFilterpost = new QFilter(postQuery, QCP.in, listQuerPost);
+                    QFilter qFilterbelongcompany = new QFilter("belongcompany", QCP.in,allSubordinateOrgIds);
+                    DynamicObject[] haosAdminorgf7s = BusinessDataServiceHelper.load("haos_adminorgf7", "id,name,number,status,enable,iscurrentversion", new QFilter[]{qFilter, qFilterorg,qFilterbelongcompany});
+//                    logger.info("查询结果haosAdminorgf7s:{}",haosAdminorgf7s);
+                    String finalOrgQuery = orgQuery;
+                    Map<String, DynamicObject> map1 =
+                            Arrays.stream(haosAdminorgf7s)
+                                    .collect(Collectors.toMap(
+                                            detail -> detail.get(finalOrgQuery).toString(),
+                                            detail -> detail,
+                                            (existing, replacement) -> existing // 保留前面的值
+                                    ));
+
+                    DynamicObject[] hbpmPositionhrs = BusinessDataServiceHelper.load("hbpm_positionhr", "id,name,number,status,enable,iscurrentversion", new QFilter[]{qFilter, qFilterpost});
+//                    logger.info("查询结果hbpmPositionhrs:{}",hbpmPositionhrs);
+                    String finalOrgQuery2 = postQuery;
+                    Map<String, Object> map2 =
+                            Arrays.stream(hbpmPositionhrs)
+                                    .collect(Collectors.toMap(
+                                            detail -> detail.get(finalOrgQuery2).toString(),
+                                            detail -> detail.get("id"),
+                                            (existing, replacement) -> existing // 保留前面的值
+                                    ));
+
+                    String finalPostQuery = postQuery;
+
+                    for (int i = 0; i < entryValue.size(); i++) {
+                        ImportEntryData importEntryData = entryValue.get(i);
+                        int i1 = index + i;
+                        logger.info("修改前importEntryData:{},jsondata:{}",importEntryData.getEntryName(),importEntryData.getData().toString());
+                        // 部门
+                        JSONObject nckdRecruitorg = importEntryData.getData().getJSONObject("nckd_recruitorg");
+                        String imoportprop = nckdRecruitorg.getString("importprop");
+                        Object o = nckdRecruitorg.get(imoportprop);
+                        if(ObjectUtils.isNotEmpty(o)){
+                            DynamicObject o1 = map1.get(o);
+                            JSONObject jsonObject = new JSONObject();
+                            if(ObjectUtils.isEmpty(o1)){
+                                errorBuilder.append("第"+i1+"行"+"部门"+o+"在组织"+nckdRecruitcompany.getString("name")+"下未找到!" + "\n");
+                            }else{
+                                jsonObject.put("importprop","id");
+                                jsonObject.put("id",o1.getPkValue());
+                                importEntryData.getData().remove("nckd_recruitorg");
+                                importEntryData.getData().put("nckd_recruitorg",jsonObject);
+                                // 岗位
+                                JSONObject nckdRecruitpost = importEntryData.getData().getJSONObject("nckd_recruitpost");
+                                String imoportprop2 = nckdRecruitpost.getString("importprop");
+                                Object o2 = nckdRecruitpost.get(imoportprop2);
+                                if(ObjectUtils.isNotEmpty(o)){
+                                    List<Long> longs2 = new ArrayList<Long>();
+                                    longs2.add((Long) o1.getPkValue());
+                                    List<Long> allSubordinateOrgIds2 = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs2, true);
+                                    QFilter qFilter1 = new QFilter("adminorg.id", QCP.in, allSubordinateOrgIds2);
+                                    QFilter qFilter2 = new QFilter(finalPostQuery, QCP.equals, o2);
+                                    DynamicObject hbpmPositionhr = BusinessDataServiceHelper.loadSingle("hbpm_positionhr", "id,name,number,status,enable,iscurrentversion", new QFilter[]{qFilter, qFilterpost, qFilter1,qFilter2});
+                                    if(ObjectUtils.isEmpty(hbpmPositionhr)){
+                                        ((List)source.get("entryentity")).clear();
+                                        errorBuilder.append("第"+i1+"行:"+o2 +"岗位不存在!" + "\n");
+                                    }else{
+                                        if(postNumber.contains(hbpmPositionhr.getString("number"))){
+                                            errorBuilder.append("第"+i1+"行:"+o2 +"岗位重复!"+"\n");
+                                        }else{
+                                            postNumber.add(hbpmPositionhr.getString("number"));
+                                            JSONObject jsonObject2 = new JSONObject();
+                                            jsonObject2.put("importprop","id");
+                                            jsonObject2.put("id",hbpmPositionhr.getPkValue());
+
+                                            // 获取对应岗位编制人数
+                                            Object fieldValue = getFieldValue(hbpmPositionhr);
+                                            importEntryData.getData().put("nckd_compilation",fieldValue);
+
+                                            // 获取对应岗位现有人数
+                                            List<Long> postIds = new ArrayList<Long>();
+                                            long id = hbpmPositionhr.getLong("id");
+                                            postIds.add(id);
+                                            Map<Long, Set<Long>> allUsersOfPosition = HRPIPersonServiceHelper.getAllUsersOfPosition("1010_S", postIds);
+                                            int num = 0;
+                                            if(ObjectUtils.isNotEmpty(allUsersOfPosition)){
+                                                Set<Long> longSet = allUsersOfPosition.get(id);
+                                                List<String> zaizhiStatus = Arrays.asList(new String[]{"1020_S","1010_S","1190_S","1050_S","1140_S","1060_S","1120_S","1210_S"});
+                                                QFilter qFilterEmepentrel = new QFilter("person.id", QCP.in, longSet)
+                                                        .and("iscurrentversion",QCP.equals,"1")
+                                                        .and("businessstatus",QCP.equals,"1")
+                                                        .and("labrelstatusprd.number",QCP.in,zaizhiStatus);
+
+                                                DynamicObject[] hrpiEmpentrels = BusinessDataServiceHelper.load("hrpi_empentrel", "id,person", qFilterEmepentrel.toArray());
+                                                num = hrpiEmpentrels.length;
+                                            }
+                                            importEntryData.getData().put("nckd_currentnum",num);
+
+                                            importEntryData.getData().put("nckd_recruitpost",jsonObject2);
+                                        }
+                                    }
+                                }
+                            }
+
+                        }
+                    }
+                    if(ObjectUtils.isNotEmpty(errorBuilder)){
+                        ((List)source.get("entryentity")).clear();
+                        throw new KDBizException(errorBuilder.toString());
+                    }
+                }
+            }
+        }
+    }
+
+    private void updateStaffCount(){
+
+        DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+        //  组织id
+        Long pkValue = (Long) org.getPkValue();
+        List<Long> longs = new ArrayList<Long>();
+        longs.add(pkValue);
+        QFilter qFilter = new QFilter("boid", QCP.equals, pkValue);
+        // 获取组织历史查询
+        DynamicObjectCollection query = QueryServiceHelper.query("haos_adminorgdetail", "id,boid,hisversion", new QFilter[]{qFilter}, "hisversion desc");
+        if(ObjectUtils.isNotEmpty(query)){
+            long boid = query.get(0).getLong("id");
+            // 获取填写的年度 nckd_year
+            Object nckdYear =  this.getModel().getValue("nckd_year");
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
+
+            if(ObjectUtils.isEmpty(nckdYear)){
+                nckdYear = new Date();
+            }else{
+                nckdYear = (Date) nckdYear;
+            }
+            String dateStr = sdf.format(nckdYear);
+//            QFilter qFilter2 = new QFilter("staff.year", QCP.like, dateStr + "%");
+            QFilter qFilter1 = new QFilter("dutyorg.id", QCP.equals, boid);
+
+            DynamicObject[] haosDutyorgdetail = BusinessDataServiceHelper.load( "haos_dutyorgdetail","id,dutyorg,staff,staffcount",new QFilter[]{qFilter1});
+            if(ObjectUtils.isNotEmpty(haosDutyorgdetail)){
+                for (DynamicObject dynamicObject : haosDutyorgdetail) {
+                    String format = sdf.format(dynamicObject.getDate("staff.year"));
+                    if(dateStr.equals(format)){
+                        int staffcount = dynamicObject.getInt("staffcount");
+                        this.getModel().setValue("nckd_sftaffcount",staffcount);
+                        return;
+                    }
+                }
+            }
+            this.getModel().setValue("nckd_sftaffcount",null);
+
+//            int staffcount = ObjectUtils.isNotEmpty(haosDutyorgdetail) ? haosDutyorgdetail.getInt("staffcount"):null;
+//            this.getModel().setValue("nckd_sftaffcount",staffcount);
+
+        }
+
+    }
+
+    @Override
+    public void loadData(LoadDataEventArgs e) {
+        super.loadData(e);
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+        String key = e.getProperty().getName();
+        ChangeData[] changeData = e.getChangeSet();
+        Object newValue = changeData[0].getNewValue();
+        Object oldValue = changeData[0].getOldValue();
+        int iRow = changeData[0].getRowIndex();
+        switch (key) {
+            case "nckd_year":
+                updateStaffCount();
+                break;
+            case "nckd_recruitcompany":
+                // 公司为空清除部门岗位
+                if(!isNotEmpty(newValue)){
+                    this.getModel().setValue("nckd_recruitorg", null,iRow);
+                    this.getModel().setValue("nckd_recruitpost", null,iRow);
+                }
+                break;
+            case "nckd_recruitorg":
+                // 部门,判断是否存企业,如果不存在企业则将部门的所属公司带入到企业中
+                this.getModel().setValue("nckd_recruitpost", null,iRow);
+                this.getModel().setValue("nckd_compilation", null,iRow);
+                this.getModel().setValue("nckd_currentnum", null,iRow);
+                this.getModel().setValue("nckd_majortype", null,iRow);
+                this.getModel().setValue("nckd_education", null,iRow);
+                this.getModel().setValue("nckd_payrangemin", null,iRow);
+                this.getModel().setValue("nckd_payrange", null,iRow);
+                this.getModel().setValue("nckd_employcategory", null,iRow);
+                this.getModel().setValue("nckd_recruittype", null,iRow);
+                this.getModel().setValue("nckd_employmentreasons", null,iRow);
+                this.getModel().setValue("nckd_approvednum", null,iRow);
+                this.getModel().setValue("nckd_recruitnum", 0,iRow);
+
+                break;
+            case "nckd_recruitpost":
+                // 岗位,判断是否存企业,如果不存在企业则将部门的所属公司带入到企业中
+                if(isNotEmpty(newValue)){
+                    DynamicObject newValue1 = (DynamicObject) newValue;
+                    if(!checkPosition(newValue1,iRow)){
+                        this.getView().showErrorNotification("已录入相同岗位!"+newValue1.getString("name")+newValue1.getString("number"));
+                        this.getModel().setValue("nckd_recruitpost", null,iRow);
+                        return;
+                    }
+                    // 获取行政组织,和行政组织的所属公司
+                    // 行政组织
+                    DynamicObject nckdRecruitcompany = (DynamicObject)this.getModel().getValue("nckd_recruitorg", iRow);
+                    if(ObjectUtils.isEmpty(nckdRecruitcompany)){
+                        DynamicObject adminorg = newValue1.getDynamicObject("adminorg");
+                        DynamicObjectCollection entryentity = this.getModel().getDataEntity().getDynamicObjectCollection("entryentity");
+                        for (DynamicObject object : entryentity) {
+                            if(newValue1.getString("number").equals(object.getString("nckd_recruitpost.number"))){
+                                object.set("nckd_recruitorg",adminorg);
+                                break;
+                            }
+                        }
+                    }
+                    this.getModel().setValue("nckd_compilation",getFieldValue(newValue1),iRow);
+                    long id = newValue1.getLong("id");
+                    List<Long> longs = new ArrayList<Long>();
+                    longs.add(id);
+                    Map<Long, Set<Long>> allUsersOfPosition = HRPIPersonServiceHelper.getAllUsersOfPosition("1010_S", longs);
+                    int num = 0;
+                    if(ObjectUtils.isNotEmpty(allUsersOfPosition)){
+                        Set<Long> longSet = allUsersOfPosition.get(id);
+                        List<String> zaizhiStatus = Arrays.asList(new String[]{"1020_S","1010_S","1190_S","1050_S","1140_S","1060_S","1120_S","1210_S"});
+                        QFilter qFilter = new QFilter("person.id", QCP.in, longSet)
+                                .and("iscurrentversion",QCP.equals,"1")
+                                .and("businessstatus",QCP.equals,"1")
+                                .and("labrelstatusprd.number",QCP.in,zaizhiStatus);
+
+                        DynamicObject[] hrpiEmpentrels = BusinessDataServiceHelper.load("hrpi_empentrel", "id,person", qFilter.toArray());
+                        num = hrpiEmpentrels.length;
+                    }
+                    this.getModel().setValue("nckd_currentnum",num,iRow);
+                }else{
+                    this.getModel().setValue("nckd_compilation",null,iRow);
+                    this.getModel().setValue("nckd_currentnum",null,iRow);
+                }
+                this.getModel().setValue("nckd_recruitnum",0,iRow);
+                this.getView().updateView("entryentity");
+                break;
+            case "nckd_recruitnum":
+                // 人数字段统计
+                setSumRecruitnum(newValue,iRow);
+                checkRecruitnum(newValue,iRow);
+                break;
+            default:
+                break;
+        }
+
+    }
+
+    // 校验岗位人数是否超编制
+    private void checkRecruitnum(Object recruitnum,int row) {
+        if(recruitnum instanceof Integer){
+            // 获取编制人数
+            Object nckdCompilation = this.getModel().getValue("nckd_compilation",row);
+            if(ObjectUtils.isNotEmpty(nckdCompilation)){
+                Integer integer =  (Integer)nckdCompilation;
+                Integer nckdCurrentnum = (Integer)this.getModel().getValue("nckd_currentnum", row);
+                Integer recruitnum1 =  (Integer)recruitnum;
+                if (integer < (nckdCurrentnum + recruitnum1)){
+                    this.getView().showErrorNotification("最高薪资不能低于最低薪资!");
+                }
+            }
+        }
+    }
+
+    // 获取岗位对应编制人数
+    private Object getFieldValue(DynamicObject nckd_recruitpost) {
+        Object num = null;
+        if(ObjectUtils.isNotEmpty(nckd_recruitpost)){
+            Object nckdSftaff = this.getModel().getValue("nckd_sftaff");
+
+            DynamicObject haosStaff = null;
+            if(ObjectUtils.isNotEmpty(nckdSftaff)){
+                haosStaff = BusinessDataServiceHelper.loadSingle(nckdSftaff,"haos_staff");
+            }else{
+                QFilter qFilter = new QFilter("enable", QCP.equals, "1");
+                DynamicObject[] haosStaffs = BusinessDataServiceHelper.load("haos_staff", "id,name,number", new QFilter[]{qFilter},"year desc");
+                if (haosStaffs != null && haosStaffs.length > 0) {
+                    haosStaff = haosStaffs[0];
+                    this.getModel().setValue("nckd_sftaff",haosStaff.getPkValue());
+                } else {
+                    return null;
+                }
+            }
+
+            Object pkValue = nckd_recruitpost.get("id");
+            QFilter qFilter3 = new QFilter("staff.id", QCP.equals, haosStaff.getPkValue())
+                    .and("enable", QCP.not_equals, "0")
+                    .and("datastatus",QCP.not_equals,"-2")
+                    .and("datastatus",QCP.not_equals,"2")
+                    .and("datastatus",QCP.not_equals,"-1")
+                    .and("dutyworkrole.boid",QCP.equals,pkValue);
+            DynamicObject[] haosDutyorgdetails = BusinessDataServiceHelper.load("haos_muldimendetail", "id,staff,dutyworkrole,dutyworkrole.boid,yearstaff", new QFilter[]{qFilter3});
+            num = haosDutyorgdetails[0].get("yearstaff");
+        }
+        return num;
+    }
+
+    private boolean checkPosition(DynamicObject  newValue,int row) {
+        DynamicObjectCollection entryentity = this.getModel().getDataEntity(true).getDynamicObjectCollection("entryentity");
+        for (int i = 0; i < entryentity.size(); i++) {
+            if(row == i){
+                break;
+            }
+            if(ObjectUtils.isNotEmpty(entryentity.get(i).get("nckd_recruitpost"))){
+                if(entryentity.get(i).get("nckd_recruitpost.number").equals(newValue.get("number"))){
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    // 公司,部门,岗位选择过滤
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent e) {
+        String fieldKey = e.getProperty().getName();
+        switch (fieldKey){
+            case "nckd_recruitcompany":
+                // 企业名称
+                ListShowParameter showParameter = (ListShowParameter)e.getFormShowParameter();
+                //是否展示审核的改为false
+                QFilter qFilter = new QFilter("adminorgtype.number", "in", COMPANY_LIST);
+                showParameter.getListFilterParameter().setFilter(qFilter);
+                break;
+            case "nckd_recruitorg":
+                // 组织名称
+                ListShowParameter showParameter2 = (ListShowParameter)e.getFormShowParameter();
+                // 展示部门,如果选择了企业,展示企业下的部门
+                DynamicObject nckdRecruitcompany = (DynamicObject)this.getModel().getValue("org");
+
+                List<Long> longs = new ArrayList<Long>();
+                Long pkValue = (Long) nckdRecruitcompany.getPkValue();
+                longs.add(pkValue);
+                List<Long> allSubordinateOrgIds = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs, true);
+                // 使用流处理过滤掉指定的值
+//                List<Long> filteredOrgIds = allSubordinateOrgIds.stream()
+//                        .filter(orgId -> !orgId.equals(pkValue)) // 过滤掉值
+//                        .collect(Collectors.toList());
+                QFilter qFilter2 = new QFilter("belongcompany", QCP.in,allSubordinateOrgIds);
+                showParameter2.getListFilterParameter().setFilter(qFilter2);
+                break;
+            case "nckd_recruitpost":
+                // 岗位名称
+                ListShowParameter showParameter3 = (ListShowParameter)e.getFormShowParameter();
+                // 展示部门,如果选择了企业,展示企业下的部门
+                EntryGrid treeEntryEntity2 = this.getControl("entryentity");
+                int[] rows2 = treeEntryEntity2.getSelectRows();
+                DynamicObject nckdRecruitcompany2 = (DynamicObject)this.getModel().getValue("org");
+
+
+
+                QFilter qFilter1 = new QFilter("adminorg.number", QCP.like, nckdRecruitcompany2.getString("number") + "%");
+                DynamicObject nckdRecruitorg = (DynamicObject)this.getModel().getValue("nckd_recruitorg", rows2[0]);
+                if(ObjectUtils.isNotEmpty(nckdRecruitorg)){
+                    qFilter1.and("adminorg.id", QCP.equals, nckdRecruitorg.getPkValue());
+                }
+                showParameter3.getListFilterParameter().setFilter(qFilter1);
+                break;
+            case "org":
+                ListShowParameter showParameter4 = (ListShowParameter)e.getFormShowParameter();
+                // 去除部门
+                QFilter qFilter4 = new QFilter("orgpattern.number", "in", COMPANY_LIST2);
+                showParameter4.getListFilterParameter().setFilter(qFilter4);
+                break;
+            default:
+                break;
+        }
+    }
+
+
+
+    @Override
+    public void registerListener(EventObject e) {
+        BasedataEdit fieldEdit = (BasedataEdit) this.getView().getControl("nckd_recruitcompany");
+        BasedataEdit fieldEdit2 = (BasedataEdit) this.getView().getControl("nckd_recruitorg");
+        BasedataEdit fieldEdit3 = (BasedataEdit) this.getView().getControl("nckd_recruitpost");
+        BasedataEdit fieldEdit4 = this.getView().getControl("org");
+        this.addItemClickListeners("advcontoolbarap2");
+        fieldEdit.addBeforeF7SelectListener(this);
+        fieldEdit.addBeforeF7SelectListener(this);
+        fieldEdit2.addBeforeF7SelectListener(this);
+        fieldEdit3.addBeforeF7SelectListener(this);
+        fieldEdit4.addBeforeF7SelectListener(this);
+    }
+
+    public void beforeItemClick(BeforeItemClickEvent evt) {
+        super.beforeItemClick(evt);
+        String key = evt.getItemKey();
+        //监听分录引入按钮
+        if (key.equals("nckd_advconbaritemap1")) {
+            DynamicObject dataEntity = this.getModel().getDataEntity();
+            if(!getErrorMsg(dataEntity)){
+                evt.setCancel(true);     // 取消事件,不执行默认的分录引入功能
+                this.getView().showErrorNotification("招聘单位已生成该年度招聘计划,不允许新增该年度招聘计划!");
+            }
+        }
+    }
+
+
+    public static boolean isNotEmpty(Object  key) {
+        // 基础资料判空
+        if(ObjectUtils.isEmpty(key) || ObjectUtils.isEmpty(((DynamicObject)key).getDataStorage())){
+            return false;
+        }
+        return true;
+    }
+
+    public void setSumRecruitnum(Object newValue,int row){
+        // 计算招聘人数,获取出所有分录,然后统计所有分录的招聘人数累加
+        DynamicObjectCollection entryEntity = this.getModel().getEntryEntity("entryentity");
+        int num = 0;
+        for (int i = 0; i < entryEntity.size(); i++) {
+            if(row == i){
+                num = num + (Integer) newValue;
+            }else{
+                num = num + (Integer) entryEntity.get(i).get("nckd_recruitnum");
+            }
+        }
+        this.getModel().setValue("nckd_applynum", num);
+    }
+
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate opreate = (FormOperate) args.getSource();
+        switch (opreate.getOperateKey()) {
+            case "submit":
+                // 先校验岗位是否重复
+//                String errorMsg1 = checkPosition();
+//                if(StringUtils.isNotBlank(errorMsg1)){
+//                    args.setCancel(true);
+//                    this.getView().showErrorNotification("年度招聘申请单(单据编号):" + errorMsg1 +"中存在相同岗位!\n");
+//                    return;
+//                }
+//
+//                // 判断是否存在年度招聘计划
+//                StringBuilder errorMsg = new StringBuilder();
+//                DynamicObject org =(DynamicObject) this.getModel().getValue("org");
+//                DynamicObject dataEntity = this.getModel().getDataEntity();
+//                if(!getErrorMsg(dataEntity)){
+//                    errorMsg.append("招聘单位:"+org.getString("org.name")+":已生成该年度招聘计划,不允许新增该年度招聘计划!\n");
+//                }
+
+                String errorMessage = vaildatorPayrange();
+                if(StringUtils.isNotEmpty(errorMessage)){
+                    this.getView().showErrorNotification(errorMessage);
+                    args.setCancel(true);
+                    return;
+                }
+                StringBuilder errorMsg = new StringBuilder();
+                // 在此添加处理逻辑
+                Object nckdSftaffcount1 = this.getModel().getValue("nckd_sftaffcount");
+                if(ObjectUtils.isNotEmpty(nckdSftaffcount1)){
+
+                    int nckdSftaffcount = (int) this.getModel().getValue("nckd_sftaffcount");
+                    // 实际人数
+                    int nckdRelnum = (int) this.getModel().getValue("nckd_relnum");
+                    // 申请人数
+                    int nckdApplynum = (int) this.getModel().getValue("nckd_applynum");
+                    if(ObjectUtils.isNotEmpty(errorMsg)){
+                        args.setCancel(true);
+                        this.getView().showErrorNotification(errorMsg.toString());
+                        return;
+                    }
+                    if(nckdApplynum>0){
+                        if(nckdSftaffcount < nckdRelnum + nckdApplynum){
+                            // 判断是否处理过
+                            String isDealed = this.getView().getPageCache().get("isDealed");
+                            if (!"true".equals(isDealed)) {
+                                // 取消原来的操作
+                                args.setCancel(true);
+                                // 在用户点击确认框上的按钮后,系统会调用confirmCallBack方法
+                                ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener("isExceed", this);
+                                // 设置页面确认框,参数为:标题,选项框类型,回调监听
+                                this.getView().showConfirm("请注意,申请人数超编,是否继续提报?", MessageBoxOptions.YesNo, confirmCallBackListener);
+                                // 只执行一次
+                                this.getView().getPageCache().put("isDealed", "true");
+                            }
+                        }
+                    }
+
+                }
+                break;
+            case "save":
+                String errorMessage2 = vaildatorPayrange();
+                if(StringUtils.isNotEmpty(errorMessage2)){
+                    this.getView().showErrorNotification(errorMessage2);
+                    args.setCancel(true);
+                    return;
+                }
+                // 先校验岗位是否重复
+//                String errorMsg2 = checkPosition();
+//                if(StringUtils.isNotBlank(errorMsg2)){
+//                    args.setCancel(true);
+//                    this.getView().showErrorNotification("年度招聘申请单(单据编号):" + errorMsg2 +"中存在相同岗位!\n");
+//                    return;
+//                }
+
+//                if(!getErrorMsg(this.getModel().getDataEntity())){
+//                    args.setCancel(true);
+//                    DynamicObject org2 =(DynamicObject) this.getModel().getValue("org");
+//                    this.getView().showErrorNotification("招聘单位:"+org2.getString("org.name")+":已生成该年度招聘计划,不允许新增该年度招聘计划!\n");
+//                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    private String vaildatorPayrange(){
+        DynamicObjectCollection entryentity = this.getModel().getDataEntity(true).getDynamicObjectCollection("entryentity");
+        StringBuilder errorBuilder = new StringBuilder();
+        for (DynamicObject object : entryentity) {
+            int nckdPayrange = object.getInt("nckd_payrange");
+            int nckdPayrangemin = object.getInt("nckd_payrangemin");
+            if(nckdPayrange < nckdPayrangemin){
+                errorBuilder.append(object.get("seq"));
+            }
+        }
+        if(ObjectUtils.isNotEmpty(errorBuilder)){
+            errorBuilder.append("行,最高薪资不能低于最低薪资!");
+        }
+        return errorBuilder.toString();
+
+    }
+
+    private String checkPosition() {
+        // 获取岗位编码,筛选掉 单据状态为 E:审批不通过的状态
+        List<String> postNumber = getPostNumber();
+        Object nckdYear = this.getModel().getValue("nckd_year");
+        Object billno = this.getModel().getValue("billno");
+        QFilter qFilter = new QFilter("billstatus", QCP.not_equals, "E")
+                .and("nckd_year", QCP.equals, nckdYear)
+                .and("billno",QCP.not_equals,billno);
+        QFilter qFilter1 = new QFilter("entryentity.nckd_recruitpost.number", QCP.in, postNumber);
+        DynamicObject[] nckdYearapplies = BusinessDataServiceHelper.load("nckd_yearapply", "id,billno,nckd_name,nckd_year,entryentity,entryentity.nckd_recruitpost", new QFilter[]{qFilter, qFilter1});
+        StringBuilder errorMsg = new StringBuilder();
+        for (DynamicObject nckdYearapply : nckdYearapplies) {
+            errorMsg.append(nckdYearapply.getString("billno")+",");
+        }
+        return errorMsg.toString();
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+        this.getView().getPageCache().remove("isDealed");
+    }
+
+    @Override
+    public void confirmCallBack(MessageBoxClosedEvent messageBoxClosedEvent) {
+        //判断回调参数id
+        if ("isExceed".equals(messageBoxClosedEvent.getCallBackId())) {
+            if (MessageBoxResult.Yes.equals(messageBoxClosedEvent.getResult())) {
+                this.getView().invokeOperation("submit");
+            } else if (MessageBoxResult.No.equals(messageBoxClosedEvent.getResult())) {
+                // 点击否也清除
+                this.getView().getPageCache().remove("isDealed");
+            }
+        }
+    }
+
+    // 判断组织是否存在年度招聘计划表
+    public  boolean getErrorMsg(DynamicObject dynamicObject){
+        Object nckdYear = dynamicObject.get("nckd_year");
+        QFilter nckdYear1 = new QFilter("nckd_year", QCP.equals, nckdYear);
+        QFilter qBillstatus = new QFilter("billstatus", QCP.equals, "C");
+        QFilter qFilter = new QFilter("org.id", QCP.equals, dynamicObject.getDynamicObject("org").getPkValue());
+        DynamicObject dynamicObject1 = BusinessDataServiceHelper.loadSingle("nckd_yearcasreplan", "id,org,org.id,billstatus,nckd_year", new QFilter[]{nckdYear1,qBillstatus,qFilter});
+        if(ObjectUtils.isNotEmpty(dynamicObject1)){
+            return false;
+        }
+        return true;
+    }
+
+
+}

+ 130 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyListPlugin.java

@@ -0,0 +1,130 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.form;
+
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.EntityType;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.MessageBoxResult;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.MessageBoxClosedEvent;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.list.BillList;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import org.apache.commons.lang3.ObjectUtils;
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-年度招聘申请
+ * Description      :年度招聘申请列表插件
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_casrecrapply
+ */
+
+
+
+public class YearCrApplyListPlugin extends AbstractListPlugin {
+
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate opreate = (FormOperate) args.getSource();
+        switch (opreate.getOperateKey()) {
+            case "submit":
+                ListSelectedRowCollection selectCols = args.getListSelectedData();
+                StringBuffer exceedMsg = new StringBuffer();
+                StringBuffer errorMsg = new StringBuffer();
+                Object[] primaryKeyValues  = selectCols.getPrimaryKeyValues();
+                BillList billlistap = this.getView().getControl("billlistap");
+                EntityType entityType = billlistap.getEntityType();
+                //获取完整数据
+                DynamicObject[] casPaybillArr = BusinessDataServiceHelper.load(primaryKeyValues, entityType);
+                for (int i = 0; i < casPaybillArr.length; i++) {
+                    // 在此添加处理逻辑
+                    DynamicObject dynamicObject = casPaybillArr[i];
+                    // 获取组织,根据组织查询年度招聘计划表,判断该组织是否存在年度招聘计划表
+//                    if(!getErrorMsg(dynamicObject)){
+//                        errorMsg.append("招聘单位:"+dynamicObject.getString("org.name")+":已生成该年度招聘计划,不允许提交该年度招聘申请!\n");
+//                        continue;
+//                    }
+                    Object nckdSftaffcount1 = dynamicObject.get("nckd_sftaffcount");
+                    if(ObjectUtils.isNotEmpty(nckdSftaffcount1)){
+                        int nckdSftaffcount = dynamicObject.getInt("nckd_sftaffcount");
+                        // 实际人数
+                        int nckdRelnum = dynamicObject.getInt("nckd_relnum");
+                        // 申请人数
+                        int nckdApplynum = dynamicObject.getInt("nckd_applynum");
+
+                        if(nckdSftaffcount < nckdRelnum + nckdApplynum){
+                            // 判断是否处理过
+                            String isDealed = this.getView().getPageCache().get("isDealed");
+                            if (!"true".equals(isDealed)) {
+                                if(ObjectUtils.isEmpty(exceedMsg)){
+                                    exceedMsg.append("单据:");
+                                }
+                                exceedMsg.append(dynamicObject.getString("billno")+",");
+                            }
+                        }
+                    }
+
+                }
+                if(ObjectUtils.isNotEmpty(errorMsg)){
+                    args.setCancel(true);
+                    this.getView().showErrorNotification(errorMsg.toString());
+                    return;
+                }
+                if(ObjectUtils.isNotEmpty(exceedMsg)){
+                    args.setCancel(true);
+                    exceedMsg.append("请注意,申请人数超编,是否继续提报?");
+                    ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener("isExceed", this);
+                    // 设置页面确认框,参数为:标题,选项框类型,回调监听
+                    this.getView().showConfirm(exceedMsg.toString(), MessageBoxOptions.YesNo, confirmCallBackListener);
+                    // 只执行一次
+                    this.getView().getPageCache().put("isDealed", "true");
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    // 判断组织是否存在年度招聘计划表
+    public  boolean getErrorMsg(DynamicObject dynamicObject){
+        Object nckdYear = dynamicObject.get("nckd_year");
+        QFilter nckdYear1 = new QFilter("nckd_year", QCP.equals, nckdYear);
+        QFilter qBillstatus = new QFilter("billstatus", QCP.equals, "C");
+        QFilter qFilter = new QFilter("org.id", QCP.equals, dynamicObject.getDynamicObject("org").getPkValue());
+        DynamicObject dynamicObject1 = BusinessDataServiceHelper.loadSingle("nckd_yearcasreplan", "id,org,org.id", new QFilter[]{nckdYear1, qBillstatus, qFilter});
+        if(ObjectUtils.isNotEmpty(dynamicObject1)){
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+        // 清除
+        this.getView().getPageCache().remove("isDealed");
+    }
+
+    @Override
+    public void confirmCallBack(MessageBoxClosedEvent messageBoxClosedEvent) {
+        //判断回调参数id
+        if ("isExceed".equals(messageBoxClosedEvent.getCallBackId())) {
+            if (MessageBoxResult.Yes.equals(messageBoxClosedEvent.getResult())) {
+                this.getView().invokeOperation("submit");
+            } else if (MessageBoxResult.No.equals(messageBoxClosedEvent.getResult())) {
+                // 点击否也清除
+                this.getView().getPageCache().remove("isDealed");
+            }
+        }
+    }
+
+}

+ 441 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyPlanFormPlugin.java

@@ -0,0 +1,441 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.form;
+
+
+import kd.bos.algo.DataSet;
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.db.DBRoute;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.LoadDataEventArgs;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.control.events.BeforeItemClickEvent;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.field.BasedataEdit;
+import kd.bos.form.field.events.BeforeF7SelectEvent;
+import kd.bos.form.field.events.BeforeF7SelectListener;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.list.ListShowParameter;
+import kd.bos.orm.ORM;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.org.OrgUnitServiceHelper;
+import kd.hr.hbp.common.util.HRDBUtil;
+import nckd.jimin.jyyy.hr.tsrsc.plugin.util.RecUtils;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-年度招聘计划
+ * Description      :年度招聘计划单据插件
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_yearcasreplan
+ */
+
+
+public class YearCrApplyPlanFormPlugin extends AbstractBillPlugIn implements BeforeF7SelectListener {
+
+    // 公司类型
+    private final List<String> COMPANY_LIST = Arrays.asList(new String[]{"1020_S", "1050_S", "1060_S", "1070_S"});
+
+    private final List<String> COMPANY_LIST2 = Arrays.asList(new String[]{"Orgform01", "Orgform01-100", "Orgform02", "Orgform03","Orgform04"});
+
+    // 定义日期格式
+    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        super.afterCreateNewData(e);
+    }
+
+    @Override
+    public void beforeBindData(EventObject e) {
+        super.beforeBindData(e);
+        //  组织id
+//        Long pkValue = (Long) org.getPkValue();
+        Object billstatus = this.getModel().getValue("billstatus");
+        // 暂存状态才发生变化
+        if(ObjectUtils.equals(billstatus,"A")){
+            DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+            updateStaffCount();
+            // 实际人数
+            this.getModel().setValue("nckd_relnum", RecUtils.getStaffCount(org.getPkValue()));
+        }
+
+    }
+
+    // 获取组织编制人数
+    private void updateStaffCount() {
+
+        DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+        //  组织id
+        Long pkValue = (Long) org.getPkValue();
+        List<Long> longs = new ArrayList<Long>();
+        longs.add(pkValue);
+        QFilter qFilter = new QFilter("boid", QCP.equals, pkValue);
+        // 获取组织历史查询
+        DynamicObjectCollection query = QueryServiceHelper.query("haos_adminorgdetail", "id,boid,hisversion", new QFilter[]{qFilter}, "hisversion desc");
+        if (ObjectUtils.isNotEmpty(query)) {
+            long boid = query.get(0).getLong("id");
+            // 获取填写的年度 nckd_year
+            Object nckdYear = this.getModel().getValue("nckd_year");
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
+
+            if (ObjectUtils.isEmpty(nckdYear)) {
+                nckdYear = new Date();
+            } else {
+                nckdYear = (Date) nckdYear;
+            }
+            String dateStr = sdf.format(nckdYear);
+//            QFilter qFilter2 = new QFilter("staff.year", QCP.like, dateStr + "%");
+            QFilter qFilter1 = new QFilter("dutyorg.id", QCP.equals, boid);
+
+            DynamicObject[] haosDutyorgdetail = BusinessDataServiceHelper.load("haos_dutyorgdetail", "id,dutyorg,staff,staffcount", new QFilter[]{qFilter1});
+            if (ObjectUtils.isNotEmpty(haosDutyorgdetail)) {
+                for (DynamicObject dynamicObject : haosDutyorgdetail) {
+                    String format = sdf.format(dynamicObject.getDate("staff.year"));
+                    if (dateStr.equals(format)) {
+                        int staffcount = dynamicObject.getInt("staffcount");
+                        this.getModel().setValue("nckd_sftaffcount", staffcount);
+                        return;
+                    }
+                }
+            }
+            this.getModel().setValue("nckd_sftaffcount", null);
+
+//            int staffcount = ObjectUtils.isNotEmpty(haosDutyorgdetail) ? haosDutyorgdetail.getInt("staffcount"):null;
+//            this.getModel().setValue("nckd_sftaffcount",staffcount);
+
+        }
+
+    }
+
+    @Override
+    public void loadData(LoadDataEventArgs e) {
+        super.loadData(e);
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+        String key = e.getProperty().getName();
+        ChangeData[] changeData = e.getChangeSet();
+        Object newValue = changeData[0].getNewValue();
+        Object oldValue = changeData[0].getOldValue();
+        int iRow = changeData[0].getRowIndex();
+        switch (key) {
+            case "nckd_recruitnum":
+                // 人数字段统计
+                setSumRecruitnum(newValue, iRow);
+                break;
+            default:
+                break;
+        }
+
+    }
+
+    // 公司,部门,岗位选择过滤
+    @Override
+    public void beforeF7Select(BeforeF7SelectEvent e) {
+        String fieldKey = e.getProperty().getName();
+        switch (fieldKey) {
+            case "org":
+                ListShowParameter showParameter4 = (ListShowParameter) e.getFormShowParameter();
+                // 去除部门
+                QFilter qFilter4 = new QFilter("orgpattern.number", "in", COMPANY_LIST2);
+                showParameter4.getListFilterParameter().setFilter(qFilter4);
+                break;
+            default:
+                break;
+        }
+    }
+
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+        // 添加对分录按钮的监听
+        this.addItemClickListeners("advcontoolbarap");
+        BasedataEdit fieldEdit = this.getView().getControl("org");
+        fieldEdit.addBeforeF7SelectListener(this);
+    }
+
+
+    @Override
+    public void beforeItemClick(BeforeItemClickEvent evt) {
+        super.beforeItemClick(evt);
+        String key = evt.getItemKey();
+        //监听分录刷新招聘申请按钮
+        if (key.equals("nckd_advconbaritemap1")) {
+            DynamicObjectCollection entryentity = this.getModel().getDataEntity(true).getDynamicObjectCollection("entryentity");
+            // 获取年度
+            Object nckdYear = this.getModel().getValue("nckd_year");
+            if (ObjectUtils.isEmpty(nckdYear)) {
+                this.getView().showErrorNotification("请先填写年度");
+                return;
+            }
+            entryentity.clear();
+            // 删除分录数据,然后使用表单组织去拉去年度招聘计划中的数据,然后获取他的下级分录,然后添加到本单据分录中,然后刷新本单分录
+            DynamicObject org = (DynamicObject) this.getModel().getValue("org");
+            QFilter nckdYear1 = new QFilter("nckd_year", QCP.equals, nckdYear);
+            QFilter qBillstatus = new QFilter("billstatus", QCP.equals, "C");
+            List<Long> longs = new ArrayList<Long>();
+            longs.add((Long) org.getPkValue());
+            // 获取组织历史查询
+            List<Long> allSubordinateOrgs = OrgUnitServiceHelper.getAllSubordinateOrgs("01", longs, true);
+            QFilter qFilter = new QFilter("org.id", QCP.in, allSubordinateOrgs);
+            Object pkValue = this.getModel().getDataEntity(true).getPkValue();
+            List<String> strings = Arrays.asList(new String[]{"B", "C"});
+            QFilter summary = new QFilter("entryentity.nckd_summary", QCP.not_in, strings);
+            if (ObjectUtils.isNotEmpty(pkValue)) {
+                summary.or("entryentity.nckd_casreplanid", QCP.equals, pkValue);
+            }
+            qFilter.and(summary);
+            // 年度招聘计划数据
+            DynamicObject[] loads = BusinessDataServiceHelper.load("nckd_yearapply", "id,org,org.id,billstatus,entryentity,entryentity.nckd_recruitorg," +
+                    "entryentity.nckd_recruitpost,entryentity.nckd_recruitnum,entryentity.nckd_majortype,entryentity.nckd_qualifications," +
+                    "entryentity.nckd_payrange,entryentity.nckd_employcategory,entryentity.nckd_recruittype,nckd_year,entryentity.nckd_summary," +
+                    "entryentity.nckd_casreplanid,entryentity.nckd_payrangemin,entryentity.nckd_education,entryentity.nckd_compilation," +
+                    "entryentity.nckd_currentnum,entryentity.nckd_employmentreasons", new QFilter[]{nckdYear1, qFilter, qBillstatus});
+            if (ObjectUtils.isEmpty(loads)) {
+                return;
+            }
+            ORM orm = ORM.create();
+            for (DynamicObject dynamicObject : loads) {
+                // 获取招聘计划的下级分录
+                DynamicObjectCollection entryentity1 = dynamicObject.getDynamicObjectCollection("entryentity");
+                if (ObjectUtils.isEmpty(entryentity1)) {
+                    continue;
+                }
+                for (DynamicObject object : entryentity1) {
+                    Object nckdCasreplanid = object.get("nckd_casreplanid");
+                    String nckdSummary = object.getString("nckd_summary");
+
+                    if (ObjectUtils.isEmpty(nckdCasreplanid) || nckdCasreplanid.equals(pkValue) || !strings.contains(nckdSummary)) {
+                        DynamicObject dynamicObjentryrow = entryentity.addNew();
+                        // 招聘单位
+                        dynamicObjentryrow.set("nckd_recruitcompany", dynamicObject.getDynamicObject("org"));
+                        dynamicObjentryrow.set("nckd_recruitorg", object.getDynamicObject("nckd_recruitorg"));
+                        dynamicObjentryrow.set("nckd_recruitpost", object.get("nckd_recruitpost"));
+                        dynamicObjentryrow.set("nckd_recruitnum", object.get("nckd_recruitnum"));
+                        dynamicObjentryrow.set("nckd_approvednum", object.get("nckd_recruitnum"));
+                        // 1专业类别
+                        StringBuilder sqlBuilder = new StringBuilder("SELECT m.fbasedataid FROM tk_nckd_yearcrapp_major m WHERE m.fentryid = ?");
+                        // 2 学历
+                        StringBuilder sqlBuilder2 = new StringBuilder("SELECT m.fbasedataid FROM tk_nckd_yearcrapp_qualifi m WHERE m.fentryid = ?");
+
+                        Object[] param = new Object[]{object.getPkValue()};
+                        DataSet rows = HRDBUtil.queryDataSet("tk_nckd_yearcrapp_major", new DBRoute("tsc"), sqlBuilder.toString(), param);
+
+                        DataSet rows2 = HRDBUtil.queryDataSet("tk_nckd_yearcrapp_qualifi", new DBRoute("tsc"), sqlBuilder2.toString(), param);
+
+                        // 多选基础资料key
+                        DynamicObjectCollection retDynCol = orm.toPlainDynamicObjectCollection(rows);
+                        MainEntityType type = EntityMetadataCache.getDataEntityType("nckd_specialityclass");
+                        DynamicObjectCollection newColList = dynamicObjentryrow.getDynamicObjectCollection("nckd_majortype");
+
+                        DynamicObjectCollection retDynCol2 = orm.toPlainDynamicObjectCollection(rows2);
+                        MainEntityType type2 = EntityMetadataCache.getDataEntityType("hbss_diploma");
+                        DynamicObjectCollection newColList2 = dynamicObjentryrow.getDynamicObjectCollection("nckd_qualifications");
+
+                        if (ObjectUtils.isNotEmpty(retDynCol)) {
+                            // 创建多选基础资料,
+                            for (DynamicObject dynamicObject1 : retDynCol) {
+                                DynamicObject dynamicObject2 = newColList.addNew();
+                                dynamicObject2.set("fbasedataId", BusinessDataServiceHelper.loadSingle(dynamicObject1.get("fbasedataid"), type));
+                            }
+                        }
+                        if (ObjectUtils.isNotEmpty(retDynCol2)) {
+                            // 创建多选基础资料,
+                            for (DynamicObject dynamicObject2 : retDynCol2) {
+                                DynamicObject dynamicObject3 = newColList2.addNew();
+                                dynamicObject3.set("fbasedataId", BusinessDataServiceHelper.loadSingle(dynamicObject2.get("fbasedataid"), type2));
+                            }
+                        }
+                        dynamicObjentryrow.set("nckd_payrange", object.get("nckd_payrange"));
+                        dynamicObjentryrow.set("nckd_payrangemin", object.get("nckd_payrangemin"));
+                        dynamicObjentryrow.set("nckd_employcategory", object.get("nckd_employcategory"));
+                        dynamicObjentryrow.set("nckd_recruittype", object.get("nckd_recruittype"));
+                        dynamicObjentryrow.set("nckd_yearapplyid", dynamicObject.getPkValue());
+                        dynamicObjentryrow.set("nckd_yearapplyentryid", object.getPkValue());
+                        dynamicObjentryrow.set("nckd_education", object.get("nckd_education"));
+                        dynamicObjentryrow.set("nckd_employmentreasons", object.get("nckd_employmentreasons"));
+                        dynamicObjentryrow.set("nckd_compilation", object.get("nckd_compilation"));
+                        dynamicObjentryrow.set("nckd_currentnum", object.get("nckd_currentnum"));
+
+                    }
+
+                }
+            }
+            // 计算人数
+            setSumRecruitnum(0, -1);
+            getView().updateView("entryentity");
+
+        }
+    }
+
+
+    // 校验
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate opreate = (FormOperate) args.getSource();
+//        switch (opreate.getOperateKey()) {
+//            case "save":
+//            case "submit":
+//                DynamicObject dataEntity = this.getModel().getDataEntity(true);
+//                if (!getErrorMsg(dataEntity)) {
+//                    args.setCancel(true);
+//                }
+//                break;
+//            default:
+//                break;
+//        }
+    }
+
+    public boolean getErrorMsg(DynamicObject dynamicObject) {
+        Object nckdYear = dynamicObject.get("nckd_year");
+        String billno = dynamicObject.getString("billno");
+        QFilter nckdYear1 = new QFilter("nckd_year", QCP.equals, nckdYear);
+        QFilter qBillstatus = new QFilter("billstatus", QCP.equals, "C");
+        qBillstatus.and("billno", QCP.not_equals, billno);
+        QFilter qFilter = new QFilter("org.id", QCP.equals, dynamicObject.getDynamicObject("org").getPkValue());
+        DynamicObject dynamicObject1 = BusinessDataServiceHelper.loadSingle("nckd_yearcasreplan", "id,org,org.id", new QFilter[]{nckdYear1, qBillstatus, qFilter});
+        if (ObjectUtils.isNotEmpty(dynamicObject1)) {
+            return false;
+        }
+        return true;
+    }
+
+    private boolean planValidator(DynamicObject org) {
+        Object nckdYear = this.getModel().getValue("nckd_year");
+        QFilter nckdYear1 = new QFilter("nckd_year", QCP.equals, nckdYear);
+        QFilter qBillstatus = new QFilter("billstatus", QCP.equals, "C");
+        // 获取所有下级组织 org.getPkValue()
+        String selectFields = "id,org,org.id,org.name,longnumber,parent,orgpattern";
+        QFilter numberFilter = new QFilter("number", "=", "01");
+        DynamicObject viewObj = BusinessDataServiceHelper.loadSingleFromCache("bos_org_viewschema", "id", new QFilter[]{numberFilter});
+        QFilter viewFilter = new QFilter("view", "=", viewObj.getPkValue());
+        QFilter viewFilter2 = new QFilter("parent.id", "=", org.getPkValue());
+        QFilter[] filters = new QFilter[]{viewFilter, viewFilter2};
+        // 获取组织所有直属下级组织
+        DynamicObject[] bosOrgStructures = BusinessDataServiceHelper.load("bos_org_structure", selectFields, filters);
+        if (ObjectUtils.isNotEmpty(bosOrgStructures)) {
+            // 存在下级组织,使用下级组织查询
+            Set<Long> allSubOrgIds = new HashSet(10000);
+            for (int i = 0; i < bosOrgStructures.length; i++) {
+                allSubOrgIds.add((Long) bosOrgStructures[i].get("org.id"));
+            }
+            QFilter qFilter4 = new QFilter("orgpattern.number", "in", COMPANY_LIST2).and("id", QCP.in, allSubOrgIds);
+            DynamicObject[] bosOrgs = BusinessDataServiceHelper.load("bos_org", "id,name,orgpattern", new QFilter[]{qFilter4});
+            Set<Long> allSubOrgIds2 = new HashSet(10000);
+            for (DynamicObject bosOrg : bosOrgs) {
+                allSubOrgIds2.add((Long) bosOrg.get("id"));
+            }
+            // 获取所有下级组织的招聘计划
+            QFilter bosOrgFilter = new QFilter("org.id", QCP.in, allSubOrgIds2);
+            StringBuilder errBuilder = new StringBuilder();
+            DynamicObject[] nckdYearcasreplans = BusinessDataServiceHelper.load("nckd_yearcasreplan", "id,org", new QFilter[]{nckdYear1, bosOrgFilter, qBillstatus});
+            if (ObjectUtils.isEmpty(nckdYearcasreplans)) {
+                errBuilder.append("直属下级组织未配置完年度招聘计划");
+            } else {
+                Map<Object, DynamicObject> resultMap = Arrays.stream(nckdYearcasreplans)
+                        .collect(Collectors.toMap(
+                                obj -> obj.get("org.id"), // 使用 org.id 作为 key
+                                obj -> obj, // 使用 DynamicObject 本身作为 value
+                                (existing, replacement) -> existing // 如果键冲突,保留现有值
+                        ));
+                for (DynamicObject bosOrgStructure : bosOrgStructures) {
+                    DynamicObject dynamicObject = resultMap.get(bosOrgStructure.get("org.id"));
+                    if (ObjectUtils.isEmpty(dynamicObject)) {
+                        errBuilder.append("组织[" + bosOrgStructure.get("org.name") + "]未配置完年度招聘计划");
+                    }
+                }
+            }
+            if (ObjectUtils.isNotEmpty(errBuilder)) {
+                // 未通过校验
+                this.getView().showErrorNotification(errBuilder.toString());
+                return false;
+            }
+
+        }
+
+        return true;
+    }
+
+
+    public static boolean isNotEmpty(Object key) {
+        // 基础资料判空
+        if (ObjectUtils.isEmpty(key) || ObjectUtils.isEmpty(((DynamicObject) key).getDataStorage())) {
+            return false;
+        }
+        return true;
+    }
+
+
+    // 获取组织对应人员编制总数(包含下级)
+    public static int getStaffCount(Object orgId) {
+
+        Date date = new Date();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        String dateStr = sdf.format(date);
+
+        // 拼接 SQL 查询
+        // 拼接 SQL 查询 haos_stafforgempcount
+        StringBuilder sql = new StringBuilder("SELECT DISTINCT T.fstructlongnumber,ST.fcount as count "
+                + "FROM T_HAOS_ADMINORG A "
+                + "LEFT JOIN T_HAOS_ADMINSTRUCT T ON a.fboid = T.fadminorgid "
+                + "left join T_HAOS_STAFFORGEMPCOUNT ST on A.fboid = ST.fuseorgboid "
+                + "WHERE A.fiscurrentversion = '0' AND A.fdatastatus = '1' AND A.finitstatus = '2' "
+                + "AND T.fiscurrentversion = '0' AND T.fdatastatus = '1' AND T.fstructprojectid = 1010 "
+                + "AND T.finitstatus = '2' AND T.fbsed <= '" + dateStr + "' "
+                + "AND T.fbsled >= '" + dateStr + "' AND T.fenable = '1' "
+                + "AND A.fbsed <= '" + dateStr + "' AND A.fbsled >= '" + dateStr + "' "
+                + "AND A.fenable = '1' "
+                + "AND ( T.fstructlongnumber LIKE ( select top 1 concat(F.fstructlongnumber,'%')  from  T_HAOS_ADMINSTRUCT F where  F.fadminorgid = ? "
+                + "AND F.fiscurrentversion = '0' AND F.fdatastatus = '1' AND F.fstructprojectid = 1010 "
+                + "AND F.finitstatus = '2' AND F.fbsed <= '" + dateStr + "' "
+                + "AND F.fbsled >= '" + dateStr + "' AND F.fenable = '1' "
+                + ") " + ") "
+        );
+        Object[] param = new Object[]{(Long) orgId};
+        DataSet dataSet = HRDBUtil.queryDataSet("haos_adminOrgHisSearch", new DBRoute("hr"), sql.toString(), param);
+
+        ORM orm = ORM.create();
+        DynamicObjectCollection retDynCol = orm.toPlainDynamicObjectCollection(dataSet);
+        // 获取实际人数
+        AtomicInteger nckdRellownum2 = new AtomicInteger(0);
+        retDynCol.forEach(dynObj -> {
+            int count = dynObj.getInt("count");
+            if (ObjectUtils.isNotEmpty(count)) {
+                nckdRellownum2.addAndGet(count);
+            }
+        });
+        return nckdRellownum2.get();
+    }
+
+    public void setSumRecruitnum(Object newValue, int row) {
+        // 计算招聘人数,获取出所有分录,然后统计所有分录的招聘人数累加
+        DynamicObjectCollection entryEntity = this.getModel().getEntryEntity("entryentity");
+        int num = 0;
+        for (int i = 0; i < entryEntity.size(); i++) {
+            if (row == i) {
+                num = num + (Integer) newValue;
+            } else {
+                num = num + (Integer) entryEntity.get(i).get("nckd_recruitnum");
+            }
+        }
+        this.getModel().setValue("nckd_applynum", num);
+    }
+
+}

+ 68 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/form/YearCrApplyPlanListPlugin.java

@@ -0,0 +1,68 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.form;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.EntityType;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.list.BillList;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import org.apache.commons.lang3.ObjectUtils;
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-年度招聘计划
+ * Description      :年度招聘计划列表插件
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_yearcasreplan
+ */
+
+public class YearCrApplyPlanListPlugin extends AbstractListPlugin {
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate opreate = (FormOperate) args.getSource();
+        switch (opreate.getOperateKey()) {
+            case "submit":
+            case "save":
+//                ListSelectedRowCollection selectCols = args.getListSelectedData();
+//                StringBuffer exceedMsg = new StringBuffer();
+//                StringBuffer errorMsg = new StringBuffer();
+//                Object[] primaryKeyValues = selectCols.getPrimaryKeyValues();
+//                BillList billlistap = this.getView().getControl("billlistap");
+//                EntityType entityType = billlistap.getEntityType();
+//                //获取完整数据
+//                DynamicObject[] casPaybillArr = BusinessDataServiceHelper.load(primaryKeyValues, entityType);
+//                for (DynamicObject dynamicObject : casPaybillArr) {
+//                    if(!getErrorMsg(dynamicObject)){
+//                        errorMsg.append("招聘单位:"+dynamicObject.getString("org.name")+":已生成该年度招聘计划,请勿重复生成!\n");
+//                    }
+//                }
+//                if(ObjectUtils.isNotEmpty(errorMsg)){
+//                    args.setCancelMessage(exceedMsg.toString());
+//                    args.setCancel(true);
+//                }
+        }
+
+    }
+
+    public  boolean getErrorMsg(DynamicObject dynamicObject){
+        Object nckdYear = dynamicObject.get("nckd_year");
+        String billno = dynamicObject.getString("billno");
+        QFilter nckdYear1 = new QFilter("nckd_year", QCP.equals, nckdYear);
+        QFilter qBillstatus = new QFilter("billstatus", QCP.equals, "C");
+        qBillstatus.and("billno",QCP.not_equals,billno);
+        QFilter qFilter = new QFilter("org.id", QCP.equals, dynamicObject.getDynamicObject("org").getPkValue());
+        DynamicObject dynamicObject1 = BusinessDataServiceHelper.loadSingle("nckd_yearcasreplan", "id,org,org.id", new QFilter[]{nckdYear1, qBillstatus, qFilter});
+        if(ObjectUtils.isNotEmpty(dynamicObject1)){
+            return false;
+        }
+        return true;
+    }
+
+
+}

+ 61 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/CasRecrApplyUnAuditValidator.java

@@ -0,0 +1,61 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.operate;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * description: 年度招聘计划校验插件,反审核校验器
+ * nckd_yearapply
+ * @author Tyx
+ * @date  2025/5/8
+ */
+
+public class CasRecrApplyUnAuditValidator extends AbstractOperationServicePlugIn {
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        // 提前加载表单里的字段
+        List<String> fieldKeys = e.getFieldKeys();
+        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+        e.addValidator(new AbstractValidator() {
+            @Override
+            public void validate() {
+                ExtendedDataEntity[] dataEntities = this.getDataEntities();
+
+                for (ExtendedDataEntity dataEntity : dataEntities) {
+                    DynamicObject dynamicObject = dataEntity.getDataEntity();
+                    DynamicObjectCollection entryentity = dynamicObject.getDynamicObjectCollection("entryentity");
+                    if(entryentity.size() > 0){
+                        List<String> objectList = entryentity.stream()
+                                .map(entry -> {
+                                    return String.valueOf(entry.getPkValue());
+                                })
+                                .collect(Collectors.toList());
+                        DynamicObject[] load = BusinessDataServiceHelper.load("tstpm_srscarfmrsm", "id", (new QFilter("nckd_mokahcnum", QCP.in, objectList)).toArray());
+                        if(load.length > 0){
+                            this.addErrorMessage(dataEntity, "已存在候选人信息,不允许反审核!");
+                            break;
+                        }
+                    }
+                }
+            }
+        });
+    }
+}

+ 86 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/CasRecrApplyWorkFlowPlugin.java

@@ -0,0 +1,86 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.operate;
+
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * Module           :人才供应云-招聘直通车-首页-临时招聘申请
+ * Description      :审批流按钮操作插件
+ * @author Tyx
+ * @date  2025/05/08
+ * 标识 nckd_casrecrapply
+ */
+
+public class CasRecrApplyWorkFlowPlugin extends AbstractOperationServicePlugIn {
+
+    private static Log logger = LogFactory.getLog(CasRecrApplyWorkFlowPlugin.class);
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        // 提前加载表单里的字段
+        List<String> fieldKeys = e.getFieldKeys();
+        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    public void beginOperationTransaction(BeginOperationTransactionArgs args) {
+        super.beginOperationTransaction(args);
+        DynamicObject[] regBillObjs = args.getDataEntities();
+//        List<Long> billIdList = new ArrayList(10);
+//        DynamicObject[] var5 = regBillObjs;
+//        int var6 = regBillObjs.length;
+//
+//        for(int var7 = 0; var7 < var6; ++var7) {
+//            DynamicObject dynamicObject = var5[var7];
+//            long id = dynamicObject.getLong("id");
+//            billIdList.add(id);
+//        }
+//
+        SWCDataServiceHelper helper = new SWCDataServiceHelper("nckd_casrecrapply");
+//        QFilter filter = new QFilter("id", "in", billIdList);
+//        DynamicObject[] needUpdateBillDy = helper.query("id,billstatus", new QFilter[]{filter});
+        switch (args.getOperationKey()) {
+            case "wfauditnotpass":
+                this.setApproveStatus(regBillObjs, "E");
+                break;
+            case "wfrejecttosubmit":
+                this.setApproveStatus(regBillObjs, "A");
+                break;
+            case "wfauditing":
+                this.setApproveStatus(regBillObjs, "D");
+                break;
+            case "wfauditpass":
+                this.setApproveStatus(regBillObjs, "C");
+                break;
+            default:
+                break;
+        }
+
+        helper.save(regBillObjs);
+    }
+
+
+    private void setApproveStatus(DynamicObject[] regBillObjs, String billstatus) {
+        DynamicObject[] var3 = regBillObjs;
+        int var4 = regBillObjs.length;
+
+        for(int var5 = 0; var5 < var4; ++var5) {
+            DynamicObject dynamicObject = var3[var5];
+            dynamicObject.set("billstatus", billstatus);
+        }
+
+    }
+
+
+}
+

+ 151 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyPlanOperatePlugin.java

@@ -0,0 +1,151 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.operate;
+
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * @author Tyx
+ * @date  2025/5/8
+ * 年度招聘计划操作插件
+ *
+ */
+public class YearCrApplyPlanOperatePlugin extends AbstractOperationServicePlugIn {
+
+
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        // 提前加载表单里的字段
+        List<String> fieldKeys = e.getFieldKeys();
+        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    public void beginOperationTransaction(BeginOperationTransactionArgs args) {
+        super.beginOperationTransaction(args);
+        DynamicObject[] regBillObjs = args.getDataEntities();
+
+        switch (args.getOperationKey()) {
+            case "wfauditnotpass":
+            case "delete":
+                // 审批不通过,删除
+
+                updateYearcrapplyPlan(regBillObjs, "A");
+                break;
+            case "wfauditpass":
+                // 审批通过
+            case "audit":
+                // 审批
+                updateYearcrapplyPlan(regBillObjs, "C");
+                updatePersonNum(regBillObjs);
+                break;
+            case "unsubmit":
+                // 校验是否存在下级单据
+                String errorMsg = validateYearcrapplyPlan(regBillObjs);
+                if(StringUtils.isNoneBlank(errorMsg)){
+
+                }
+
+
+                updateYearcrapplyPlan(regBillObjs, "B");
+                break;
+                // 反审批
+            case "save":
+                // 保存
+                updateYearcrapplyPlan(regBillObjs, "B");
+                break;
+            default:
+                break;
+        }
+
+    }
+
+    private String validateYearcrapplyPlan(DynamicObject[] yearcrapplyPlanObj){
+
+        return null;
+    }
+
+
+    // 更新年度招聘申请核定人数
+    private void updatePersonNum(DynamicObject[] yearcrapplyPlanObjs){
+        List<DynamicObject> yearcrapplyPlanObjsList = new ArrayList<>();
+        Set<Long> yearcrapplyPlanIds = new HashSet<>();
+        for (DynamicObject yearcrapplyPlanObj : yearcrapplyPlanObjs) {
+            DynamicObjectCollection entryentity = yearcrapplyPlanObj.getDynamicObjectCollection("entryentity");
+            for (DynamicObject dynamicObject : entryentity) {
+                yearcrapplyPlanObjsList.add(dynamicObject);
+                yearcrapplyPlanIds.add(dynamicObject.getLong("nckd_yearapplyid"));
+            }
+        }
+        Map<Object, DynamicObject> resultMap = yearcrapplyPlanObjsList.stream()
+                .collect(Collectors.toMap(
+                        obj -> obj.get("nckd_yearapplyentryid"), // 获取key
+                        obj -> obj // 获取value
+                ));
+
+        QFilter qFilter = new QFilter("id", QCP.in, yearcrapplyPlanIds);
+        DynamicObject[] nckdYearapplies = BusinessDataServiceHelper.load("nckd_yearapply", "id,entryentity,entryentity.nckd_summary,entryentity.nckd_approvednum", new QFilter[]{qFilter});
+        for (DynamicObject nckdYearapply : nckdYearapplies) {
+            DynamicObjectCollection entryentity = nckdYearapply.getDynamicObjectCollection("entryentity");
+            for (DynamicObject dynamicObject : entryentity) {
+                DynamicObject dynamicObjectentry = resultMap.get(dynamicObject.getPkValue());
+                if(ObjectUtils.isNotEmpty(dynamicObjectentry)){
+                    dynamicObject.set("nckd_approvednum", dynamicObjectentry.get("nckd_approvednum"));
+                }
+            }
+        }
+        if(nckdYearapplies.length>0){
+            SaveServiceHelper.save(nckdYearapplies);
+        }
+    }
+
+    private void updateYearcrapplyPlan(DynamicObject[] yearcrapplyPlanObjs, String status) {
+        //  获取单据单内 年度招聘申请id和申请分录id
+
+        for (DynamicObject yearcrapplyPlanObj : yearcrapplyPlanObjs) {
+            Set<Long> yearcrapplyPlanIds = new HashSet<>();
+            Set<Long> yearcrapplyPlanEntryIds = new HashSet<>();
+            DynamicObjectCollection entryentity = yearcrapplyPlanObj.getDynamicObjectCollection("entryentity");
+            for (DynamicObject entry : entryentity) {
+                yearcrapplyPlanEntryIds.add(entry.getLong("nckd_yearapplyentryid"));
+                yearcrapplyPlanIds.add(entry.getLong("nckd_yearapplyid"));
+            }
+
+            List<Long> yearcrapplyPlanEntryIdsList = new ArrayList<>(yearcrapplyPlanEntryIds);
+            List<Long> yearcrapplyPlanIdsList = new ArrayList<>(yearcrapplyPlanIds);
+            QFilter qFilter = new QFilter("id", QCP.in, yearcrapplyPlanIdsList);
+            QFilter qFilter1 = new QFilter("entryentity.id", QCP.in, yearcrapplyPlanEntryIdsList);
+
+            DynamicObject[] loads = BusinessDataServiceHelper.load("nckd_yearapply","id,nckd_summarstatus,entryentity,entryentity.id,entryentity.,entryentity.nckd_summary,entryentity.nckd_casreplanid",new QFilter[]{qFilter,qFilter1});
+            for (DynamicObject load : loads) {
+                load.set("nckd_summarstatus", status);
+                DynamicObjectCollection entryentity1 = load.getDynamicObjectCollection("entryentity");
+                for (DynamicObject dynamicObject : entryentity1) {
+                    if(yearcrapplyPlanEntryIdsList.contains(dynamicObject.getLong("id"))){
+                        dynamicObject.set("nckd_summary", status);
+                        if(status.equals("A")){
+                            dynamicObject.set("nckd_casreplanid", null);
+                        }else{
+                            dynamicObject.set("nckd_casreplanid", yearcrapplyPlanObj.getPkValue());
+                        }
+                    }
+                }
+            }
+            SaveServiceHelper.save(loads);
+        }
+    }
+}

+ 66 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyPlanUnAuditValidator.java

@@ -0,0 +1,66 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.operate;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * description: 年度招聘计划校验插件
+ * nckd_yearapply
+ * @author Tyx
+ * @date  2025/5/8
+ */
+
+public class YearCrApplyPlanUnAuditValidator extends AbstractOperationServicePlugIn {
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        // 提前加载表单里的字段
+        List<String> fieldKeys = e.getFieldKeys();
+        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+
+
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+        e.addValidator(new AbstractValidator() {
+            @Override
+            public void validate() {
+                ExtendedDataEntity[] dataEntities = this.getDataEntities();
+
+                for (ExtendedDataEntity dataEntity : dataEntities) {
+                    DynamicObject dynamicObject = dataEntity.getDataEntity();
+                    DynamicObjectCollection entryentity = dynamicObject.getDynamicObjectCollection("entryentity");
+                    if(entryentity.size() > 0){
+                        List<String> objectList = entryentity.stream()
+                                .map(entry -> {
+                                    return String.valueOf(entry.getPkValue());
+                                })
+                                .collect(Collectors.toList());
+                        DynamicObject[] load = BusinessDataServiceHelper.load("tstpm_srscarfmrsm", "id", (new QFilter("nckd_mokahcnum", QCP.in, objectList)).toArray());
+                        if(load.length > 0){
+                            this.addErrorMessage(dataEntity, "已存在候选人信息,不允许反审核!");
+                            break;
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+}

+ 73 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyPlanWorkFlowPlugin.java

@@ -0,0 +1,73 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.operate;
+
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-年度招聘计划
+ * Description      :审批流按钮操作插件
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_yearapply
+ */
+
+
+public class YearCrApplyPlanWorkFlowPlugin extends AbstractOperationServicePlugIn {
+
+    private static Log logger = LogFactory.getLog(YearCrApplyPlanWorkFlowPlugin.class);
+
+
+    public void beginOperationTransaction(BeginOperationTransactionArgs args) {
+        super.beginOperationTransaction(args);
+        DynamicObject[] regBillObjs = args.getDataEntities();
+
+        SWCDataServiceHelper helper = new SWCDataServiceHelper("nckd_yearcasreplan");
+
+        switch (args.getOperationKey()) {
+            case "wfauditnotpass":
+                this.setApproveStatus(regBillObjs, "E");
+                break;
+            case "wfrejecttosubmit":
+                this.setApproveStatus(regBillObjs, "A");
+                break;
+            case "wfauditing":
+                this.setApproveStatus(regBillObjs, "D");
+                break;
+            case "wfauditpass":
+                this.setApproveStatus(regBillObjs, "C");
+                break;
+            default:
+                break;
+        }
+        helper.update(regBillObjs);
+    }
+
+    private void setApproveStatus(DynamicObject[] regBillObjs, String billstatus) {
+        DynamicObject[] var3 = regBillObjs;
+        int var4 = regBillObjs.length;
+        for(int var5 = 0; var5 < var4; ++var5) {
+            DynamicObject dynamicObject = var3[var5];
+            dynamicObject.set("billstatus", billstatus);
+        }
+    }
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        // 提前加载表单里的字段
+        List<String> fieldKeys = e.getFieldKeys();
+        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
+    }
+}
+

+ 56 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplySubmitValidator.java

@@ -0,0 +1,56 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.operate;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.servicehelper.MetadataServiceHelper;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * description: 年度招聘申请提交校验插件
+ * nckd_yearapply
+ * @author Tyx
+ * @date  2025/5/8
+ */
+
+public class YearCrApplySubmitValidator extends AbstractOperationServicePlugIn {
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        // 提前加载表单里的字段
+        List<String> fieldKeys = e.getFieldKeys();
+        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+
+
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
+        e.addValidator(new AbstractValidator() {
+            @Override
+            public void validate() {
+                ExtendedDataEntity[] dataEntities = this.getDataEntities();
+                for (ExtendedDataEntity dataEntity : dataEntities) {
+                    DynamicObject dynamicObject = dataEntity.getDataEntity();
+                    String nckdSummarstatus = dynamicObject.getString("nckd_summarstatus");
+                    if(StringUtils.isNotEmpty(nckdSummarstatus) && !"A".equals(nckdSummarstatus)){
+                        this.addErrorMessage(dataEntity, "汇总状态为已汇总和汇总中的数据,不能进行操作!");
+                        break;
+                    }
+                }
+            }
+        });
+    }
+
+}

+ 86 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/operate/YearCrApplyWorkFlowPlugin.java

@@ -0,0 +1,86 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.operate;
+
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.swc.hsbp.business.servicehelper.SWCDataServiceHelper;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Module           :人才供应云-招聘直通车-首页-年度招聘申请
+ * Description      :审批流按钮操作插件
+ *
+ * @author Tyx
+ * @date  2025/5/8
+ * 标识 nckd_yearapply
+ */
+
+
+public class YearCrApplyWorkFlowPlugin extends AbstractOperationServicePlugIn {
+
+    private static Log logger = LogFactory.getLog(YearCrApplyWorkFlowPlugin.class);
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        // 提前加载表单里的字段
+        List<String> fieldKeys = e.getFieldKeys();
+        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    public void beginOperationTransaction(BeginOperationTransactionArgs args) {
+        super.beginOperationTransaction(args);
+        DynamicObject[] regBillObjs = args.getDataEntities();
+//        List<Long> billIdList = new ArrayList(10);
+//        DynamicObject[] var5 = regBillObjs;
+//        int var6 = regBillObjs.length;
+//
+//        for(int var7 = 0; var7 < var6; ++var7) {
+//            DynamicObject dynamicObject = var5[var7];
+//            long id = dynamicObject.getLong("id");
+//            billIdList.add(id);
+//        }
+
+        SWCDataServiceHelper helper = new SWCDataServiceHelper("nckd_yearapply");
+//        QFilter filter = new QFilter("id", "in", billIdList);
+//        DynamicObject[] needUpdateBillDy = helper.query("id,billstatus", new QFilter[]{filter});
+
+        switch (args.getOperationKey()) {
+            case "wfauditnotpass":
+                this.setApproveStatus(regBillObjs, "E");
+                break;
+            case "wfrejecttosubmit":
+                this.setApproveStatus(regBillObjs, "A");
+                break;
+            case "wfauditing":
+                this.setApproveStatus(regBillObjs, "D");
+                break;
+            case "wfauditpass":
+                this.setApproveStatus(regBillObjs, "C");
+                break;
+            default:
+                break;
+        }
+
+        helper.save(regBillObjs);
+    }
+
+    private void setApproveStatus(DynamicObject[] regBillObjs, String billstatus) {
+        DynamicObject[] var3 = regBillObjs;
+        int var4 = regBillObjs.length;
+        for(int var5 = 0; var5 < var4; ++var5) {
+            DynamicObject dynamicObject = var3[var5];
+            dynamicObject.set("billstatus", billstatus);
+        }
+    }
+}
+

+ 61 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/tsrsc/plugin/util/RecUtils.java

@@ -0,0 +1,61 @@
+package nckd.jimin.jyyy.hr.tsrsc.plugin.util;
+
+import kd.bos.algo.DataSet;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.db.DBRoute;
+import kd.bos.orm.ORM;
+import kd.hr.hbp.common.util.HRDBUtil;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class RecUtils {
+
+    /**
+     * 获取组织对应人员编制总数(包含下级)
+     * @param orgId 组织ID
+     * @return 编制数
+     */
+    public static int getStaffCount(Object orgId){
+
+        Date date = new Date();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        String dateStr = sdf.format(date);
+
+        // 拼接 SQL 查询 haos_stafforgempcount
+        StringBuilder sql2 = new StringBuilder("SELECT DISTINCT T.fstructlongnumber,ST.fcount as count "
+                + "FROM T_HAOS_ADMINORG A "
+                + "LEFT JOIN T_HAOS_ADMINSTRUCT T ON a.fboid = T.fadminorgid "
+                + "left join T_HAOS_STAFFORGEMPCOUNT ST on A.fboid = ST.fuseorgboid "
+                + "WHERE A.fiscurrentversion = '0' AND A.fdatastatus = '1' AND A.finitstatus = '2' "
+                + "AND T.fiscurrentversion = '0' AND T.fdatastatus = '1' AND T.fstructprojectid = 1010 "
+                + "AND T.finitstatus = '2' AND T.fbsed <= '" + dateStr + "' "
+                + "AND T.fbsled >= '" + dateStr + "' AND T.fenable = '1' "
+                + "AND A.fbsed <= '" + dateStr + "' AND A.fbsled >= '" + dateStr + "' "
+                + "AND A.fenable = '1' "
+                + "AND ( T.fstructlongnumber LIKE ( select top 1 concat(F.fstructlongnumber,'%')  from  T_HAOS_ADMINSTRUCT F where  F.fadminorgid = ? "
+                + "AND F.fiscurrentversion = '0' AND F.fdatastatus = '1' AND F.fstructprojectid = 1010 "
+                + "AND F.finitstatus = '2' AND F.fbsed <= '" + dateStr + "' "
+                + "AND F.fbsled >= '" + dateStr + "' AND F.fenable = '1' "
+                +") " +") "
+        );
+
+        Object[] param = new Object[]{(Long) orgId};
+//        DataSet dataSet = HRDBUtil.queryDataSet("haos_adminOrgHisSearch", new DBRoute("hr"), sql.toString(), param);
+        DataSet dataSet = HRDBUtil.queryDataSet("haos_adminOrgHisSearch", new DBRoute("hr"), sql2.toString(), param);
+
+        ORM orm = ORM.create();
+        DynamicObjectCollection retDynCol = orm.toPlainDynamicObjectCollection(dataSet);
+        // 获取实际人数
+        AtomicInteger nckdRellownum2 = new AtomicInteger(0);
+        retDynCol.forEach(dynObj -> {
+            if(ObjectUtils.isNotEmpty(dynObj.getInt("count"))){
+                nckdRellownum2.addAndGet(dynObj.getInt("count"));
+            }
+        });
+        return nckdRellownum2.get();
+    }
+
+}

+ 71 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyAlertTask.java

@@ -0,0 +1,71 @@
+package nckd.jimin.jyyy.hr.wtc.wtabm.opplugin.web.vaapply;
+
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.exception.KDException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.message.api.MessageChannels;
+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.workflow.MessageCenterServiceHelper;
+import kd.bos.workflow.engine.msg.info.MessageInfo;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.sdk.plugin.Plugin;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tyx 2025-04-30
+ * 预警插件
+ * 查找未做销假的长假单,并通知对应人员
+ */
+public class VaApplyAlertTask extends AbstractTask implements Plugin {
+
+    private static final Log log = LogFactory.getLog(VaApplyAlertTask.class);
+    private static String apply_entity = "wtabm_vaapply";
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+
+        log.info("-------- 开始执行未销假休假单定时提醒 --------");
+        String selectFields = "personid.number,billno,startdate,enddate,nckd_isupdateperson,nckd_islongleave,entryentity.entryvacationtype";
+        HRBaseServiceHelper helper = HRBaseServiceHelper.create(apply_entity);
+        QFilter filter = new QFilter("nckd_islongleave", QCP.equals, true);
+        filter.and("nckd_iscancelleave", QCP.equals, false);
+        filter.and("auditstatus", QCP.equals, "C");
+        filter.and("enddate", QCP.large_equals, new Date());
+        DynamicObject[] bills = BusinessDataServiceHelper.load(apply_entity, selectFields, new QFilter[]{filter});
+        log.info("-------- 查询出符合条件的休假单条数:" + bills.length + " --------");
+        for (DynamicObject bill : bills) {
+            //提醒person对应的user
+            String personNo = bill.getString("personid.number");
+            String billNo = bill.getString("billno");
+            DynamicObject user = VaApplyBillUtil.getUserByPersonNo(personNo);
+            //发送消息
+            sendMessage(user, billNo);
+        }
+    }
+
+    /**
+     * 发送消息给指定用户
+     * @param user userDyn
+     * @param billNo 休假单单据编号
+     */
+    public void sendMessage (DynamicObject user, String billNo) {
+        MessageInfo msgInfo = new MessageInfo();
+        List<Long> userList = new ArrayList();
+        userList.add(user.getLong("id"));
+        msgInfo.setUserIds(userList);
+        msgInfo.setNotifyType(MessageChannels.MC.getNumber());
+        msgInfo.setType(MessageInfo.TYPE_MESSAGE);
+        msgInfo.setContent("您有待销假的休假申请,单据号:" + billNo);
+        //msgInfo.setContentUrl(); TODO 界面链接
+        msgInfo.setTitle("销假提醒");
+        Long msgId = MessageCenterServiceHelper.sendMessage(msgInfo);
+    }
+}

+ 39 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyBillOpEx.java

@@ -0,0 +1,39 @@
+package nckd.jimin.jyyy.hr.wtc.wtabm.opplugin.web.vaapply;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.sdk.plugin.Plugin;
+
+import java.util.Date;
+
+/**
+ * Tyx 2025-04-28
+ * 请假单通用操作插件
+ * 判断请假结束日期-开始日期是否超过30天,是的话表头是否长假字段[nckd_islongleave]为true
+ */
+public class VaApplyBillOpEx extends AbstractOperationServicePlugIn implements Plugin {
+
+    private static final Log log = LogFactory.getLog(VaApplyBillOpEx.class);
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        DynamicObject[] bills = e.getDataEntities();
+        for (DynamicObject bill : bills) {
+            Date startDate = bill.getDate("startdate");
+            Date endDate = bill.getDate("enddate");
+            //判断两个日期是不是相差30天
+            //2025-05-06 判断是否哺乳假 是的话不算长假
+            long dateDiff = Math.abs(endDate.getTime() - startDate.getTime());
+            long day = dateDiff / ( 1000 * 60 * 60 * 24);
+            log.info(" -------- 相差天数:" + day + " -------- ");
+            if(day > 30) {
+                bill.set("nckd_islongleave", true);
+            }
+        }
+        
+        super.beginOperationTransaction(e);
+    }
+}

+ 70 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyBillTask.java

@@ -0,0 +1,70 @@
+package nckd.jimin.jyyy.hr.wtc.wtabm.opplugin.web.vaapply;
+
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+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.SaveServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.sdk.plugin.Plugin;
+
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Tyx 2025-04-27
+ * 休假更新员工状态定时任务插件
+ * 查询休假单数据,更新这些请假人员的基本信息-员工状态字段为长期休假
+ * 具体数据过滤条件:
+ * nckd_isupdateperson = false and nckd_islongleave = true
+ * ischange = false and ishavechange = false
+ * auditstatus = 'C' and startdate < now();
+ */
+public class VaApplyBillTask extends AbstractTask implements Plugin {
+
+    private static String apply_entity = "wtabm_vaapply";
+    private static final Log log = LogFactory.getLog(VaApplyBillTask.class);
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+
+        log.info("-------- 开始执行请假单定时更新长假员工状态 --------");
+        String selectFields = "personid,startdate,enddate,nckd_isupdateperson,nckd_islongleave,entryentity.entryvacationtype";
+        HRBaseServiceHelper helper = HRBaseServiceHelper.create(apply_entity);
+        QFilter filter = new QFilter("nckd_islongleave", QCP.equals, true);
+        filter.and("ischange", QCP.equals, false);
+        filter.and("ishavechange", QCP.equals, false);
+        filter.and("auditstatus", QCP.equals, "C");
+        filter.and("startdate", QCP.less_equals, new Date());
+        filter.and("nckd_isupdateperson", QCP.equals, false);
+        DynamicObject[] bills = BusinessDataServiceHelper.load(apply_entity, selectFields, new QFilter[]{filter});
+        log.info("-------- 查询出符合条件的休假单条数:" + bills.length + " --------");
+        for(DynamicObject bill : bills) {
+            //获取到人员
+            Long personId = bill.getLong("personid_id");
+            //获取到假期类型 根据假期类型判断员工状态编码
+            String typeNumber = "";
+
+            DynamicObjectCollection entryCols = bill.getDynamicObjectCollection("entryentity");
+            if(entryCols.size() > 0) {
+                DynamicObject entry = entryCols.get(0);
+                String vacationNumber = entry.getString("entryvacationtype.number");
+                if (vacationNumber.equals("1060_S")) {
+                    typeNumber = "9020_S";  //产假
+                } else {
+                    typeNumber = "9010_S";  //长假
+                }
+                //更新员工档案
+                VaApplyBillUtil.updatePersonType(typeNumber, personId);
+                //更新单据上nckd_isupdateperson字段
+                bill.set("nckd_isupdateperson", true);
+            }
+        }
+        SaveServiceHelper.save(bills);
+    }
+}

+ 129 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaApplyBillUtil.java

@@ -0,0 +1,129 @@
+package nckd.jimin.jyyy.hr.wtc.wtabm.opplugin.web.vaapply;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+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.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.hbp.business.application.impl.newhismodel.HisModelController;
+import kd.hr.hbp.business.domain.model.newhismodel.HisResponse;
+import kd.hr.hbp.business.domain.model.newhismodel.HisVersionParamBo;
+import kd.hr.hbp.business.domain.model.newhismodel.VersionChangeRespData;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.constants.newhismodel.EnumHisOperateType;
+import kd.hr.hbp.common.util.HRDynamicObjectUtils;
+import kd.hrmp.hrpi.business.infrastructure.utils.QFilterUtil;
+import kd.imc.rim.common.utils.StringUtils;
+
+import java.util.List;
+
+public class VaApplyBillUtil {
+
+    private static String laborStatus_entity = "hbss_laborrelstatus";
+    private static String perNonTsProp_entity = "hrpi_pernontsprop";
+    private static String empEntRel_entity = "hdm_empentrel";
+    private static String depEmp_entity = "hrpi_depemp";
+    private static String ermanFile_entity = "hspm_ermanfile";
+    private static final Log log = LogFactory.getLog(VaApplyBillUtil.class);
+    /**
+     * 更新员工基本信息上员工状态字段,保存历史版本
+     * @param typeNumber 用工关系状态编码
+     * @param personId  人员
+     */
+    public static void updatePersonType (String typeNumber, Long personId) {
+        HRBaseServiceHelper helper = HRBaseServiceHelper.create(perNonTsProp_entity);
+        QFilter filter = new QFilter("person", QCP.equals, personId);
+        filter.and("datastatus", QCP.equals, "1");
+        filter.and("iscurrentversion",QCP.equals, "1");
+        String selectFields = "iscurrentversion,person,datastatus,nckd_isgbqs,boid";
+        DynamicObject curVersionDyn = helper.queryOne(selectFields, new QFilter[]{filter});
+        curVersionDyn = helper.loadSingle(curVersionDyn.getPkValue());
+        DynamicObject newVersionDyn = helper.generateEmptyDynamicObject();
+        HRDynamicObjectUtils.copy(curVersionDyn, newVersionDyn,true);
+        DynamicObject ygzt = getLaborRelStatusDyn(typeNumber);
+        newVersionDyn.set("nckd_ygzt", ygzt);
+        HisVersionParamBo hisVersionParamBo = new HisVersionParamBo();
+        hisVersionParamBo.setOperateType(EnumHisOperateType.NO_TIME_SAVE_VERSION.getType());
+        hisVersionParamBo.setEntityNumber(perNonTsProp_entity);
+        hisVersionParamBo.setHisDyns(new DynamicObject[]{newVersionDyn});
+        HisModelController hisModelController = HisModelController.getInstance();
+        HisResponse<VersionChangeRespData> hisResponse = hisModelController.noLineTimeHisVersionChange(hisVersionParamBo);
+        if(StringUtils.isNoneBlank(hisResponse.getErrorMessage())) {
+            log.error("保存历史模型失败:" + hisResponse.getErrorMessage());
+        }
+    }
+
+    /**
+     * 获取用工关系状态Dyn
+     * @param typeNumber 编码
+     * @return
+     */
+    public static DynamicObject getLaborRelStatusDyn (String typeNumber) {
+        QFilter filter = new QFilter("number", QCP.equals, typeNumber);
+        return BusinessDataServiceHelper.loadSingle(laborStatus_entity, new QFilter[]{filter});
+    }
+
+    /**
+     * 获取员工当前用工关系状态编码
+     * @param personId
+     * @return
+     */
+    public static String getLaborStatusNumber (Long personId) {
+        QFilter filter = QFilterUtil.getCurrentQf();
+        filter.and("businessstatus", QCP.equals, "1");
+        filter.and("person.id", QCP.equals, personId);
+        DynamicObjectCollection cols = QueryServiceHelper.query(empEntRel_entity, "laborrelstatus.number", new QFilter[]{filter});
+        if(cols.size() > 0) {
+            return cols.get(0).getString("laborrelstatus.number");
+        }
+        else {
+            return null;
+        }
+    }
+
+    /**
+     * 获取人员主职职位Dyn
+     * @param personId
+     */
+    public static DynamicObject getPersonPrimaryPosition (Long personId) {
+        QFilter filter = QFilterUtil.getCurrentQf();
+        filter.and("businessstatus", QCP.equals, "1");
+        filter.and("person.id", QCP.equals, personId);
+        filter.and("isprimary", QCP.equals, "1");
+        HRBaseServiceHelper helper = HRBaseServiceHelper.create(depEmp_entity);
+        DynamicObject position = helper.queryOne("position.id", new QFilter[]{filter});
+        return position;
+    }
+
+    /**
+     * 获取职位上的兼职档案
+     * @param positionIds
+     * @return
+     */
+    public static DynamicObject[] getErmanFilesByPosition (List<Long> positionIds) {
+        QFilter filter = new QFilter("depemp.iscurrentversion", QCP.equals, "1");
+        filter.and("depemp.businessstatus", QCP.equals, "1");
+        filter.and("depemp.postype.number",QCP.equals, "1020_S");
+        filter.and("depemp.position", QCP.in, positionIds);
+        filter.and("iscurrentversion", QCP.equals, "1");
+        filter.and("businessstatus", QCP.equals, "1");
+        HRBaseServiceHelper helper = HRBaseServiceHelper.create(ermanFile_entity);
+        DynamicObject[] ermanFiles = helper.query(new QFilter[]{filter});
+        return ermanFiles;
+    }
+
+    /**
+     * 根据HR人员工号获取平台人员Dyn
+     * @param personNo
+     * @return
+     */
+    public static DynamicObject getUserByPersonNo (String personNo) {
+        QFilter filter = new QFilter("number", QCP.equals, personNo);
+        return QueryServiceHelper.queryOne("bos_user", "id", new QFilter[]{filter});
+    }
+
+
+}

+ 94 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaChangeBillAuditOp.java

@@ -0,0 +1,94 @@
+package nckd.jimin.jyyy.hr.wtc.wtabm.opplugin.web.vaapply;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.bos.util.StringUtils;
+import kd.hr.hdm.business.domain.parttime.ParttimeServiceHelper;
+import kd.hr.hdm.business.domain.transfer.service.external.PersonExternalService;
+import kd.sdk.plugin.Plugin;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Tyx 2025-04-29
+ * 休假变更审批插件
+ * 如果是长假单据,审批后反写员工状态为员工当前用工关系状态,同时要撤销该请假员工主职上的所有兼职;
+ */
+public class VaChangeBillAuditOp extends AbstractOperationServicePlugIn implements Plugin {
+
+    private static String vaUpdate_entity = "wtabm_vaupdate";
+    private static String vaApply_entity = "wtabm_vaapply";
+
+    private static final Log log = LogFactory.getLog(VaChangeBillAuditOp.class);
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        e.getFieldKeys().add("nckd_islongleave");
+        e.getFieldKeys().add("nckd_iscancelleave");
+        e.getFieldKeys().add("parentid");
+    }
+
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+//        DynamicObject[] bills = e.getDataEntities();
+//        for(DynamicObject bill : bills) {
+//            if(!bill.getBoolean("nckd_islongleave"))
+//                continue;
+//            Long personId = bill.getLong("personid.id");
+//            //查询请假人当前任职用工关系状态
+//            String typeNumber = VaApplyBillUtil.getDepEmpInfo(personId);
+//            if(!StringUtils.isBlank(typeNumber)) {
+//                VaApplyBillUtil.updatePersonType(typeNumber, personId);
+//                bill.set("nckd_iscancelleave",true);
+//            }
+//        }
+//        SaveServiceHelper.save(bills);
+        super.afterExecuteOperationTransaction(e);
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        DynamicObject[] bills = e.getDataEntities();
+        for(DynamicObject bill : bills) {
+            if(!bill.getBoolean("nckd_islongleave"))
+                continue;
+            Long personId = bill.getLong("personid.id");
+            //查询请假人当前任职用工关系状态
+            String typeNumber = VaApplyBillUtil.getLaborStatusNumber(personId);
+            if(!StringUtils.isBlank(typeNumber)) {
+                VaApplyBillUtil.updatePersonType(typeNumber, personId);
+                //反写源单是否已销假为是
+                Long parentId = bill.getLong("parentid");
+                DynamicObject parentBill = BusinessDataServiceHelper.loadSingle(parentId, vaApply_entity);
+                parentBill.set("nckd_iscancelleave",true);
+                SaveServiceHelper.save(new DynamicObject[]{parentBill});
+            }
+
+            DynamicObject position = VaApplyBillUtil.getPersonPrimaryPosition(personId);
+            List<Long> positionIds = new ArrayList<Long>();
+            positionIds.add(position.getLong("id"));
+            DynamicObject[] ermanFiles = VaApplyBillUtil.getErmanFilesByPosition(positionIds);
+            //转成List<Long>
+            List<Long> ermanFileIds = Arrays.stream(ermanFiles).map(dyx -> dyx.getLong("id")).collect(Collectors.toList());
+            //调用标准方法获取ermanFile
+            List<Map<String, Object>> erManFiles = PersonExternalService.getInstance().invokeGetCardFields(ermanFileIds);
+            //actionId 默认201100_S
+            QFilter filter = new QFilter("number", "=", "201100_S");
+            DynamicObject action = BusinessDataServiceHelper.loadSingle("hpfs_chgaction",new QFilter[]{filter});
+            Date partEndDate = new Date();
+            //调用标准终止兼职方法
+            ParttimeServiceHelper.batchEndParttime(action.getLong("id"), partEndDate, erManFiles);
+        }
+        super.beginOperationTransaction(e);
+    }
+}

+ 52 - 0
code/jyyy/nckd-jimin-jyyy-hr/src/main/java/nckd/jimin/jyyy/hr/wtc/wtabm/opplugin/web/vaapply/VaUpdateBillEditEx.java

@@ -0,0 +1,52 @@
+package nckd.jimin.jyyy.hr.wtc.wtabm.opplugin.web.vaapply;
+
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.bill.BillOperationStatus;
+import kd.bos.bill.BillShowParameter;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.form.field.FieldEdit;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.sdk.plugin.Plugin;
+import kd.wtc.wtabm.formplugin.web.vaupdate.VaUpdateBillEdit;
+
+import java.util.EventObject;
+
+/**
+ * 单据界面插件
+ */
+public class VaUpdateBillEditEx extends AbstractBillPlugIn implements Plugin {
+
+    private static final Log LOG = LogFactory.getLog(VaUpdateBillEditEx.class);
+
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+        this.getModel().beginInit();
+        BillShowParameter formShowParameter = (BillShowParameter)this.getView().getFormShowParameter();
+        BillOperationStatus status = formShowParameter.getBillStatus();
+        Long id;
+        if (status.equals(BillOperationStatus.ADDNEW)) {
+            id = (Long)formShowParameter.getCustomParam("parentid");
+            this.copyModel(id);
+            this.getModel().endInit();
+        }
+    }
+
+    /**
+     * 携带二开字段到变更单上
+     * @param parentId
+     */
+    private void copyModel(Long parentId) {
+        HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper("wtabm_vaapply");
+        DynamicObject parentDynObj = serviceHelper.loadDynamicObject(new QFilter("id", "=", parentId));
+        this.getModel().setValue("nckd_isupdateperson", parentDynObj.get("nckd_isupdateperson"));
+        this.getModel().setValue("nckd_islongleave", parentDynObj.get("nckd_islongleave"));
+        this.getModel().setValue("nckd_iscancelleave", parentDynObj.get("nckd_iscancelleave"));
+        this.getView().updateView("fieldsetpanelap21");
+    }
+}