Explorar o código

Merge branch 'master' of http://39.108.216.210:3000/zhuwei/bladex

huangtf hai 8 meses
pai
achega
df25dcb369
Modificáronse 22 ficheiros con 528 adicións e 299 borrados
  1. 16 0
      blade-common/src/main/java/org/springblade/common/utils/BaseUtils.java
  2. 108 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ConstructionSchedule.java
  3. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InterimMeter.java
  4. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/MeterPeriodInfo.java
  5. 30 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ReportMergeCellsConfig.java
  6. 2 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ReportResult.java
  7. 19 11
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SubprojectInterimPaymentSummary.java
  8. 1 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java
  9. 4 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVisaController.java
  10. 83 129
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  11. 4 0
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  12. 7 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  13. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeController.java
  14. 166 122
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java
  15. 0 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/MeterElementWriter.java
  16. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java
  17. 11 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  18. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  19. 3 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/ContractMeterPeriodController.java
  20. 1 1
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/MeterTreeController.java
  21. 50 20
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java
  22. 7 3
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/MeterTreeProjectServiceImpl.java

+ 16 - 0
blade-common/src/main/java/org/springblade/common/utils/BaseUtils.java

@@ -1,6 +1,7 @@
 package org.springblade.common.utils;
 
 import com.alibaba.cloud.commons.lang.StringUtils;
+import org.checkerframework.checker.regex.RegexUtil;
 import org.springblade.common.constant.RegexConstant;
 import org.springblade.common.vo.DataVO;
 
@@ -213,6 +214,21 @@ public class BaseUtils {
         return !isNotEmpty(value);
     }
 
