Browse Source

计量公式\分部评定

yangyj 1 year ago
parent
commit
6bb120b657

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

@@ -350,4 +350,5 @@ public class BaseUtils {
     }
 
 
+
 }

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/ElementData.java

@@ -73,6 +73,10 @@ public class ElementData implements Serializable {
     public ElementData() {
     }
 
+    public ElementData(Object value) {
+        this.value = value;
+    }
+
     public ElementData(Integer index, Integer groupId, Object value) {
         this.index = index;
         this.groupId = groupId;

+ 0 - 3
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/FormulaClient.java

@@ -1,6 +1,5 @@
 package org.springblade.manager.feign;
 
-import org.springblade.manager.dto.FormData;
 import org.springblade.manager.entity.FormulaOption;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -9,7 +8,6 @@ import org.springframework.web.bind.annotation.RequestParam;
 
 import javax.validation.constraints.NotNull;
 import java.io.FileNotFoundException;
-import java.util.List;
 
 import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
 
@@ -32,5 +30,4 @@ public interface FormulaClient {
     @GetMapping(API_PREFIX + "option")
     FormulaOption option(@RequestParam @NotNull Long pkeyId);
 
-
 }

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

@@ -82,7 +82,7 @@ public abstract class EvaSummary<T> {
                 Coords c = fd.getCoordsList().get(i);
                 list.add(new ElementData(pn, 0, data.get(i), c.getX(), c.getY()));
             }
-            fd.getValues().addAll(list);
+            fd.setValues(list);
             return recovery(list);
         }
         return StringPool.EMPTY;

+ 33 - 3
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/FB02.java

@@ -3,15 +3,19 @@ package org.springblade.manager.vo;
 import com.alibaba.fastjson.JSON;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.dto.FormData;
 import org.springblade.manager.entity.FormulaDataBlock;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+import static java.util.regex.Pattern.compile;
+
 /**
  * @author yangyj
  * @Date 2023/11/1 17:24
@@ -25,10 +29,12 @@ public class FB02 extends EvaSummary<Item02>{
     private FormData name;
     private FormData passRate;
     private FormData weight;
+    /**加权平均分*/
+    private FormData wAvg;
   @Override
     public Integer getPageNum(){
         if(this.name!=null){
-          return  (this.getDatas().size()/this.name.getCoordsList().size())+1;
+          return  (int)Math.ceil(this.getDatas().size()/(double)this.name.getCoordsList().size());
         }
         return null;
     }
@@ -51,14 +57,22 @@ public class FB02 extends EvaSummary<Item02>{
               }else if(fd.getEName().trim().equals("权值")){
                   this.weight=fd;
                   this.fm.put(fd.getCode(),(List<Item02> l,Integer pn)->l.stream().map(Item02::getWeight).collect(Collectors.toList()));
+              }else if(fd.getEName().trim().contains("得分")&&fd.getEName().trim().contains("权值")){
+                  this.wAvg=fd;
+                  this.fm.put(fd.getCode(),(List<Item02> l,Integer pn)-> Collections.singletonList(l.stream()
+                          .mapToDouble(item -> item.getPassRate() * item.getWeight())
+                          .sum() / l.stream()
+                          .mapToInt(Item02::getWeight)
+                          .sum()));
               }
-              if(this.subItem!=null&&this.name!=null&&this.passRate!=null&&this.weight!=null&&this.sn!=null){
+              if(this.subItem!=null&&this.name!=null&&this.passRate!=null&&this.weight!=null&&this.sn!=null&&this.wAvg!=null){
                   /*匹配完成*/
                   this.fds.add(this.subItem);
                   this.fds.add(this.sn);
                   this.fds.add(this.name);
                   this.fds.add(this.passRate);
                   this.fds.add(this.weight);
+                  this.fds.add(this.wAvg);
                   break;
               }
          }
@@ -70,7 +84,7 @@ public class FB02 extends EvaSummary<Item02>{
             elementBlockList.forEach(eb -> {
                 String name = eb.getEName();
                 Item02 xm = new Item02();
-                xm.setName(name);
+                xm.setName(checkItemName(name));
                 xm.setSubItem(swNameMap.get(fdb.getSwId().toString()));
                 List<ItemBlock> ib = eb.getList();
                 int total = ib.stream().mapToInt(ItemBlock::getSubTotal).sum();
@@ -88,5 +102,21 @@ public class FB02 extends EvaSummary<Item02>{
         });
     }
 
+    public static  String checkItemName(String eName){
+        if (Func.isEmpty(eName)) {
+            return eName;
+        }
+        /*分割字符串,选取第一个匹配的子串*/
+        String str = eName.replaceAll("\\s", "");
+        Pattern pattern = compile("[((][^\\u4e00-\\u9fa5]+[))]|_+");
+        String[] candidate = pattern.split(str);
+        String regex = "[^\\u4e00-\\u9fa5]+";
+        return Arrays.stream(candidate).map(s->s.replaceAll(regex,"")).distinct().filter(Func::isNotEmpty).filter(s->!isContainKeywords2(s)).findFirst().orElse("");
+    }
+
+    private static boolean isContainKeywords2(String s) {
+        List<String> keywords = Arrays.asList( "实测项目");
+        return keywords.stream().anyMatch(s::contains);
+    }
 
 }

+ 40 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InterimPaymentCertificate.java

@@ -0,0 +1,40 @@
+package org.springblade.manager.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * @author yangyj
+ * @Date 2024/1/8 15:46
+ * @description 中期支付证书
+ */
+@Data
+public class InterimPaymentCertificate {
+    public static final String ID="20210000000";
+    public static final String TBN="IPayCert";
+    public static final String TBN_CH="中期支付证书";
+    /**项目名称*/
+    @JSONField(name = "key_1",label="项目名称",ordinal = 1)
+    private String itemName;
+    /**合同金额*/
+    @JSONField(name = "key_2",label="合同金额",ordinal = 2)
+    private String contractAmount;
+    /**变更后的金额*/
+    @JSONField(name = "key_3",label="变更后的金额",ordinal = 3)
+    private String revisedAmount;
+    /**本期末支付金额*/
+    @JSONField(name = "key_4",label="本期末支付金额",ordinal = 4)
+    private String currentPeriodEndPay;
+    /**上期末支付金额*/
+    @JSONField(name = "key_5",label="上期末支付金额",ordinal = 5)
+    private String previousPeriodEndPay;
+    /**本期支付金额*/
+    @JSONField(name = "key_6",label="本期支付金额",ordinal = 6)
+    private String currentPeriodPay;
+    /**支付比例*/
+    @JSONField(name = "key_7",label="支付比例",ordinal = 7)
+    private String payRatio;
+    /**备注*/
+    @JSONField(name = "key_8",label="备注",ordinal = 8)
+    private String remark;
+}

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

@@ -0,0 +1,30 @@
+package org.springblade.manager.vo;
+
+public enum MeterType {
+    /**中间计量*/
+    INTERIM(0,"计量报表"),
+    /**材料预付款*/
+    MATERIAL(1,"材料预付款报表"),
+    /**开工预付款*/
+    START(2,"动员预付款报表");
+    private final int index;
+    private final String name;
+    MeterType(int index, String name) {
+        this.index = index;
+        this.name = name;
+    }
+    public int getIndex() {
+        return index;
+    }
+    public String getName() {
+        return name;
+    }
+    public static MeterType getByIndex(int index) {
+        MeterType[] values = MeterType.values();
+        if (index >= 0 && index < values.length) {
+            return values[index];
+        } else {
+           return values[0];
+        }
+    }
+}

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

@@ -338,11 +338,12 @@ public class FormulaUtils {
         }
     }
 