+    public static List<Integer> coords2Int(String coords){
+        Matcher mx = matcher("([A-Z]{1,3})(\\d{1,3})[~|\\-|,|#]([A-Z]{1,3})(\\d{1,3})",coords);
+        List<Integer> list = new ArrayList<>();
+        if(mx.find()) {
+            list.add(Integer.parseInt(mx.group(1)));
+            list.add(Integer.parseInt(mx.group(2)));
+            list.add(Integer.parseInt(mx.group(3)));
+            list.add(Integer.parseInt(mx.group(4)));
+        }
+        return list;
+    }
+    public static Matcher matcher(String regex, String value) {
+        Pattern pattern = Pattern.compile(regex);
+        return pattern.matcher(value);
+    }
 
     public static Double[] scopeParse(Object dev, Object design, Object xN) {
         if (isNotEmpty(dev)) {

+ 108 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ConstructionSchedule.java

@@ -0,0 +1,108 @@
+package org.springblade.manager.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author yangyj
+ * @Date 2024/3/27 17:46
+ * @description 施工进度表
+ */
+@Data
+public class ConstructionSchedule {
+    public static final String ID="20320000000";
+    public static final String TBN="ConSch";
+    public static final String TBN_CH="施工进度表";
+    /**支付编号*/
+    @JSONField(name = "key_0",label="支付编号")
+    private String formNumber;
+    /**项目名称*/
+    @JSONField(name = "key_1",label="项目名称",ordinal = 1)
+    private String itemName;
+    /**计量单位*/
+    @JSONField(name = "key_2",label="计量单位",ordinal = 2)
+    private String unit;
+    /**合同数量*/
+    @JSONField(name = "key_3",label="合同数量",ordinal = 3)
+    private String contractTotal;
+    /**变更数量*/
+    @JSONField(name = "key_4",label="变更数量",ordinal = 4)
+    private String changeTotal;
+    /**本次完成数量*/
+    @JSONField(name = "key_5",label="本次完成数量",ordinal = 5)
+    private String currentPeriodCompleted;
+    /**至上期完成数量*/
+    @JSONField(name = "key_15",label="至上期完成数量",ordinal = 5)
+    private String previousPeriodCompleted;
+    /**累计完成数量*/
+    @JSONField(name = "key_6",label="累计完成数量",ordinal = 6)
+    private String completed;
+    /**合同金额*/
+    @JSONField(name = "key_7",label="合同金额",ordinal = 7)
+    private String contractMoney;
+    /**变更后A金额*/
+    @JSONField(name = "key_8",label="变更后A金额",ordinal = 8)
+    private String changeMoney;
+    /**上次支付金额*/
+    @JSONField(name = "key_13",label="上次支付金额",ordinal = 8)
+    private String previousPeriodPay;
+    /**本次支付金额*/
+    @JSONField(name = "key_9",label="本次支付金额",ordinal = 9)
+    private String currentPeriodPay;
+    /**累计支付B金额*/
+    @JSONField(name = "key_10",label="累计支付B金额",ordinal = 10)
+    private String currentPeriodEndPay;
+    /**比例*/
+    @JSONField(name = "key_11",label="比例",ordinal = 11)
+    private String payRatio;
+    /**第n页 共m页*/
+    @JSONField(name = "key_12",label="页码",ordinal = 101)
+    private String pageCount;
+    /**变更金额*/
+    @JSONField(name = "key_16",label="变更金额-ZJ",ordinal = 12)
+    private String adjustmentAmount;
+    /**单项占合同价*/
+    @JSONField(name = "key_17",label="单项占合同价-ZJ",ordinal = 12)
+    private String itemPercent;
+    /**单项计划完成*/
+    @JSONField(name = "key_18",label="单项计划完成-ZJ",ordinal = 12)
+    private String itemProgress;
+    /**单项计划完成*/
+    @JSONField(name = "key_19",label="本期占该合同金额-ZJ",ordinal = 12)
+    private String currentPayPercent;
+    /**本期末累计占变更后的总金额*/
+    @JSONField(name = "key_20",label="本期末累计占变更后的总金额-ZJ",ordinal = 12)
+    private String payPercent;
+    /**本期末累计占变更后的总金额*/
+    @JSONField(name = "key_21",label="按月计划与实际完成-ZJ",ordinal = 12)
+    private List<List<Payment>> monthlyCompletion = new ArrayList<>() ;
+    /**累计实际完成*/
+    @JSONField(name = "key_22",label="累计实际完成-ZJ",ordinal = 102)
+    private String actualCompletion;
+    /**本次实际完成*/
+    @JSONField(name = "key_23",label="本次实际完成-ZJ",ordinal = 102)
+    private String currentCompletion;
+    /**合同概要*/
+    @JSONField(name = "key_24",label="合同概要-ZJ",ordinal = 106)
+    private String contractSummary;
+
+
+    public ConstructionSchedule(String itemName) {
+        this.itemName = itemName;
+        this.currentPeriodPay = "0.0";
+        this.currentPeriodEndPay = "0.0";
+    }
+
+    public ConstructionSchedule(String itemName, String currentPeriodPay, String currentPeriodEndPay) {
+        this.itemName = itemName;
+        this.currentPeriodPay = currentPeriodPay;
+        this.currentPeriodEndPay = currentPeriodEndPay;
+    }
+
+    public ConstructionSchedule() {
+    }
+
+}

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InterimMeter.java

@@ -48,6 +48,12 @@ public class InterimMeter {
     @JSONField(name = "key_9",label="合同图号")
     private String contractPicture;
 
+    @JSONField(name = "key_16",label="支付项目编号")
+    private String formNumber;
+
+    @JSONField(name = "key_17",label="项目名称-ZJ")
+    private String itemName;
+
     @JSONField(name = "key_10",label="支付号")
     private List<String> formNumberList;
     @JSONField(name = "key_11",label="项目名称")

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/MeterPeriodInfo.java

@@ -47,6 +47,12 @@ public class MeterPeriodInfo {
     /**请款理由*/
     @JSONField(name = "key_5",label="请款理由",ordinal = 5)
     private String  cause;
+
+    @JSONField(name = "key_10",label="计量汇总表数量(浙江)",ordinal = 5)
+    private String  summaryNumber;
+
+    @JSONField(name = "key_11",label="工程计量表数量(浙江)",ordinal = 5)
+    private String  meterNumber;
     /**排序号*/
     private Integer sort;
     /**计量期ID*/

+ 30 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ReportMergeCellsConfig.java

@@ -0,0 +1,30 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author yangyj
+ * @Date 2024/3/28 10:37
+ * @description 写死的单元格个配置,有些元素元素设置得非常不好输出,先这样处理
+ */
+@Data
+public class ReportMergeCellsConfig {
+       private Long tableId;
+       private String contentCells;
+       private String mergeRange;
+
+       public ReportMergeCellsConfig(Long tableId, String contentCells, String mergeRange) {
+              this.tableId = tableId;
+              this.contentCells = contentCells;
+              this.mergeRange = mergeRange;
+       }
+
+       public  static List<ReportMergeCellsConfig> bulider(){
+              List<ReportMergeCellsConfig> list = new ArrayList<>();
+              list.add(new ReportMergeCellsConfig(1111L,"AC","A1-A2"));
+              return list;
+       }
+}

+ 2 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ReportResult.java

@@ -60,7 +60,8 @@ public class ReportResult {
     }
     public void pathInit(String sysLocalFileUrl){
         this.pdfPath=sysLocalFileUrl + "/pdf//" +getId() + ".pdf";
-        this.excelPath=sysLocalFileUrl + "/pdf//" + getId() + ".xlsx";
+        /*this.excelPath=sysLocalFileUrl + "/pdf//" + getId() + ".xlsx";*/
+        this.excelPath=sysLocalFileUrl + "/pdf//" + getName().trim()+ ".xlsx";
     }
     /*添加公共部分*/
     public void putCommon(){

+ 19 - 11
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SubprojectInterimPaymentSummary.java

@@ -4,8 +4,10 @@ import com.alibaba.fastjson.annotation.JSONField;
 import lombok.Data;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.core.tool.utils.StringPool;
+import org.springframework.beans.BeanUtils;
 
 import javax.validation.constraints.NotNull;
+import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.ArrayList;
@@ -20,7 +22,7 @@ import java.util.function.Function;
  * @description 分项工程中期支付汇总表
  */
 @Data
-public class SubprojectInterimPaymentSummary {
+public class SubprojectInterimPaymentSummary  {
     public static final String ID="20230000000";
     public static final String TBN="SubIPaySum";
     public static final String TBN_CH="分项工程中期支付汇总表";
@@ -70,32 +72,32 @@ public class SubprojectInterimPaymentSummary {
     @JSONField(name = "key_12",label="页码",ordinal = 101)
     private String pageCount;
     /**变更金额*/
-    @JSONField(name = "key_16",label="变更金额-ZJ",ordinal = 12)
+   /* @JSONField(name = "key_16",label="变更金额-ZJ",ordinal = 12)
     private String adjustmentAmount;
-    /**单项占合同价*/
+    *//**单项占合同价*//*
     @JSONField(name = "key_17",label="单项占合同价-ZJ",ordinal = 12)
     private String itemPercent;
-    /**单项计划完成*/
+    *//**单项计划完成*//*
     @JSONField(name = "key_18",label="单项计划完成-ZJ",ordinal = 12)
     private String itemProgress;
-    /**单项计划完成*/
+    *//**单项计划完成*//*
     @JSONField(name = "key_19",label="本期占该合同金额-ZJ",ordinal = 12)
     private String currentPayPercent;
-    /**本期末累计占变更后的总金额*/
+    *//**本期末累计占变更后的总金额*//*
     @JSONField(name = "key_20",label="本期末累计占变更后的总金额-ZJ",ordinal = 12)
     private String payPercent;
-    /**本期末累计占变更后的总金额*/
+    *//**本期末累计占变更后的总金额*//*
     @JSONField(name = "key_21",label="按月计划与实际完成-ZJ",ordinal = 12)
     private List<List<Payment>> monthlyCompletion = new ArrayList<>() ;
-    /**累计实际完成*/
+    *//**累计实际完成*//*
     @JSONField(name = "key_22",label="累计实际完成-ZJ",ordinal = 102)
     private String actualCompletion;
-    /**本次实际完成*/
+    *//**本次实际完成*//*
     @JSONField(name = "key_23",label="本次实际完成-ZJ",ordinal = 102)
     private String currentCompletion;
-    /**合同概要*/
+    *//**合同概要*//*
     @JSONField(name = "key_24",label="合同概要-ZJ",ordinal = 106)
-    private String contractSummary;
+    private String contractSummary;*/
 
 
     public SubprojectInterimPaymentSummary(String itemName) {
@@ -127,4 +129,10 @@ public class SubprojectInterimPaymentSummary {
             count(this::setCurrentPeriodEndPay,data,SubprojectInterimPaymentSummary::getCurrentPeriodEndPay,scale);
         }
     }
+
+    public SubprojectInterimPaymentSummary copy(){
+        SubprojectInterimPaymentSummary target = new SubprojectInterimPaymentSummary();
+        BeanUtils.copyProperties(this,target);
+        return target;
+    }
 }

+ 1 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java

@@ -404,14 +404,13 @@ public class EVisaTaskCheckController {
                         //设置提示信息
                         String name="";
                         List<Map<String, Object>> userInfo = jdbcTemplate.queryForList("select name from blade_user WHERE id =" + userRole.getString("userId"));
-                        if(userInfo!=null && userInfo.size()>1){
+                        if(userInfo!=null && userInfo.size()>=1){
                             name = userInfo.get(0).get("name")+"";
                             next.setTips(name + "没有电签权限,请检查电签配置或查看表单是否隐藏");
                         }else{
                             name = userRole.getString("userId");
                             next.setTips(name + "该用户不存在");
                         }
-
                         break;
                     }
                 }

+ 4 - 2
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVisaController.java

@@ -174,10 +174,12 @@ public class EVisaController {
             RedisTemplate.delete("sign-" + taskApprovalVO.getFormDataId());
         }else{ //废除
             // 修改 主 任务 u_task 表 状态改为3
-            String up_task_par = "update u_task_parallel set status=3 where parallel_process_instance_id="+taskApprovalVO.getParallelProcessInstanceId();
-            String up_task = "update u_task set status=3 where id="+taskApprovalVO.getTaskId();
+            String up_task_par = "update u_task_parallel set status=3 where parallel_process_instance_id='"+taskApprovalVO.getParallelProcessInstanceId()+"'";
+            String up_task = "update u_task set status=3 where id='"+taskApprovalVO.getTaskId()+"'";
+            this.jdbcTemplate.execute("delete from u_task_batch where id="+taskApprovalVO.getId());
             jdbcTemplate.execute(up_task_par);
             jdbcTemplate.execute(up_task);
+            RedisTemplate.delete("sign-" + taskApprovalVO.getFormDataId());
         }
     }
 

+ 83 - 129
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java

@@ -60,6 +60,7 @@ import org.springblade.evisa.utils.FileUtils;
 import org.springblade.evisa.utils.PDFUtils;
 import org.springblade.evisa.vo.*;
 import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.SignPfxFile;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.SignPfxClient;
@@ -239,6 +240,8 @@ public class EVisaServiceImpl implements EVisaService {
         if (CommonUtil.checkIsBigDecimal(sysBatch)) {
             batch = new Integer(sysBatch);
         }
+        String sql = "SELECT DISTINCT a.remark_type from m_project_info a,u_task b where a.id=b.project_id  and form_data_id='"+task.getFormDataId()+"'";
+        String reType = jdbcTemplate.queryForObject(sql, String.class);
 
         if (DistributedRedisLock.acquire(AuthUtil.getUserId().toString(), batch)) {
             try {
@@ -250,135 +253,89 @@ public class EVisaServiceImpl implements EVisaService {
                 String contractId = this.taskClient.queryTaskContractId(task.getParallelProcessInstanceId());
 
                 String ids = String.join(",", eVisaConfigList);
-                String sqlinfo = "SELECT a.id,a.pyzbx,a.pyzby,b.signature_file_url,b.id as sfId,b.certificate_password,b.certificate_user_name from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + contractId + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + ids + ")";
+                String sqlinfo = "SELECT a.id,a.pyzbx,a.pyzby,b.signature_file_url,b.id as sfId,b.certificate_password,b.certificate_user_name,b.certificate_number from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + contractId + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + ids + ")";
                 List<Map<String, Object>> maps = jdbcTemplate.queryForList(sqlinfo);
                 System.out.println("合同-" + contractId + "--" + sqlinfo);
                 if (maps == null || maps.isEmpty()) {
                     return finalPdfUrl;
                 }
-                //准备签章策略
-                List<SealStrategyVO> sealStrategyVOS = new ArrayList<>();
-                for (Map<String, Object> eVisaConfig : maps) {
-                    //设置签章策略
-                    SealStrategyVO vo = new SealStrategyVO();
-                    vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + eVisaConfig.get("sfId"));
-                    vo.setSealPassword(eVisaConfig.get("certificate_password") + "");
-                    vo.setSealPerson(eVisaConfig.get("certificate_user_name") + "" + System.currentTimeMillis());
-                    //设置签字文件
-                    vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
-                    vo.setSealType("3");
-                    vo.setCompanySeal(true);
-                    vo.setKeyword(eVisaConfig.get("id") + "");
-                    vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
-                    vo.setOffSetY(eVisaConfig.get("pyzby") + "");
-                    sealStrategyVOS.add(vo);
-                }
+                //
+                if(reType.equals("2")){
+                    if (maps != null && !maps.isEmpty()) {
+                        String fileUrl = finalPdfUrl;
+                        for (Map<String, Object> dataMap : maps) {
+                            HashMap<String, Object> daMa = new HashMap<>();
+                            daMa.put("keyWord", dataMap.get("id"));
+                            daMa.put("sealId", dataMap.get("certificate_number"));
+
+                            byte[] fileByte;
+                            if (fileUrl.indexOf("aliyuncs.com") >= 0) {
 
-                SealPdfVO pdfVO = new SealPdfVO();
-                pdfVO.setStrategyVoList(sealStrategyVOS);
-
-                //获取字节
-                byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(finalPdfUrl));
-                //执行电签
-                Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
-                if (result != null) {
-                    if (result[0] != null) {
-                        MultipartFile newFiles = new MockMultipartFile("file", SnowFlakeUtil.getId() + ".pdf", "text/plain", IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0])));
-                        //重新上传
-                        BladeFile bladeFile = this.newIOSSClient.uploadFileByInputStream(newFiles);
-                        if (bladeFile != null) {
-                            finalPdfUrl = bladeFile.getLink();
+                                URL url =new URL(finalPdfUrl);
+                                fileByte = IOUtils.toByteArray(url);
+                            } else {
+                                FileReader fileReader = new FileReader(fileUrl);
+                                fileByte = fileReader.readBytes();
+                            }
+                            String originalFileB64 = Base64.toBase64String(fileByte);
+                            daMa.put("fileB64", originalFileB64);
+                            daMa.put("lastSignFlag", false);
+                            String reData = signPdfByDFZX(daMa);
+                            if (reData.indexOf("success@") >= 0) {
+                                fileUrl = reData.split("@@@@")[1];
+                            }
                         }
+                        if (fileUrl.indexOf("aliyuncs.com") >= 0) {
+                            return E_VISA_ERROR;
+                        } else {
+                            BladeFile bladeFile = this.newIOSSClient.uploadFile(fileUrl.substring(fileUrl.lastIndexOf("/") + 1, fileUrl.length()), fileUrl);
+                            if (bladeFile != null) {
+                                System.out.println("pdf上传=" + bladeFile.getLink());
+                                return bladeFile.getLink();
+                            } else {
+                                return E_VISA_ERROR;
+                            }
+                        }
+                    } else {
+                        System.out.println("------3------");
+                        RedisTemplate.delete("sign-" + task.getFormDataId());
+                        return finalPdfUrl;
                     }
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-        //释放锁
-        DistributedRedisLock.release(AuthUtil.getUserId().toString());
-
-        return finalPdfUrl;
-    }
-
-
-    /**
-     * 合同章 签字
-     *
-     * @param task
-     * @param finalPdfUrl
-     * @return
-     */
-
-    public String eVisaContractSeal222(EVisaTaskApprovalVO task, String finalPdfUrl) {
-        //获取任务对应表格的电签配置(合同张)
-        List<JSONObject> eVisaConfigList = this.taskClient.queryBusinessTableEVisaConfig(task.getParallelProcessInstanceId(), task.getUserId(), "true");
-        if (eVisaConfigList == null || eVisaConfigList.size() == 0) {
-            //没有电签配置,默认当前任务为不签字审批,返回成功
-            return finalPdfUrl;
-        }
-
-        String sysBatch = ParamCache.getValue(CommonConstant.SYS_USER_TASK_BATCH);
-        int batch = 2;
-        if (CommonUtil.checkIsBigDecimal(sysBatch)) {
-            batch = new Integer(sysBatch);
-        }
-
-        //确定合同段并获取合同章
-        List<SignPfxFile> userPfxList = this.signPfxClient.querySignPfxByUserIdOrContractId("", this.taskClient.queryTaskContractId(task.getParallelProcessInstanceId()));
-        if (userPfxList == null || userPfxList.size() <= 0) {
-            //没有签章,不执行电签
-            return finalPdfUrl;
-        }
+                }else {
 
-        //上锁
-        System.out.println(AuthUtil.getUserId().toString());
-        if (DistributedRedisLock.acquire(AuthUtil.getUserId().toString(), batch)) {
-            try {
-                //准备签章策略
-                List<SealStrategyVO> sealStrategyVOS = new ArrayList<>();
-                for (JSONObject eVisaConfig : eVisaConfigList) {
-                    //找到类型与之对应的合同章
-                    Iterator<SignPfxFile> iterator = userPfxList.iterator();
-                    while (iterator.hasNext()) {
-                        SignPfxFile next = iterator.next();
-                        if (eVisaConfig.getString("type").equals(next.getPfxType())) {
-                            //设置签章策略
-                            SealStrategyVO vo = new SealStrategyVO();
-                            vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + next.getId());
-                            vo.setSealPassword(next.getCertificatePassword());
-                            vo.setSealPerson(next.getCertificateUserName() + System.currentTimeMillis());
-                            //设置签字文件
-                            vo.setImageUrl(next.getSignatureFileUrl());
-                            vo.setSealType("3");
-
-                            vo.setCompanySeal(true);
-
-                            vo.setKeyword(eVisaConfig.getString("KEY"));
-                            vo.setOffSetX(eVisaConfig.getString("X"));
-                            vo.setOffSetY(eVisaConfig.getString("Y"));
-
-                            sealStrategyVOS.add(vo);
-                            iterator.remove();
-                            break;
-                        }
+                    //准备签章策略
+                    List<SealStrategyVO> sealStrategyVOS = new ArrayList<>();
+                    for (Map<String, Object> eVisaConfig : maps) {
+                        //设置签章策略
+                        SealStrategyVO vo = new SealStrategyVO();
+                        vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + eVisaConfig.get("sfId"));
+                        vo.setSealPassword(eVisaConfig.get("certificate_password") + "");
+                        vo.setSealPerson(eVisaConfig.get("certificate_user_name") + "" + System.currentTimeMillis());
+                        //设置签字文件
+                        vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
+                        vo.setSealType("3");
+                        vo.setCompanySeal(true);
+                        vo.setKeyword(eVisaConfig.get("id") + "");
+                        vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
+                        vo.setOffSetY(eVisaConfig.get("pyzby") + "");
+                        sealStrategyVOS.add(vo);
                     }
-                }
 
-                SealPdfVO pdfVO = new SealPdfVO();
-                pdfVO.setStrategyVoList(sealStrategyVOS);
-
-                //获取字节
-                byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(finalPdfUrl));
-                //执行电签
-                Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
-                if (result != null) {
-                    if (result[0] != null) {
-                        MultipartFile newFiles = new MockMultipartFile("file", SnowFlakeUtil.getId() + ".pdf", "text/plain", IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0])));
-                        //重新上传
-                        BladeFile bladeFile = this.newIOSSClient.uploadFileByInputStream(newFiles);
-                        if (bladeFile != null) {
-                            finalPdfUrl = bladeFile.getLink();
+                    SealPdfVO pdfVO = new SealPdfVO();
+                    pdfVO.setStrategyVoList(sealStrategyVOS);
+
+                    //获取字节
+                    byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(finalPdfUrl));
+                    //执行电签
+                    Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
+                    if (result != null) {
+                        if (result[0] != null) {
+                            MultipartFile newFiles = new MockMultipartFile("file", SnowFlakeUtil.getId() + ".pdf", "text/plain", IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0])));
+                            //重新上传
+                            BladeFile bladeFile = this.newIOSSClient.uploadFileByInputStream(newFiles);
+                            if (bladeFile != null) {
+                                finalPdfUrl = bladeFile.getLink();
+                            }
                         }
                     }
                 }
@@ -393,6 +350,7 @@ public class EVisaServiceImpl implements EVisaService {
     }
 
 
+
     /**
      * 个人-电签信息
      *
@@ -419,10 +377,10 @@ public class EVisaServiceImpl implements EVisaService {
            // 计量任务类型  5 = 中间计量申请,6 = 材料计量单,7 = 开工预付款计量单,8 = 变更令
             Map<String, Object> map =new HashMap<>();
             if(task.getApprovalType()==6 || task.getApprovalType()==7){
-                map = this.jdbcTemplate.queryForMap("select * from  s_material_start_statement where meter_period_id = " + task.getFormDataId());
+                map = this.jdbcTemplate.queryForMap("select * from  s_material_start_statement where is_deleted=0 and meter_period_id = " + task.getFormDataId());
                 taskFile.setApprovalFileList(map.get("period_number")+"", map.get("raw_url")+"");
             }else if (task.getApprovalType()==5) {
-                map = this.jdbcTemplate.queryForMap("select * from s_interim_pay_certificate where contract_period_id = " + task.getFormDataId());
+                map = this.jdbcTemplate.queryForMap("select * from s_interim_pay_certificate where  is_deleted=0 and contract_period_id = " + task.getFormDataId());
                 taskFile.setApprovalFileList(map.get("period_number")+"", map.get("raw_url")+"");
             }
             taskFile.setRemarkType("1");
@@ -722,20 +680,15 @@ public class EVisaServiceImpl implements EVisaService {
     }
 
   /*  public static void main(String[] args) throws Exception {
-        String pdfPath ="/Users/hongchuangyanfa/Downloads/d2cf9f4ee9bef0cad6c1105e86b3ab09.pdf";
-        String sealId ="0ff724e095fc4a16b9c9c25ebe44e68f";
+        String pdfPath ="/Users/hongchuangyanfa/Documents/fcf5efab3af8d1e7f26cec1d5fbdb634.pdf";
+        String sealId ="289b84c769694deba4c42599032699a4";
         String formDataId ="vv";
         List<Map<String,Object>> maps = new ArrayList<>();
         Map<String,Object> daMap = new HashMap<>();
-        daMap.put("keyWord","1715216098053324800");
+        daMap.put("keyWord","1630012525913309193");
         daMap.put("sealId",sealId);
         maps.add(daMap);
 
-        Map<String,Object> daMap2 = new HashMap<>();
-        daMap2.put("keyWord","1673632651463884");
-        daMap2.put("sealId",sealId);
-        maps.add(daMap2);
-
         String fileUrl =pdfPath;
         for(int i=0;i<maps.size();i++){
             HashMap daMa  = (HashMap) maps.get(i);
@@ -764,7 +717,8 @@ public class EVisaServiceImpl implements EVisaService {
      * @throws Exception
      */
     public static String signPdfByDFZX(HashMap<String, Object> request) {
-        String url = "http://47.110.251.215:9125/FrontSysGs/SealServicezx/FileSignByKeyWord";
+        String url = "http://39.108.216.210:9125/FrontSysGs/SealServicezx/FileSignByKeyWord";
+       // String url = "http://172.30.224.81:9125/FrontSysGs/SealServicezx/FileSignByKeyWord";
         String sysLocalFileUrl = FileUtils.getSysLocalFileUrl();
         String filecode = SnowFlakeUtil.getId() + "";
         String dataFileUrl = sysLocalFileUrl + "/pdf/" + filecode + ".pdf";

+ 4 - 0
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -1386,6 +1386,10 @@ public static Map<String,List<Long>> relatedPages(List<FormData> curFormDatas ,L
     public static  Optional<FormData>  elementFindByCode( Map<String, FormData> formDataMap ,String code){
         return formDataMap.values().stream().filter(e->code.equals(e.getCode())).findAny();
     }
+    /*根据key查找元素 ,用于元素范围在同一张表情况*/
+    public static  Optional<FormData>  elementFindByKey( Map<String, FormData> fdm ,String key){
+        return fdm.values().stream().filter(e->key.equals(e.getCode().split(":")[1])).findAny();
+    }
 
     public static List<TableInfo> getTableInfoList(JSONArray dataArray) {
         if (dataArray != null && !dataArray.isEmpty()) {

+ 7 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java

@@ -162,10 +162,14 @@ public class TextdictInfoController extends BladeController {
     @PostMapping("/remove")
     @ApiOperationSupport(order = 7)
     @ApiOperation(value = "逻辑删除", notes = "传入ids")
-    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) throws FileNotFoundException {
+    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids,@ApiParam(value = "wbs p_key_id", required = true) @RequestParam String tabId) throws FileNotFoundException {
         //获取节点信息
-        TextdictInfo textdictInfo = textdictInfoService.getById(ids);
-        WbsTreePrivate wbsTreePrivate = wbsTreePrivateMapper.getByPKeyId(Long.parseLong(textdictInfo.getTabId()));
+
+        WbsTreePrivate wbsTreePrivate = wbsTreePrivateMapper.getByPKeyId(Long.parseLong(tabId));
+        TextdictInfo textdi = new TextdictInfo();
+        textdi.setId(Func.toLong(ids));
+        textdi.setProjectId(wbsTreePrivate.getProjectId());
+        TextdictInfoVO textdictInfo = textdictInfoService.selectTextdictInfoById(textdi);
 
         //获取当前项目下引用相同模板的元素表信息
         List<WbsTreePrivate> wbsTreePrivatesEqual = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeController.java

@@ -299,6 +299,7 @@ public class WbsTreeController extends BladeController {
          set.add(InterimPaymentCertificate.ID);
          set.add(InterimPaymentSummary.ID);
          set.add(SubprojectInterimPaymentSummary.ID);
+         set.add(ConstructionSchedule.ID);
          set.add(SubInterimMeterPaySummary.ID);
          set.add(InterimMeterPaySummary.ID);
          set.add(InterimMeter.ID);
@@ -314,6 +315,7 @@ public class WbsTreeController extends BladeController {
         MODEL_MAP.put(InterimPaymentCertificate.ID,FormulaUtils.toElementVos(InterimPaymentCertificate.class));
         MODEL_MAP.put(InterimPaymentSummary.ID,FormulaUtils.toElementVos(InterimPaymentSummary.class));
         MODEL_MAP.put(SubprojectInterimPaymentSummary.ID,FormulaUtils.toElementVos(SubprojectInterimPaymentSummary.class));
+        MODEL_MAP.put(ConstructionSchedule.ID,FormulaUtils.toElementVos(ConstructionSchedule.class));
         MODEL_MAP.put(SubInterimMeterPaySummary.ID,FormulaUtils.toElementVos(SubInterimMeterPaySummary.class));
         MODEL_MAP.put(InterimMeterPaySummary.ID,FormulaUtils.toElementVos(InterimMeterPaySummary.class));
         MODEL_MAP.put(InterimMeter.ID,FormulaUtils.toElementVos(InterimMeter.class));

+ 166 - 122
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.formula.impl;
 
+import cn.hutool.log.StaticLog;
 import com.mixsmart.utils.CustomFunction;
 import com.mixsmart.utils.FormulaUtils;
 import com.mixsmart.utils.StringUtils;
@@ -53,6 +54,8 @@ public class ExecutorMeter extends FormulaExecutor {
     private List<Payment>   paymentsPeriodEnd =new ArrayList<>();
 
     private List<InterimPaymentCertificate> interimPaymentCertificates =new ArrayList<>();
+    /*分项中期汇总*/
+    private List<SubprojectInterimPaymentSummary> subprojectInterimPaymentSummarys  =new ArrayList<>();
     /*求百分比*/
     private BinaryOperator<String> ratioFc = (a,b)->{
         /*合同金额*/
@@ -111,6 +114,7 @@ public class ExecutorMeter extends FormulaExecutor {
             this.specialList.add(new InterimPayCert());
             this.specialList.add(new InterimSum());
             this.specialList.add(new SubIPaySum());
+            this.specialList.add(new ConSch());
             this.specialList.add(new SubIMeterPay());
             this.specialList.add(new IMeterPaySummary());
             /*中间计量表*/
@@ -607,129 +611,44 @@ public class ExecutorMeter extends FormulaExecutor {
                 sis.setPayRatio(ratioFc.apply(sis.getCurrentPeriodEndPay(),sis.getChangeMoney()));
                 totalList.add(sis);
             });
-        /*    if(MeterInfo.MB_ZJ.equals(tec.meterInfo.getConfig())){
-                *//*把所有计量期根据打印日期按自然月分类,支付信息按计量期分类*//*
-               LinkedHashMap<Long,MeterPeriodInfo> meterPeriodInfoMap = tec.meterInfo.getMeterPeriodInfoLinkedHashMap();
-               LinkedHashMap<Integer,MeterPeriodInfo> monthMeterMap=meterPeriodInfoMap.values().stream().collect(Collectors.toMap(e->e.getFormPrintDate().getMonthValue(),t->t,(v1,v2)->v2,LinkedHashMap::new));
-               *//*根据清单编号、计量期分组*//*
-                Map<String,Map<Long,List<Payment>>> paymentGroup=paymentsPeriodEnd.stream().collect(Collectors.groupingBy(Payment::getNumber,Collectors.groupingBy(Payment::getPeriodId,Collectors.toList())));
-               int max=monthMeterMap.keySet().stream().max(Comparator.comparingInt(t->t)).orElse(12);
-                BaseInfo baseInfo =tec.meterInfo.getBaseInfo();
-                totalList.forEach(sis->{
-                   *//*单项占合同价的比例*//*
-                   sis.setItemPercent(ratioFc.apply(sis.getChangeMoney(),baseInfo.getTotalAmount().toString()));
-                   *//*单项计划完成完成比例*//*
-                   sis.setItemProgress(ratioFc.apply(sis.getCurrentPeriodEndPay(),sis.getChangeMoney()));
-                   *//*本期占合同金额*//*
-                   sis.setCurrentPayPercent(ratioFc.apply(sis.getCurrentPeriodPay(), sis.getChangeMoney()));
-                   *//*本期末累计支付金额占合同比*//*
-                   sis.setPayPercent(ratioFc.apply(sis.getCurrentPeriodEndPay(),sis.getChangeMoney()));
-                   *//*根据月份来获取payment*//*
-                   Map<Long,List<Payment>> meterPaymentGroup = paymentGroup.get(sis.getFormNumber());
-                   *//*当前月已经累计的*//*
-                   List<Payment> pl =new ArrayList<>();
-                   for(int i=1;i<=max;i++){
-                       MeterPeriodInfo period = monthMeterMap.get(i);
-                       if(period!=null) {
-                           List<Payment> pays = meterPaymentGroup.get(period.getId());
-                           if (Func.isNotEmpty(pays)) {
-                               pl.addAll(pays);
-                           }
-                       }
-                       if(pl.size()>0) {
-                           sis.getMonthlyCompletion().add(new ArrayList<>(pl));
-                       }
-                   }
-               });
-                *//*输出设置*//*
-                *//*合同按月计划完成进度*//*
-                fieldDataFcMap.put(SubprojectInterimPaymentSummary.TBN+":key_21",dl->dl.stream().flatMap(e->{
-                    List<List<Payment>> l= e.getMonthlyCompletion();
-                    return  IntStream.range(0,12).boxed().map(month->{
-                        if(month>=l.size()){
-                            return StringPool.EMPTY;
-                        }else{
-                            List<Payment> cur=l.get(month);
-                            String money=cur.stream().map(Payment::getMoneyAsBigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
-                            String change =cur.get(0).getChangeMoney();
-                            return ratioFc.apply(money,change);
-                        }
-                    });
-               }).collect(Collectors.toList()));
-                *//*分页*//*
-                List<List<SubprojectInterimPaymentSummary>> pageList = BaseUtils.splitList(totalList,capacity);
-                BiFunction<List<SubprojectInterimPaymentSummary>,Function<SubprojectInterimPaymentSummary,String>,String> sumFc= (page,fc)->page.stream().map(fc).map(BaseUtils::str2BigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
-                pageList.forEach(page->{
-                        dataList.addAll(page);
-                        SubprojectInterimPaymentSummary sis = new SubprojectInterimPaymentSummary("合计 (万元)");
-                        *//*合同金额*//*
-                        sis.setContractMoney(sumFc.apply(page,SubprojectInterimPaymentSummary::getContractMoney));
-                        *//*变更后的金额*//*
-                        sis.setChangeMoney(sumFc.apply(page,SubprojectInterimPaymentSummary::getChangeMoney));
-                        *//*实际工程量金额*//*
-                        sis.setCurrentPeriodPay(page.stream().map(SubprojectInterimPaymentSummary::getCurrentPeriodPay).map(BaseUtils::str2BigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString());
-                        dataList.add(sis);
-                });
-                *//*实际完成,累计完成、按月完成*//*
-                List<List<List<Payment>>> all =totalList.stream().map(SubprojectInterimPaymentSummary::getMonthlyCompletion).collect(Collectors.toList());
-                FormulaUtils.beRelyFrom(tec.getFormDataMap(),SubprojectInterimPaymentSummary.TBN,"key_22,key_23,key_24").forEach(e->e.setRepeat(true));
-                *//*每月合计进度*//*
-                List<String> monthlySum= IntStream.range(0,max).boxed().map(month->{
-                    List<Payment> tmp=  all.stream().flatMap(row->row.get(month).stream()).collect(Collectors.toList());
-                    return  ratioFc.apply(tmp.stream().map(Payment::getMoneyAsBigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString(),baseInfo.getTotalAmount().toString());
-                }).collect(Collectors.toList());
-                FormulaUtils.elementFindByCode(fdm,SubprojectInterimPaymentSummary.TBN+":key_22").ifPresent(t->{
-                    elementWriter.write(t,monthlySum);
-                });
-
-                AtomicReference<Double> cp = new AtomicReference<>(0.0);
-                FormulaUtils.elementFindByCode(fdm,SubprojectInterimPaymentSummary.TBN+":key_23").ifPresent(t->{
-                    elementWriter.write(t, monthlySum.stream().map(e->{double r=BaseUtils.obj2DoubleZero(e)- cp.get();
-                        cp.set(BaseUtils.obj2DoubleZero(e));return r;}).collect(Collectors.toList()));
-                });
-                *//*合同概要*//*
-                FormulaUtils.elementFindByCode(fdm,SubprojectInterimPaymentSummary.TBN+":key_24").ifPresent(t->{
-                    elementWriter.write(t,"开工日期:"+baseInfo.getStartDatePlan()+" 始算工期日:"+baseInfo.getStartDate()+" 合同完成日期:"+baseInfo.getEndDatePlan()+" 合同期限$4天 时间延长$5天 修改后合同期限"+ CustomFunction.daysPassed(baseInfo.getStartDate(),baseInfo.getEndDate()) +"天(即至"+baseInfo.getEndDate()+")\n 合同总价"+baseInfo.getContractAmount().divide(new BigDecimal(10000),2,RoundingMode.HALF_UP)+"万元、暂定金$9万元、工程量清单金额$10万元、BG估计最终金额$11万元");
-                });
-
-            }else*/
-            {
-                LinkedHashMap<String,List<SubprojectInterimPaymentSummary>> chapterGroup= totalList.stream().collect(Collectors.groupingBy(e->getPrefix(e.getFormNumber()),LinkedHashMap::new,Collectors.toList()));
-                AtomicInteger loop = new AtomicInteger(chapterGroup.size());
-                chapterGroup.forEach((k,v)->{
-                    int extra=loop.getAndDecrement()>0?1:2;
-                    /*每章小结或总结等价一行数据*/
-                    int dataLength=v.size()+extra;
-                    /*每页小结是固定内容,需要每页保留一行*/
-                    int dataAreaSize=capacity-1;
-                    int pageSize=(int)Math.ceil(dataLength/(double)dataAreaSize);
-                    List<List<SubprojectInterimPaymentSummary>> ds = BaseUtils.splitList(v,capacity-1);
-                    List<SubprojectInterimPaymentSummary> tmp = new ArrayList<>();
-                    for(int n=0;n<pageSize;n++){
-                        List<SubprojectInterimPaymentSummary> currentPageData =ds.get(n);
-                        tmp.addAll(currentPageData);
-                        int m=1;
-                        if(pageSize-n==1){
-                            m+=extra;
-                        }
-                        int placeholderSize = capacity-m-currentPageData.size();
-                        if(placeholderSize>0){
-                            tmp.addAll(Collections.nCopies(placeholderSize,new SubprojectInterimPaymentSummary()));
-                        }
-                        subtotal(new SubprojectInterimPaymentSummary("本页小计"),tmp,currentPageData,tec.getScale());
-                        if(m>1) {
-                            /*本章小结*/
-                            subtotal(new SubprojectInterimPaymentSummary("章合计"),tmp,v,tec.getScale());
-                        }
-                        if(m>2){
-                            /*所有章合计*/
-                            subtotal(new SubprojectInterimPaymentSummary("所有章合计"),tmp,totalList,tec.getScale());
-                        }
-                        dataList.addAll(tmp);
-                        tmp.clear();
+            totalList.forEach(e->{
+                subprojectInterimPaymentSummarys.add(e.copy());
+            });
+            LinkedHashMap<String,List<SubprojectInterimPaymentSummary>> chapterGroup= totalList.stream().collect(Collectors.groupingBy(e->getPrefix(e.getFormNumber()),LinkedHashMap::new,Collectors.toList()));
+            AtomicInteger loop = new AtomicInteger(chapterGroup.size());
+            chapterGroup.forEach((k,v)->{
+                int extra=loop.getAndDecrement()>0?1:2;
+                /*每章小结或总结等价一行数据*/
+                int dataLength=v.size()+extra;
+                /*每页小结是固定内容,需要每页保留一行*/
+                int dataAreaSize=capacity-1;
+                int pageSize=(int)Math.ceil(dataLength/(double)dataAreaSize);
+                List<List<SubprojectInterimPaymentSummary>> ds = BaseUtils.splitList(v,capacity-1);
+                List<SubprojectInterimPaymentSummary> tmp = new ArrayList<>();
+                for(int n=0;n<pageSize;n++){
+                    List<SubprojectInterimPaymentSummary> currentPageData =ds.get(n);
+                    tmp.addAll(currentPageData);
+                    int m=1;
+                    if(pageSize-n==1){
+                        m+=extra;
                     }
-                });
-            }
+                    int placeholderSize = capacity-m-currentPageData.size();
+                    if(placeholderSize>0){
+                        tmp.addAll(Collections.nCopies(placeholderSize,new SubprojectInterimPaymentSummary()));
+                    }
+                    subtotal(new SubprojectInterimPaymentSummary("本页小计"),tmp,currentPageData,tec.getScale());
+                    if(m>1) {
+                        /*本章小结*/
+                        subtotal(new SubprojectInterimPaymentSummary("章合计"),tmp,v,tec.getScale());
+                    }
+                    if(m>2){
+                        /*所有章合计*/
+                        subtotal(new SubprojectInterimPaymentSummary("所有章合计"),tmp,totalList,tec.getScale());
+                    }
+                    dataList.addAll(tmp);
+                    tmp.clear();
+                }
+            });
             /*内容输出*/
              putOut(SubprojectInterimPaymentSummary.class);
         }
@@ -753,7 +672,117 @@ public class ExecutorMeter extends FormulaExecutor {
 
     }
 
+    @Data
+    @EqualsAndHashCode(callSuper = true)
+    public  class ConSch extends   BaseSpecial<ConstructionSchedule> implements Special{
 
+        @Override
+        public boolean ready() {
+            return subprojectInterimPaymentSummarys.size()>0&&MeterInfo.MB_ZJ.equals(tec.getMeterInfo().getConfig());
+        }
+
+        @Override
+        public void parse() {
+            builderFormDatas(ConstructionSchedule.class);
+            List<ConstructionSchedule> totalList = new ArrayList<>();
+            subprojectInterimPaymentSummarys.forEach(e->{
+                ConstructionSchedule cs = new ConstructionSchedule();
+                BeanUtils.copyProperties(e,cs);
+                totalList.add(cs);
+            });
+            /*把所有计量期根据打印日期按自然月分类,支付信息按计量期分类*/
+            LinkedHashMap<Long,MeterPeriodInfo> meterPeriodInfoMap = tec.meterInfo.getMeterPeriodInfoLinkedHashMap();
+            LinkedHashMap<Integer,MeterPeriodInfo> monthMeterMap=meterPeriodInfoMap.values().stream().collect(Collectors.toMap(e->e.getFormPrintDate().getMonthValue(),t->t,(v1,v2)->v2,LinkedHashMap::new));
+            /*  根据清单编号、计量期分组*/
+            Map<String,Map<Long,List<Payment>>> paymentGroup=paymentsPeriodEnd.stream().collect(Collectors.groupingBy(Payment::getNumber,Collectors.groupingBy(Payment::getPeriodId,Collectors.toList())));
+            int max=monthMeterMap.keySet().stream().max(Comparator.comparingInt(t->t)).orElse(12);
+            BaseInfo baseInfo =tec.meterInfo.getBaseInfo();
+            totalList.forEach(sis->{
+                /*    单项占合同价的比例*/
+                sis.setItemPercent(ratioFc.apply(sis.getChangeMoney(),baseInfo.getTotalAmount().toString()));
+                /*单项计划完成完成比例*/
+                sis.setItemProgress(ratioFc.apply(sis.getCurrentPeriodEndPay(),sis.getChangeMoney()));
+                /*本期占合同金额*/
+                sis.setCurrentPayPercent(ratioFc.apply(sis.getCurrentPeriodPay(), sis.getChangeMoney()));
+                /* 本期末累计支付金额占合同比*/
+                sis.setPayPercent(ratioFc.apply(sis.getCurrentPeriodEndPay(),sis.getChangeMoney()));
+                /* 根据月份来获取payment*/
+                Map<Long,List<Payment>> meterPaymentGroup = paymentGroup.get(sis.getFormNumber());
+                /* 当前月已经累计的*/
+                List<Payment> pl =new ArrayList<>();
+                for(int i=1;i<=max;i++){
+                    MeterPeriodInfo period = monthMeterMap.get(i);
+                    if(period!=null) {
+                        List<Payment> pays = meterPaymentGroup.get(period.getId());
+                        if (Func.isNotEmpty(pays)) {
+                            pl.addAll(pays);
+                        }
+                    }
+                    if(pl.size()>0) {
+                        sis.getMonthlyCompletion().add(new ArrayList<>(pl));
+                    }
+                }
+            });
+              /*  输出设置
+             合同按月计划完成进度*/
+            fieldDataFcMap.put(ConstructionSchedule.TBN+":key_21",dl->dl.stream().flatMap(e->{
+                List<List<Payment>> l= e.getMonthlyCompletion();
+                return  IntStream.range(0,12).boxed().map(month->{
+                    if(month>=l.size()){
+                        return StringPool.EMPTY;
+                    }else{
+                        List<Payment> cur=l.get(month);
+                        String money=cur.stream().map(Payment::getMoneyAsBigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
+                        String change =cur.get(0).getChangeMoney();
+                        return ratioFc.apply(money,change);
+                    }
+                });
+            }).collect(Collectors.toList()));
+            /*分页*/
+            List<List<ConstructionSchedule>> pageList = BaseUtils.splitList(totalList,capacity);
+            BiFunction<List<ConstructionSchedule>,Function<ConstructionSchedule,String>,String> sumFc= (page,fc)->page.stream().map(fc).map(BaseUtils::str2BigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString();
+            pageList.forEach(page->{
+                dataList.addAll(page);
+                ConstructionSchedule sis = new ConstructionSchedule("合计 (万元)");
+                /*合同金额*/
+                sis.setContractMoney(sumFc.apply(page,ConstructionSchedule::getContractMoney));
+                /*变更后的金额*/
+                sis.setChangeMoney(sumFc.apply(page,ConstructionSchedule::getChangeMoney));
+                /*实际工程量金额*/
+                sis.setCurrentPeriodPay(page.stream().map(ConstructionSchedule::getCurrentPeriodPay).map(BaseUtils::str2BigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString());
+                dataList.add(sis);
+            });
+            /* 实际完成,累计完成、按月完成*/
+            List<List<List<Payment>>> all =totalList.stream().map(ConstructionSchedule::getMonthlyCompletion).collect(Collectors.toList());
+            FormulaUtils.beRelyFrom(tec.getFormDataMap(),ConstructionSchedule.TBN,"key_22,key_23,key_24").forEach(e->e.setRepeat(true));
+            /*每月合计进度*/
+            try {
+                List<String> monthlySum= IntStream.range(0,max).boxed().map(month->{
+                    List<Payment> tmp=  all.stream().flatMap(row->row.get(month).stream()).collect(Collectors.toList());
+                    return  ratioFc.apply(tmp.stream().map(Payment::getMoneyAsBigDecimal).reduce(BigDecimal.ZERO,BigDecimal::add).toString(),baseInfo.getTotalAmount().toString());
+                }).collect(Collectors.toList());
+                FormulaUtils.elementFindByCode(fdm,ConstructionSchedule.TBN+":key_22").ifPresent(t->{
+                    elementWriter.write(t,monthlySum);
+                });
+                AtomicReference<Double> cp = new AtomicReference<>(0.0);
+                FormulaUtils.elementFindByCode(fdm,ConstructionSchedule.TBN+":key_23").ifPresent(t->{
+                    elementWriter.write(t, monthlySum.stream().map(e->{double r=BaseUtils.obj2DoubleZero(e)- cp.get();
+                        cp.set(BaseUtils.obj2DoubleZero(e));return r;}).collect(Collectors.toList()));
+                });
+            }catch (Exception e){
+                StaticLog.error(e.getMessage());
+            }
+
+            /* 合同概要*/
+            FormulaUtils.elementFindByCode(fdm,ConstructionSchedule.TBN+":key_24").ifPresent(t->{
+                elementWriter.write(t,"开工日期:"+baseInfo.getStartDatePlan()+" 始算工期日:"+baseInfo.getStartDate()+" 合同完成日期:"+baseInfo.getEndDatePlan()+" 合同期限$4天 时间延长$5天 修改后合同期限"+ CustomFunction.daysPassed(baseInfo.getStartDate(),baseInfo.getEndDate()) +"天(即至"+baseInfo.getEndDate()+")\n 合同总价"+baseInfo.getContractAmount().divide(new BigDecimal(10000),2,RoundingMode.HALF_UP)+"万元、暂定金$9万元、工程量清单金额$10万元、BG估计最终金额$11万元");
+            });
+
+            /*内容输出*/
+            putOut(ConstructionSchedule.class);
+        }
+
+    }
 
     @Data
     @EqualsAndHashCode(callSuper = true)
@@ -955,6 +984,10 @@ public class ExecutorMeter extends FormulaExecutor {
                 double sum=dataList.stream().map(InterimMeterPaySummary::getMoney).filter(StringUtils::isNumber).mapToDouble(Double::parseDouble).sum();
                 summary.setMoney(StringUtils.number2StringZero(sum,tec.getScale()));
                 dataList.add(summary);
+                FormulaUtils.elementFindByCode(tec.getFormDataMap(),MeterPeriodInfo.TBN+":key_10").ifPresent(fd->{
+                    elementWriter.write(fd,BaseUtils.sliceNumber(dataList.size(),capacity));
+                });
+
             }
             putOut(InterimMeterPaySummary.class);
         }
@@ -997,6 +1030,8 @@ public class ExecutorMeter extends FormulaExecutor {
                     iim.setItemNameList(itemNameList);
                     iim.setUnitList(unitList);
                     iim.setCompletedList(completedList);
+                    iim.setFormNumber(iim.getFormNumberList().stream().filter(Func::isNotEmpty).distinct().collect(Collectors.joining("、")));
+                    iim.setItemName(iim.getItemNameList().stream().filter(Func::isNotEmpty).distinct().collect(Collectors.joining("、")));
                     dataList.add(iim);
                 }
             }
@@ -1008,6 +1043,9 @@ public class ExecutorMeter extends FormulaExecutor {
             fieldDataFcMap.put(InterimMeter.TBN+":key_13",interimMeters2oListFc.apply(InterimMeter::getCompletedList));
            /*每条记录一页*/
             capacity=1;
+            FormulaUtils.elementFindByCode(tec.getFormDataMap(),MeterPeriodInfo.TBN+":key_11").ifPresent(fd->{
+                elementWriter.write(fd,BaseUtils.sliceNumber(dataList.size(),capacity));
+            });
            putOut(InterimMeter.class);
         }
     }
@@ -1062,6 +1100,12 @@ public class ExecutorMeter extends FormulaExecutor {
             pageNumber(clazz);
             FormulaUtils.put2FormData(fdm, fieldDataFcMap,dataList);
         };
+
+        public void write(Object data){
+            FormulaUtils.elementFindByKey(fdm,"key_24").ifPresent(t->{
+                elementWriter.write(t,data);
+            });
+        }
     }
     interface  Special{
         /**是否满足执行条件*/

+ 0 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/MeterElementWriter.java

@@ -11,7 +11,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
-import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
 
 /**

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java

@@ -210,7 +210,7 @@ public class SubTable {
                 if (StringUtils.isNotEmpty(x) && !x.equals(name) || (i == itemName.size() - 1)) {
                    /* String des =designs.subList(head, i).stream().filter(StringUtils::isNotEmpty).distinct().collect(Collectors.joining("/"));*/
                     Item item = new Item(name);
-                    if(designs!=null) {
+                    if(designs!=null&&designs.size()>0) {
                         item.setDesign(designs.subList(head, i).stream().filter(StringUtils::isNotEmpty).distinct().collect(Collectors.toList()));
                     }
                    /* original.put(name + StringPool.AT + des, new ArrayList<>(data.subList(head*15,  i*ROW_SIZE)));*/

+ 11 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -336,7 +336,14 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                     }else{
                                         values=  itemBlockList.stream().map(ItemBlock::getData).flatMap(v -> v.stream().flatMap(Collection::stream)).map(Func::toStr).collect(Collectors.toList());
                                     }
-
+                                    if(t.getPoint().contains("榀数")){
+                                        if(values.size()>0) {
+                                            double x=values.stream().mapToDouble(Double::parseDouble).sum() / 3.0;
+                                            if(x!=0) {
+                                                values = Collections.singletonList(StringUtils.number2String(x, 0));
+                                            }
+                                        }
+                                    }
                                     int scale = StringUtils.getScale(values);
                                     FormulaUtils.write(t.getValue(), values.stream().filter(StringUtils::isNotEmpty).map(u -> {
                                               if(StringUtils.isNumber(u)){
@@ -1486,8 +1493,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
     /**加页增容*/
    public void copy(FormData fd,TableElementConverter tec){
-       if(fd.getAddPages()>20){
-           /*最大页数20*/
+       if(fd.getAddPages()>30){
+           /*最大页数30*/
+           StaticLog.error("{}超过最大30页限制",fd.getTableChName()+fd.getEName());
            return;
        }
        int pageAdd=fd.getAddPages();

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -265,6 +265,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         titleMap.put(InterimPaymentCertificate.TBN_CH, new String[]{InterimPaymentCertificate.TBN, InterimPaymentCertificate.ID});
         titleMap.put(InterimPaymentSummary.TBN_CH, new String[]{InterimPaymentSummary.TBN, InterimPaymentSummary.ID});
         titleMap.put(SubprojectInterimPaymentSummary.TBN_CH, new String[]{SubprojectInterimPaymentSummary.TBN, SubprojectInterimPaymentSummary.ID});
+        titleMap.put(ConstructionSchedule.TBN_CH, new String[]{ConstructionSchedule.TBN, ConstructionSchedule.ID});
         titleMap.put(SubInterimMeterPaySummary.TBN_CH, new String[]{SubInterimMeterPaySummary.TBN, SubInterimMeterPaySummary.ID});
         titleMap.put(InterimMeterPaySummary.TBN_CH, new String[]{InterimMeterPaySummary.TBN, InterimMeterPaySummary.ID});
         titleMap.put(InterimMeter.TBN_CH, new String[]{InterimMeter.TBN, InterimMeter.ID});

+ 3 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/ContractMeterPeriodController.java

@@ -111,6 +111,9 @@ public class ContractMeterPeriodController extends BladeController {
 				if (interimPayCertificate != null) {
 					interimPayCertificate.setPeriodNumber(period.getPeriodNumber());
 					interimPayCertificate.setPrintDate(period.getFormPrintDate());
+					interimPayCertificate.setStartDate(period.getStartDate());
+					interimPayCertificate.setEndDate(period.getEndDate());
+					interimPayCertificate.setCertificateNumber(interimPayCertificate.getPeriodNumber());
 					interimPayCertificateService.saveOrUpdate(interimPayCertificate);
 				}
 			}

+ 1 - 1
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/MeterTreeController.java

@@ -343,7 +343,7 @@ public class MeterTreeController extends BladeController {
                 return R.fail(400, "请勿重复提交,30秒后再尝试");
             }
             bladeRedis.set(redisKey, "1");
-            bladeRedis.expire(redisKey, 30);
+            bladeRedis.expire(redisKey, 5);
 
             /*初始化 或 增量同步 项目计量树*/
             return meterTreeProjectService.projectTreeInitOrSync(projectInfo.getMeterTemplateId(), Long.parseLong(projectId));

+ 50 - 20
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

@@ -1,7 +1,9 @@
 package org.springblade.meter.controller;
 
 
+import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSON;
+import com.aspose.cells.PageSetup;
 import com.aspose.cells.SaveFormat;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -16,6 +18,7 @@ import com.itextpdf.text.pdf.PdfCopy;
 import com.itextpdf.text.pdf.PdfReader;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.models.auth.In;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import org.apache.commons.lang.StringUtils;
@@ -54,6 +57,7 @@ import org.springblade.manager.entity.ContractRelationJlyz;
 import org.springblade.manager.entity.TextdictInfo;
 import org.springblade.manager.feign.FormulaClient;
 import org.springblade.manager.vo.MeterInfo;
+import org.springblade.manager.vo.ReportMergeCellsConfig;
 import org.springblade.manager.vo.ReportResult;
 import org.springblade.meter.dto.*;
 import org.springblade.meter.entity.*;
@@ -2763,6 +2767,8 @@ public class TaskController extends BladeController {
                         throw new RuntimeException(e);
                     }
                 });
+                /*写死合并*/
+                List<ReportMergeCellsConfig> configList = ReportMergeCellsConfig.bulider();
                 /*每种表生成一份pdf*/
                 StringBuffer sb = new StringBuffer();
                 reportResults.parallelStream().forEach(rs -> {
@@ -2789,26 +2795,22 @@ public class TaskController extends BladeController {
                                         int x1 = Func.toInt(keys.split("_")[1]);
                                         Row row = sheet.getRow(y1 - 1);
                                         if (row != null) {
-                                            Cell cell = row.getCell(x1 - 1);
-                                            if (cell != null) {
-                                                String value = dataMap.getOrDefault(keys, StringPool.EMPTY).toString();
-                                                if (value.startsWith("http")&&RegexUtil.find("(?i)[.](jpeg|png|jpg)",value)) {
-                                                    InputStream imageIn = CommonUtil.getOSSInputStream(value);
-                                                    if (imageIn != null) {
-                                                        byte[] bytes = CommonUtil.compressImage(IOUtils.toByteArray(imageIn));
-                                                        CreationHelper helper = workbook.getCreationHelper();
-                                                        ClientAnchor anchor = helper.createClientAnchor();
-                                                        Drawing<?> drawing = sheet.createDrawingPatriarch();
-                                                        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
-                                                        Picture pict = drawing.createPicture(anchor, workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG)); // 调整图片占单元格百分比的大小,1.0就是100%
-                                                        pict.resize(1, 1);
-                                                        CollectionUtils.imageOrientation(sheet, anchor, new DataVO(x1 - 1, y1 - 1));
-                                                    }
-                                                } else {
-                                                    cell.setCellValue(value);
+                                            Cell cell = row.getCell(x1 - 1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
+                                            String value = dataMap.getOrDefault(keys, StringPool.EMPTY).toString();
+                                            if (value.startsWith("http")&&RegexUtil.find("(?i)[.](jpeg|png|jpg)",value)) {
+                                                InputStream imageIn = CommonUtil.getOSSInputStream(value);
+                                                if (imageIn != null) {
+                                                    byte[] bytes = CommonUtil.compressImage(IOUtils.toByteArray(imageIn));
+                                                    CreationHelper helper = workbook.getCreationHelper();
+                                                    ClientAnchor anchor = helper.createClientAnchor();
+                                                    Drawing<?> drawing = sheet.createDrawingPatriarch();
+                                                    anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
+                                                    Picture pict = drawing.createPicture(anchor, workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG)); // 调整图片占单元格百分比的大小,1.0就是100%
+                                                    pict.resize(1, 1);
+                                                    CollectionUtils.imageOrientation(sheet, anchor, new DataVO(x1 - 1, y1 - 1));
                                                 }
                                             } else {
-                                                System.out.println(keys + "不存在");
+                                                cell.setCellValue(value);
                                             }
                                         }
                                     }
@@ -2821,11 +2823,23 @@ public class TaskController extends BladeController {
                                 sheet.setPrintGridlines(false);
                                 //设置 整个工作表为一页
                                 sheet.setFitToPage(true);
-                                sheet.getPrintSetup().setPaperSize(PrintSetup.A4_PAPERSIZE);
+                                PrintSetup printSetup = sheet.getPrintSetup();
+                                /*printSetup.setFitHeight((short) 1);
+                                printSetup.setFitWidth((short) 1);*/
+                                // 设置页边距,单位为厘米
+                                printSetup.setPaperSize(PrintSetup.A4_PAPERSIZE);
+
                                 ByteArrayOutputStream out = new ByteArrayOutputStream();
                                 workbook.write(out);
-                                //workbook.write(new FileOutputStream(rs.getExcelPath()));
+                                workbook.write(new FileOutputStream(rs.getExcelPath()));
                                 com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(new ByteArrayInputStream(out.toByteArray()));
+                                PageSetup pageSetup =wb.getWorksheets().get(0).getPageSetup();
+                                pageSetup.setLeftMargin(0.5);   // 左边距
+                                pageSetup.setRightMargin(0.5);  // 右边距
+                                pageSetup.setTopMargin(1.5);    // 上边距
+                                pageSetup.setBottomMargin(1.5); // 下边距*/
+                                pageSetup.setCenterHorizontally(true);
+                                pageSetup.setCenterVertically(true);
                                 out.reset();
                                 wb.save(out, SaveFormat.PDF);
                                 reader = new PdfReader(new ByteArrayInputStream(out.toByteArray()));
@@ -2871,6 +2885,22 @@ public class TaskController extends BladeController {
         return R.data(fileUrl);
     }
 
+     /*固定合并*/
+    private void mergeCells(Sheet sheet, List<ReportMergeCellsConfig> configList){
+        if(configList.size()>0){
+            configList.forEach(c->{
+                List<Integer> list = BaseUtils.coords2Int(c.getMergeRange());
+                if(list.size()>0) {
+                    try {
+                        sheet.addMergedRegion(new CellRangeAddress(list.get(1), list.get(3),list.get(0),list.get(2)));
+                    }catch (Exception e){
+                        StaticLog.error(e.getMessage());
+                    }
+
+                }
+            });
+        }
+    }
 
 
     // 添加电签任务列表

+ 7 - 3
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/MeterTreeProjectServiceImpl.java

@@ -68,6 +68,8 @@ public class MeterTreeProjectServiceImpl extends BaseServiceImpl<MeterTreeProjec
                 logger.info(" ==================== 已成功删除旧系统模板id {} 项目id {} 的合同段单元树数据 ==================== ", meterTreeProject.getTemplateId(), projectId);
             }
         }
+        //新增总数
+        int addTotal = 0;
 
         if (rootNode.size() == 0) {
             /*================== 新增初始化 ==================*/
@@ -130,7 +132,8 @@ public class MeterTreeProjectServiceImpl extends BaseServiceImpl<MeterTreeProjec
 
                 if (sortedList.size() == systemNodeIds.size()) {
                     if (this.saveBatch(sortedList, 1000)) {
-                        return R.success("操作成功");
+                        addTotal = sortedList.size();
+                        return R.success("同步完成,新增个"+addTotal+"节点!");
                     } else {
                         return R.fail("操作失败");
                     }
@@ -260,17 +263,18 @@ public class MeterTreeProjectServiceImpl extends BaseServiceImpl<MeterTreeProjec
 
                                 /*入库*/
                                 this.saveBatch(sortedList, 1000);
+                                addTotal = sortedList.size();
                             }
                         }
 
                     }
-                    return R.success("操作成功");
+                    return R.success("同步完成,新增个"+addTotal+"节点!");
                 } catch (Exception e) {
                     e.printStackTrace();
                     throw new ServiceException("操作异常!");
                 }
             } else {
-                return R.fail("未获取到需要同步的系统级计量单元信息!");
+                return R.success("同步完成,新增0个节点!");
             }
         }
     }