+    public static final String TBN_FN="TBN";
 /*把模型类转换成共识配置选项*/
     public static List<WbsFormElementVO> toElementVos(Class<?> clazz)  {
         List<WbsFormElementVO> vos =new ArrayList<>();
         try {
-            Field tbnField = clazz.getField("TBN");
+            Field tbnField = clazz.getField(TBN_FN);
             String TBN = (String) tbnField.get(null);
             for (Field field : clazz.getDeclaredFields()) {
                 JSONField jf = field.getAnnotation(JSONField.class);
@@ -361,14 +362,14 @@ public class FormulaUtils {
         return vos;
     }
 
-    public static <T> Map<String,FormData> toFormDataMap(T bean){
-        Map<String,FormData> result = new HashMap<>();
+    public static <T> LinkedHashMap<String,FormData> toFormDataMap(T bean){
+        LinkedHashMap<String,FormData> result = new LinkedHashMap<>();
         if(bean!=null){
             try {
                 @SuppressWarnings("unchecked")
                 Map<String,String> map= JSON.parseObject(JSON.toJSONString(bean),Map.class);
                 Class<?> clazz=bean.getClass();
-                String TBN = (String)  clazz.getField("TBN").get(null);
+                String TBN = (String)  clazz.getField(TBN_FN).get(null);
                 for (Field field : clazz.getDeclaredFields()) {
                     JSONField jf = field.getAnnotation(JSONField.class);
                     if (jf != null) {
@@ -389,6 +390,34 @@ public class FormulaUtils {
     }
 
 
+    /*数据模型按字段生成内容获取函数*/
+    public static <T> Map<String,Function<T,Object>> functionMapBuilder(Class<T> clazz){
+        Map<String, Function<T, Object>> functionMap = new HashMap<>();
+        for (Field field : clazz.getDeclaredFields()) {
+            JSONField jf = field.getAnnotation(JSONField.class);
+            if(jf!=null) {
+                String key = TBN_FN+ StringPool.COLON +jf.name();
+                String fieldName = field.getName();
+                Function<T, Object> function = getFunction(clazz, fieldName);
+                functionMap.put(key, function);
+            }
+        }
+        return functionMap;
+    }
+
+    private static <T> Function<T, Object> getFunction(Class<T> clazz, String fieldName) {
+        return certificate -> {
+            try {
+                Field field = clazz.getDeclaredField(fieldName);
+                field.setAccessible(true);
+                return field.get(certificate);
+            } catch (Exception e) {
+                e.printStackTrace();
+                return null;
+            }
+        };
+    }
+
     /**从元素名称中解析项目名称,细化项目匹配用*/
     public static  String parseItemName(String eName){
         if (StringUtils.isEmpty(eName)) {

+ 24 - 7
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorInit.java

@@ -5,7 +5,10 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.springblade.manager.formula.FormulaExecutor;
 import org.springblade.manager.vo.BaseInfo;
+import org.springblade.manager.vo.InterimPaymentCertificate;
 import org.springblade.manager.vo.MeterPeriodInfo;
+import org.springblade.manager.vo.MeterType;
+
 import java.util.function.Function;
 
 /**
@@ -19,20 +22,34 @@ public class ExecutorInit extends FormulaExecutor {
     public ExecutorInit(TableElementConverter tec) {
         super(tec);
     }
-    private  Function<Long, BaseInfo> baseInfoFc;
-    private  Function<Long, MeterPeriodInfo>  meterPeriodFc;
+    private  Function<Long, BaseInfo> getBaseInfo;
+    private  Function<Long, MeterPeriodInfo>  getMeterPeriod;
 
 
     public void handle() {
+
         /*加载合同数据*/
-        BaseInfo baseInfo = this.baseInfoFc.apply(tec.getContractId());
+        BaseInfo baseInfo = this.getBaseInfo.apply(tec.getContractId());
         tec.getConstantMap().put(BaseInfo.TBN,baseInfo);
         tec.formDataMap.putAll(FormulaUtils.toFormDataMap(baseInfo));
-        /*加载计量期信息*/
-        MeterPeriodInfo meterPeriod=meterPeriodFc.apply(tec.getPeriodId());
-        tec.formDataMap.putAll(FormulaUtils.toFormDataMap(meterPeriod));
-        tec.getConstantMap().put(MeterPeriodInfo.TBN,meterPeriod);
+        if(MeterType.MATERIAL.equals(tec.getMeterType())||MeterType.START.equals(tec.getMeterType())){
+            /*加载计量期信息*/
+            MeterPeriodInfo meterPeriod=getMeterPeriod.apply(tec.getPeriodId());
+            tec.formDataMap.putAll(FormulaUtils.toFormDataMap(meterPeriod));
+            tec.getConstantMap().put(MeterPeriodInfo.TBN,meterPeriod);
+        }else if(MeterType.INTERIM.equals(tec.getMeterType())){
+            /*中间支付证书*/
+            tec.formDataMap.putAll(FormulaUtils.toFormDataMap(new InterimPaymentCertificate()));
+            /*中间支付汇总*/
+            /*分项工程中期支付汇总*/
+            /*分项工程中期计量支付*/
+            /*中间计量支付汇总*/
+            /*中间计量*/
+        }
+
     }
 
 
+
+
 }

+ 51 - 10
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorSpecial.java

@@ -1,21 +1,25 @@
 package org.springblade.manager.formula.impl;
 
+import com.alibaba.fastjson.annotation.JSONField;
 import com.mixsmart.utils.FormulaUtils;
 import com.mixsmart.utils.StringUtils;
+import io.swagger.models.auth.In;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.ReflectUtil;
+import org.springblade.core.tool.utils.StringPool;
 import org.springblade.manager.dto.ElementData;
 import org.springblade.manager.dto.FormData;
 import org.springblade.manager.formula.FormulaExecutor;
 import org.springblade.manager.formula.NodeTable;
 import org.springblade.manager.vo.BaseInfo;
+import org.springblade.manager.vo.InterimPaymentCertificate;
 import org.springblade.manager.vo.Material;
+import org.springblade.manager.vo.MeterType;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.lang.reflect.Field;
+import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
@@ -36,11 +40,10 @@ public class ExecutorSpecial extends FormulaExecutor {
 
     @Override
     public void handle() {
-        for(NodeTable nodeTable:tec.getTableAll()){
-            if(Material.TBN_CH.equals(nodeTable.getNodeName())){
-                MaterialCalc materialCalc = new MaterialCalc(tec.getFormDataList());
-                this.specialList.add(materialCalc);
-            }
+        if(MeterType.MATERIAL.equals(tec.getMeterType())){
+            this.specialList.add(new MaterialCalc());
+        }else if(MeterType.INTERIM.equals(tec.getMeterType())){
+            this.specialList.add(new InterimPayCert());
         }
         this.specialList.stream().filter(Special::ready).forEach(Special::parse);
     }
@@ -65,7 +68,8 @@ public class ExecutorSpecial extends FormulaExecutor {
         /**预付款合计*/
         private String totalAdvance;
         private List<FormData> fds=new ArrayList<>();
-        public MaterialCalc(List<FormData> list) {
+        public MaterialCalc() {
+            List<FormData> list =tec.getFormDataList();
            Optional<FormData> fop=  list.stream().filter(e->e.executable()&&"MATERIAL".equals(e.getFormula().getNumber())).findAny();
            List<FormData> candidate = new ArrayList<>();
            if(fop.isPresent()){
@@ -184,8 +188,45 @@ public class ExecutorSpecial extends FormulaExecutor {
         }
     }
 
+    @Data
+    public  class InterimPayCert implements Special{
+
+        @Override
+        public boolean ready() {
+            return true;
+        }
+
+
+        @Override
+        public void parse() {
+            LinkedHashMap<String,FormData> fdm = FormulaUtils.toFormDataMap(new InterimPaymentCertificate());
+            Map<String,Function<InterimPaymentCertificate,Object>> functionMap = FormulaUtils.functionMapBuilder(InterimPaymentCertificate.class);
+            tec.getFormDataMap().putAll(fdm);
+            List<InterimPaymentCertificate> dataList = new ArrayList<>();
+            /*数据获取start*/
+            dataList.add(new InterimPaymentCertificate()) ;//测试,按照业务写,实际会复杂许多
+            //TODO
+            /*数据获取end*/
+            fdm.values().forEach(fd->{
+                List<Object> raw = dataList.stream().map(functionMap.get(fd.getCode())).filter(Func::isNotEmpty).collect(Collectors.toList());
+                if(raw.size()>0){
+                    List<ElementData> eds = fd.getValues();
+                    for(Object value:raw){
+                        eds.add(new ElementData(value));
+                    }
+                }
+            });
+
+        }
+    }
+
+
+
+
     public interface  Special{
+        /**是否满足执行条件*/
         boolean ready();
+        /**解析数据*/
         void parse();
     }
 }

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

@@ -24,6 +24,7 @@ import org.springblade.manager.formula.ITableElementConverter;
 import org.springblade.manager.formula.KeyMapper;
 import org.springblade.manager.formula.NodeTable;
 import org.springblade.manager.vo.CurrentNode;
+import org.springblade.manager.vo.MeterType;
 import org.springblade.manager.vo.ReportResult;
 import org.springframework.jdbc.core.JdbcTemplate;
 
@@ -105,11 +106,13 @@ public class TableElementConverter implements ITableElementConverter {
     public  boolean isNew=false;
     /**是否强制执行,刷数据的时候会用到*/
     public boolean  force=false;
-
+    /**输入输出转换,在创建TableElementConverter必须明确实例*/
     private final Converter in;
     private final Converter out;
     /*计量属性*/
     private Long periodId;
+    /**计量类型*/
+    private MeterType meterType;
     /*存放计量计算结果*/
     public List<ReportResult> reportResults ;
     /*计量属性*/

+ 15 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -2529,32 +2529,43 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     }
 
 
-    String[] tabArr=new String[]{"计量报表","动员预付款报表","材料预付款报表"};
     @Override
     public  List<ReportResult> execute3(Long contractId,Long periodId ,Integer type) {
         ContractInfo contractInfo = this.contractInfoService.getById(contractId);
-        Map<String,String> parent=  this.getSqlOne("select id,wbs_id wbsId,CONCAT(ancestors,',',id) path from  m_wbs_tree_private a  where a.node_name=? and a.project_id=?",Map.class,tabArr[type],contractInfo.getPId());
+        MeterType meterType = MeterType.getByIndex(type);
+
+        /*元素创建*/
+        Map<String,String> parent=  this.getSqlOne("select id,wbs_id wbsId,CONCAT(ancestors,',',id) path from  m_wbs_tree_private a  where a.node_name=? and a.project_id=?",Map.class,meterType.name(),contractInfo.getPId());
         List<NodeTable> tableList=  this.getSqlList("select p_key_id pkeyId, node_name nodeName ,init_table_name initTableName,html_url htmlUrl  from  m_wbs_tree_private where ancestors like ? and LENGTH(html_url)>0 and is_deleted=0 and project_id=? and wbs_id=?",NodeTable.class,parent.get("path")+"%",contractInfo.getPId(),parent.get("wbsId"));
         Map<String,Map<String,String>> coordinateMap=tableList.stream().collect(Collectors.toMap(NodeTable::getInitTableName,m->FormulaUtils.getElementCell(m.getHtmlUrl()),(v1,v2)->v2));
         List<FormData> processFds = this.createFormDataByTableName(tableList.stream().map(NodeTable::getInitTableName).collect(Collectors.joining("','")));
         listForMeter(processFds,contractInfo.getPId(),parent.get("id"));
+
+        /*转换器声明*/
         TableElementConverter tec = new TableElementConverter(processFds,coordinateMap,tableList);
         tec.setProjectId(Long.parseLong(contractInfo.getPId()));
         tec.setContractId(contractInfo.getId());
         tec.setPeriodId(periodId);
         tec.setLog(new FormulaLog());
+        tec.setMeterType(meterType);
         tec.before();
+
+        /*执行链*/
         List<FormulaHandleChain> formulaHandleChains = new ArrayList<>();
+        /*初始化*/
         ExecutorInit init= new ExecutorInit(tec);
-        init.setBaseInfoFc(this.formulaDao.getBaseInfo());
-        init.setMeterPeriodFc(this.formulaDao.getMeterPeriod());
+        init.setGetBaseInfo(this.formulaDao.getBaseInfo());
+        init.setGetMeterPeriod(this.formulaDao.getMeterPeriod());
         formulaHandleChains.add(init);
         formulaHandleChains.add(new ExecutorSort(tec));
         formulaHandleChains.add(new ExecutorPre(tec));
+        /*特殊公式*/
         ExecutorSpecial special = new ExecutorSpecial(tec);
         special.setMaterialListFc(this.formulaDao.getMaterialForm());
         formulaHandleChains.add(special);
+        /*通用计算*/
         formulaHandleChains.add(new ExecutorCalc(tec));
+        /*格式化*/
         formulaHandleChains.add(new ExecutorFormat(tec));
         formulaHandleChains.forEach(FormulaHandleChain::handle);
         tec.after();