Browse Source

合同计量单元导入模板3

qianxb 11 months ago
parent
commit
9ca0e47305

+ 40 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/vo/InventoryFormMeterVO2.java

@@ -0,0 +1,40 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.meter.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.meter.entity.InventoryFormMeter;
+
+import java.math.BigDecimal;
+
+/**
+ * 合同计量单元导入模板3专用,中间表携带是否被计量标识
+ *
+ * @author BladeX
+ * @since 2023-11-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class InventoryFormMeterVO2 extends InventoryFormMeter {
+	private static final long serialVersionUID = 1L;
+
+	@ApiModelProperty(value = "是否被计量0是1否")
+	private Integer isMeter;
+
+}

+ 69 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/vo/MeterImport3VO.java

@@ -0,0 +1,69 @@
+package org.springblade.meter.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.core.tool.node.INode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Param   合同计量单元导入模板3专用,携带标识当前是新增节点还是原生节点
+ * @Author wangwl
+ * @Date 2023/12/26 15:38
+ **/
+@Data
+public class MeterImport3VO implements INode<MeterImport3VO> {
+    /**
+     * 主键ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long id;
+
+    /**
+     * 父节点ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long parentId;
+
+    /**
+     * 子孙节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private List<MeterImport3VO> children;
+
+    /**
+     * 是否有子孙节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private Boolean hasChildren;
+
+    @Override
+    public List<MeterImport3VO> getChildren() {
+        if (this.children == null) {
+            this.children = new ArrayList<>();
+        }
+        return this.children;
+    }
+
+    @ApiModelProperty(value = "0原生1新增")
+    private Integer isNew;
+
+    private String nodeName;
+
+    private Integer nodeType;
+    private String remarks;
+    private String contractPicture;
+
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "合同段id")
+    private Long contractId;
+
+    @ApiModelProperty(value = "祖级id")
+    private String ancestor;
+}

+ 45 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/vo/MeterImport3VO2.java

@@ -0,0 +1,45 @@
+package org.springblade.meter.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.core.tool.node.INode;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @Param   合同计量单元导入模板3专用,通过计量id和清单id确定是否存在数据
+ * @Author wangwl
+ * @Date 2023/12/26 15:38
+ **/
+@Data
+public class MeterImport3VO2  {
+
+    private Long meterId;
+    private Long formId;
+
+    public MeterImport3VO2() {
+    }
+
+    public MeterImport3VO2(Long meterId, Long formId) {
+        this.meterId = meterId;
+        this.formId = formId;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MeterImport3VO2 that = (MeterImport3VO2) o;
+        return Objects.equals(meterId, that.meterId) && Objects.equals(formId, that.formId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(meterId, formId);
+    }
+}

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

@@ -871,9 +871,11 @@ public class MeterTreeController extends BladeController {
     public R<String> contractTreeNodeImport(@RequestParam String id,Integer type, MultipartFile file) {
         if (ObjectUtil.isNotEmpty(id) && type != null) {
             if (type == 1){
-               return meterTreeContractService.contractTreeNodeImport1(id, file);
+                return meterTreeContractService.contractTreeNodeImport1(id, file);
             }else if (type == 2) {
-               return meterTreeContractService.contractTreeNodeImport2(id, file);
+                return meterTreeContractService.contractTreeNodeImport2(id, file);
+            }else if (type == 3){
+                return meterTreeContractService.contractTreeNodeImport3(id, file);
             }
         }
         return R.fail("操作失败");

+ 11 - 4
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/MeterTreeContractMapper.java

@@ -5,11 +5,11 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.springblade.meter.dto.MeterTreeContractDTO;
 import org.springblade.meter.entity.*;
-import org.springblade.meter.vo.MeterFullTreeVO;
-import org.springblade.meter.vo.MeterTreeLinkWbsTreeVO;
-import org.springblade.meter.vo.NodePartVO;
+import org.springblade.meter.vo.*;
 
+import java.io.Serializable;
 import java.math.BigDecimal;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -21,9 +21,12 @@ public interface MeterTreeContractMapper extends BaseMapper<MeterTreeContract> {
 
     MeterTreeContract getAllChildNodeMoney(@Param("contractId") Long contractId,@Param("id") Long id);
 
+    //批量修改带施工图
     void batchUpdateById(@Param("list") List<MeterTreeContract> list);
+    //批量修改不带施工图
+    void batchUpdateById2(@Param("list") List<MeterTreeContract> list);
 
-    List<InventoryFormMeter> getNodeAllForm(@Param("ids") Set<Long> ids);
+    List<InventoryFormMeter> getNodeAllForm(@Param("ids") Collection<? extends Serializable> ids);
 
     List<String> getAllEqualsNumber(@Param("contractId") Long contractId,@Param("numbers") List<String> collect);
 
@@ -44,4 +47,8 @@ public interface MeterTreeContractMapper extends BaseMapper<MeterTreeContract> {
     List<NodePartVO> getAllWbsNode(@Param("projectId") Long projectId,@Param("contractId") Long contractId);
 
     List<MiddleMeterApply> getMiddleMeter(@Param("contractId") Long contractId, @Param("ids") List<Long> meterIds);
+
+    List<MeterImport3VO> getALLNodeByContractId(@Param("contractId") Long contractId);
+
+    List<InventoryFormMeterVO2> getAllFormMeter(@Param("contractId") Long contractId);
 }

+ 22 - 1
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/MeterTreeContractMapper.xml

@@ -11,6 +11,16 @@
             where id = #{item.id}
         </foreach>
     </update>
+    <update id="batchUpdateById2">
+        <foreach item="item" collection="list" separator=";">
+            UPDATE s_meter_tree_contract
+            <set>
+                build_picture_money = #{item.buildPictureMoney},
+                change_money = #{item.changeMoney}
+            </set>
+            where id = #{item.id}
+        </foreach>
+    </update>
     <update id="batchUpdateFormByNumber">
         <foreach item="value" collection="map" index="key" separator=";">
             UPDATE s_contract_inventory_form
@@ -32,7 +42,7 @@
         where contract_id = #{contractId} and is_deleted = 0 and  FIND_IN_SET(#{id}, ancestor)
     </select>
     <select id="getNodeAllForm" resultType="org.springblade.meter.entity.InventoryFormMeter">
-        select contract_meter_id,change_build_picture_money
+        select contract_meter_id,build_picture_money,change_build_picture_money
         from s_inventory_form_meter where is_deleted = 0 and contract_meter_id in
         <foreach collection="ids" item="id" open="(" close=")" separator=",">
             #{id}
@@ -90,6 +100,17 @@
             #{id}
         </foreach>
     </select>
+    <select id="getALLNodeByContractId" resultType="org.springblade.meter.vo.MeterImport3VO">
+        select id ,parent_id,node_name,node_type,ancestor,0 as isNew
+        from s_meter_tree_contract where contract_id = #{contractId} and is_deleted = 0
+    </select>
+    <select id="getAllFormMeter" resultType="org.springblade.meter.vo.InventoryFormMeterVO2">
+        select *,
+               if((select count(1) from s_inventory_form_apply ifa where ifa.contract_id = #{contractId} and ifa.is_deleted = 0
+                    and ifa.contract_meter_id = ifm.contract_meter_id and ifa.contract_form_id = ifm.contract_form_id) = 0,0,1) as isMeter
+        from s_inventory_form_meter ifm
+        where contract_id = #{contractId} and is_deleted = 0
+    </select>
 
 
 </mapper>

+ 6 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/MeterTreeContractService.java

@@ -12,6 +12,8 @@ import org.springblade.meter.vo.MeterTreeContractVO;
 import org.springblade.meter.vo.MeterTreeAndWbsTreeVO;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.Serializable;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -29,6 +31,8 @@ public interface MeterTreeContractService extends BaseService<MeterTreeContract>
 
     //异步重新计算节点金额,和修改施工图号
     void asyncCalculateNodeMoney(List<ChangeNodeVO> vos);
+    //通过合同计量单元id,重新计算节点金额
+    void asyncCalculateNodeMoney2(Collection<? extends Serializable> ids);
 
     boolean contractTreeNodeImport(String id, MultipartFile file);
 
@@ -36,6 +40,8 @@ public interface MeterTreeContractService extends BaseService<MeterTreeContract>
     R<String> contractTreeNodeImport2(String id, MultipartFile file);
     //只导入一层
     R<String> contractTreeNodeImport1(String id, MultipartFile file);
+    //按层级导入
+    R<String> contractTreeNodeImport3(String id, MultipartFile file);
 
     boolean contractUpdate(MeterTreeContractDTO dto);
 

+ 346 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/MeterTreeContractServiceImpl.java

@@ -39,6 +39,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.function.Function;
@@ -583,6 +584,36 @@ public class MeterTreeContractServiceImpl extends BaseServiceImpl<MeterTreeContr
         baseMapper.batchUpdateById(list);
     }
 
+    /**
+     * 统计节点的的施工图金额,变更后金额,根据节点id
+     * @param ids
+     */
+    @Override
+    public void asyncCalculateNodeMoney2(Collection<? extends Serializable> ids) {
+        //获取所有要重新计算的节点的最新数据
+        List<MeterTreeContract> list = this.listByIds(ids);
+        //获取节点下所有分解的表单
+        List<InventoryFormMeter> formMeters = baseMapper.getNodeAllForm(ids);
+        //聚合施工图金额,按照合同计量单元分组
+        Map<Long, BigDecimal> decimalMap = formMeters.stream()
+                .collect(Collectors.groupingBy(l -> l.getContractMeterId(),
+                        Collectors.mapping(InventoryFormMeter::getBuildPictureMoney,
+                                Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
+        //聚合变更后施工图金额,按照合同计量单元分组
+        Map<Long, BigDecimal> decimalMap2 = formMeters.stream()
+                .collect(Collectors.groupingBy(l -> l.getContractMeterId(),
+                        Collectors.mapping(InventoryFormMeter::getChangeBuildPictureMoney,
+                                Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
+        list.stream().forEach(l -> {
+            //为节点设置施工图金额
+            l.setBuildPictureMoney(decimalMap.get(l.getId()) == null ? BigDecimal.ZERO : decimalMap.get(l.getId()));
+            //为节点设置变更后施工图金额
+            l.setChangeMoney(decimalMap2.get(l.getId()) == null ? BigDecimal.ZERO : decimalMap2.get(l.getId()));
+        });
+        //拼接SQL修改合同图号和重新计算的金额
+        baseMapper.batchUpdateById2(list);
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean contractTreeNodeImport(String id, MultipartFile file) {
@@ -1786,6 +1817,321 @@ public class MeterTreeContractServiceImpl extends BaseServiceImpl<MeterTreeContr
         return R.success("成功导入:节点("+addNode+")个,"+"新增清单("+addForm+")条,"+"修改清单("+updateForm+")条.");
     }
 
+    @Override
+    @Transactional
+    public R<String> contractTreeNodeImport3(String id, MultipartFile file) {
+        try {
+            //获取当前节点
+            MeterTreeContract meterTreeContract = baseMapper.selectById(id);
+            if (meterTreeContract == null){
+                throw new ServiceException("未找到当前导入节点信息");
+            }
+            Long projectId = meterTreeContract.getProjectId();
+            Long contractId = meterTreeContract.getContractId();
+            /*解析excel*/
+            List<Map<String, String>> parseExcelFileToList;
+            try {
+                parseExcelFileToList = this.parseExcelFile(file);
+            } catch (Exception e) {
+                throw new ServiceException("请检查格式:" + e.getMessage());
+            }
+            if (parseExcelFileToList.size() == 0) {
+                throw new ServiceException("excel中未发现数据,请检查后再导入");
+            }
+            //过滤掉单位工程为空的
+            parseExcelFileToList = parseExcelFileToList.stream()
+                    .filter(l -> StringUtils.isNotBlank(l.get("单位工程"))).collect(Collectors.toList());
+            if (parseExcelFileToList.size() == 0) {
+                throw new ServiceException("excel中未发现单位工程数据,请检查后再导入");
+            }
+            //获取合同段所有的清单
+            List<ContractInventoryForm> formList = contractInventoryFormMapper.selectList(new LambdaQueryWrapper<ContractInventoryForm>()
+                    .eq(ContractInventoryForm::getContractId, meterTreeContract.getContractId())
+                    .eq(ContractInventoryForm::getIsFormNode, 1));
+            if (formList.size() == 0){
+                throw new ServiceException("导入失败,当前合同段没有合同工程清单");
+            }
+            //清单转换为编号集合,用于校验是否存在
+            List<String> numberList = formList.stream().map(l -> l.getFormNumber()).collect(Collectors.toList());
+            //清单按照编号转换为map,用于设置中间表信息
+            Map<String, ContractInventoryForm> inventoryFormMap = formList.stream().collect(Collectors.toMap(l -> l.getFormNumber(), l -> l));
+            //校验数据,开始桩号和结束桩号必须同时存在,清单编号必须存在数据,有清单编号必须填写分解量
+            parseExcelFileToList.stream().forEach(l->{
+                if ((StringUtils.isBlank(l.get("开始桩号")) && StringUtils.isNotBlank(l.get("结束桩号")))
+                        || (StringUtils.isNotBlank("开始桩号") && StringUtils.isBlank(l.get("结束桩号")))){
+                    throw new ServiceException("开始桩号和结束桩号必须同时存在,请修改后重新导入");
+                }
+                if (StringUtils.isNotBlank(l.get("清单编号"))){
+                    if (numberList.indexOf(l.get("清单编号")) == -1){
+                        throw new ServiceException("合同段中不存在清单编号:"+l.get("清单编号")+"请检查后重新导入");
+                    }
+                    if (StringUtils.isBlank(l.get("分解核实量"))){
+                        throw new ServiceException("清单编号:"+l.get("清单编号")+",没有填写分解核实量");
+                    }
+                }
+            });
+            //获取清单与计量单元中间表的所有数据,并且携带是否被计量的信息
+            List<InventoryFormMeterVO2> formMeters = baseMapper.getAllFormMeter(meterTreeContract.getContractId());
+            Boolean isLink = false; // 是否存在中间表数据
+            Map<MeterImport3VO2, InventoryFormMeterVO2> meterMap = new HashMap<>();
+            //按照计量单元id分组,用于判断是否存在
+            if (formMeters.size() > 0){
+                isLink = true;
+                try {
+                    meterMap = formMeters.stream().collect(Collectors.toMap(l -> new MeterImport3VO2(l.getContractMeterId(), l.getContractFormId()), l -> l));
+                }catch (Exception e){
+                    throw new ServiceException("清单与计量单元中间表中存在错误重复数据,请联系管理员");
+                }
+            }
+            /*节点新增*/
+            List<MeterImport3VO> resultNodeAdd = new LinkedList<>();
+            List<MeterTreeContract> resultNodeListAdd = new LinkedList<>();
+            /*节点修改*/
+            List<MeterTreeContract> resultNodeListUpdate = new ArrayList<>();
+            /*节点金额修改Ids*/
+            Set<Long> updateNodeSet = new HashSet<>();
+            /*清单中间新增*/
+            List<InventoryFormMeter> resultFormListAdd = new LinkedList<>();
+            /*清单中间数量修改*/
+            List<InventoryFormMeter> resultFormListUpdate = new LinkedList<>();
+            /*合同清单变更后数量修改*/
+            List<ContractInventoryForm> InventoryFormListUpdate = new LinkedList<>();
+
+            //获取出所有的合同计量单元节点,并转化为树,用VO标识字段是新增节点,还是原生节点
+            List<MeterImport3VO> vos = baseMapper.getALLNodeByContractId(meterTreeContract.getContractId());
+            List<MeterImport3VO> list = ForestNodeMerger.merge(vos);
+            if (list.size() != 1){
+                throw new ServiceException("当前合同计量单元结构错误,请联系管理员");
+            }
+
+            //层级数组
+            String[] nodeType = {"单位工程","子单位工程","分部工程","子分部工程","分项工程","子分项工程"};
+            //循环Excel每一行
+            for (Map<String, String> map : parseExcelFileToList) {
+                //上一个节点(必定存在)
+                MeterImport3VO lastNode = list.get(0);
+                //当前层节点(不存在就新增绑定到上一个节点的children下)
+                List<MeterImport3VO> thisNode = lastNode.getChildren();
+                Map<String, MeterImport3VO> thisMap = new HashMap<>();
+                if (thisNode != null && thisNode.size() > 0) {
+                    //当前层节点map,key为节点名称(同一层,不能有节点名称相同)
+                    thisMap = thisNode.stream().collect(Collectors.toMap(l -> l.getNodeName(), l -> l));
+                }
+                //标识上一层节点是否为新增,默认为否
+                Boolean isNew = false;
+                //循环处理节点
+                for (int i = 0; i <= 6; i++) {
+                    int j = i==0?1:i;
+                    //处理前面6个节点,如果等于6则处理工序节点
+                    String nodeName = null;
+                    if (i != 6) {
+                        nodeName = map.get(nodeType[i]);
+                    }else {
+                        if (StringUtils.isNotBlank(map.get("开始桩号")) && StringUtils.isNotBlank(map.get("结束桩号"))){
+                            nodeName = map.get("开始桩号") + "~" +map.get("结束桩号");
+                        }
+                    }
+                    //Excel存在节点名称则执行,不存在则跳过
+                    if (StringUtils.isNotBlank(nodeName)){
+                        //上一层节点为新增 或者 当前层不存在数据,都去创建当前层数据
+                        if (isNew || (thisNode == null || thisNode.size() == 0)){
+                            //创建当前层数据,添加到上一层的children下,并且修改isNew为true
+                            isNew = true;
+                            List<MeterImport3VO> childList = new ArrayList<>();
+                            MeterImport3VO vo1 = new MeterImport3VO();
+                            vo1.setId(SnowFlakeUtil.getId());
+                            vo1.setParentId(lastNode.getId());
+                            vo1.setProjectId(projectId);
+                            vo1.setContractId(contractId);
+                            vo1.setAncestor(lastNode.getAncestor()+","+lastNode.getId());
+                            vo1.setNodeName(nodeName);
+                            vo1.setIsNew(1);
+                            vo1.setNodeType(j);
+                            if (i == 6 && (StringUtils.isNotBlank(map.get("图册")) || StringUtils.isNotBlank(map.get("图号")))){
+                                vo1.setRemarks(map.get("图册"));
+                                vo1.setContractPicture(map.get("图号"));
+                            }
+                            childList.add(vo1);
+                            //则新增到上一层的children下
+                            lastNode.setChildren(childList);
+                            //设置上一层为当前层
+                            lastNode = vo1;
+                            //添加到新增节点中
+                            resultNodeAdd.add(vo1);
+                        }else {
+                            //当前层存在数据,则是否存在集合中
+                            MeterImport3VO vo2 = thisMap.get(nodeName);
+                            if (vo2 == null) {
+                                //不存在集合中,则新增,然后添加进当前集合
+                                isNew = true;
+                                MeterImport3VO vo1 = new MeterImport3VO();
+                                vo1.setId(SnowFlakeUtil.getId());
+                                vo1.setParentId(lastNode.getId());
+                                vo1.setProjectId(projectId);
+                                vo1.setContractId(contractId);
+                                vo1.setAncestor(lastNode.getAncestor()+","+lastNode.getId());
+                                vo1.setNodeName(nodeName);
+                                vo1.setIsNew(1);
+                                vo1.setNodeType(j);
+                                if (i == 6 && (StringUtils.isNotBlank(map.get("图册")) || StringUtils.isNotBlank(map.get("图号")))){
+                                    vo1.setRemarks(map.get("图册"));
+                                    vo1.setContractPicture(map.get("图号"));
+                                }
+                                thisNode.add(vo1);
+                                //设置上一层为当前层
+                                lastNode = vo1;
+                                //添加到新增节点中
+                                resultNodeAdd.add(vo1);
+                            }else {
+                                //查看当前节点层级是否匹配
+                                if (vo2.getNodeType() == null){
+                                    MeterTreeContract tree = new MeterTreeContract();
+                                    tree.setId(vo2.getId());
+                                    tree.setNodeType(j);
+                                    resultNodeListUpdate.add(tree);
+                                }else {
+                                    if (vo2.getNodeType() != j){
+                                        throw new ServiceException("节点:"+nodeName+"存在于合同中,但类型和当前Excel不匹配");
+                                    }
+                                }
+                                //工序节点涉及到修改备注和图号
+                                if (i == 6 && (StringUtils.isNotBlank(map.get("图册")) || StringUtils.isNotBlank(map.get("图号")))){
+                                    MeterTreeContract tree = new MeterTreeContract();
+                                    tree.setId(vo2.getId());
+                                    tree.setRemarks(map.get("图册"));
+                                    tree.setContractPicture(map.get("图号"));
+                                    resultNodeListUpdate.add(tree);
+                                }
+                                //把当前节点设置为上一层,并且依次重置thisNode和thisMap
+                                lastNode = vo2;
+                                thisNode = lastNode.getChildren();
+                                if (thisNode != null && thisNode.size() > 0) {
+                                    //当前层节点map,key为节点名称(同一层,不能有节点名称相同)
+                                    thisMap = thisNode.stream().collect(Collectors.toMap(l -> l.getNodeName(), l -> l));
+                                }
+
+                            }
+                        }
+                    }
+                }
+                // 处理完成节点,处理清单,如果清单不存在则直接跳过
+                String formNumber = map.get("清单编号");
+                if (StringUtils.isBlank(formNumber)){
+                    continue;
+                }
+                //获取清单基础信息
+                ContractInventoryForm form = inventoryFormMap.get(formNumber);
+                InventoryFormMeterVO2 meter2 = meterMap.get(new MeterImport3VO2(lastNode.getId(), form.getId()));
+                BigDecimal total = BigDecimal.ZERO;
+                try {
+                    total = new BigDecimal(map.get("分解核实量"));
+                }catch (Exception e){
+                    throw new ServiceException("清单编号:"+map.get("清单编号")+",分解核实量包含字符,请修改后重新导入");
+                }
+                if(lastNode.getIsNew() == 1 || !isLink || meter2 == null){
+                    //上一层节点为新增,直接挂载
+                    //新增中间表数据
+                    InventoryFormMeter meter = new InventoryFormMeter();
+                    meter.setProjectId(meterTreeContract.getProjectId());
+                    meter.setContractId(meterTreeContract.getContractId());
+                    meter.setContractMeterId(lastNode.getId());
+                    meter.setContractFormId(form.getId());
+                    meter.setBuildPictureTotal(total);
+                    meter.setChangeBuildPictureTotal(total);
+                    meter.setBuildPictureMoney(total.multiply(form.getCurrentPrice()));
+                    meter.setChangeBuildPictureMoney(meter.getBuildPictureMoney());
+                    resultFormListAdd.add(meter);
+                    //设置清单增量
+                    ContractInventoryForm form2 = new ContractInventoryForm();
+                    form2.setFormNumber(form.getFormNumber());
+                    form2.setChangeTotal(total);
+                    InventoryFormListUpdate.add(form2);
+                }else {
+                    //当前节点下存在当前表单,则判断是否被计量过,被计量过则跳过,没被计量过则做增量,没被计量时,施工图金额和变更后施工图金额相等
+                    if (meter2.getIsMeter() == 0){
+                        InventoryFormMeter meter = new InventoryFormMeter();
+                        meter.setId(meter2.getId());
+                        meter.setBuildPictureTotal(meter2.getBuildPictureTotal().add(total));
+                        meter.setChangeBuildPictureTotal(meter.getBuildPictureTotal());
+                        meter.setBuildPictureMoney(meter.getBuildPictureTotal().multiply(form.getCurrentPrice()));
+                        meter.setChangeBuildPictureMoney(meter.getBuildPictureMoney());
+                        resultFormListUpdate.add(meter);
+                        //设置清单增量
+                        ContractInventoryForm form2 = new ContractInventoryForm();
+                        form2.setFormNumber(form.getFormNumber());
+                        form2.setChangeTotal(total);
+                        InventoryFormListUpdate.add(form2);
+                    }
+                }
+                //把上层节点id添加进修改集合,重新计算金额
+                updateNodeSet.add(lastNode.getId());
+
+            }
+            int addNode = 0;
+            int addForm = 0;
+            int updateForm = 0;
+            //新增节点
+            if (resultNodeAdd.size() > 0) {
+                resultNodeListAdd = resultNodeAdd.stream().map(l->{
+                    MeterTreeContract contract = new MeterTreeContract();
+                    BeanUtil.copyProperties(l,contract);
+                    return contract;
+                }).collect(Collectors.toList());
+                this.saveBatch(resultNodeListAdd, 1000);
+                addNode = resultNodeListAdd.size();
+            }
+            //修改节点 图号或者备注
+            if (resultNodeListUpdate.size() > 0){
+                this.updateBatchById(resultNodeListUpdate);
+            }
+            /*清单中间新增*/
+            if (resultFormListAdd.size() > 0) {
+                //校验数据
+                try {
+                    resultFormListAdd.stream().collect(Collectors.toMap(l -> new MeterImport3VO2(l.getContractMeterId(), l.getContractFormId()), l -> l));
+                }catch (Exception e){
+                    throw new ServiceException("导入模板中存在同一个节点下清单重复,请直接合并分解量后再导入");
+                }
+                inventoryFormMeterMapper.batchInsert(resultFormListAdd);
+                addForm = resultFormListAdd.size();
+            }
+
+            /*清单中间数量修改*/
+            if (resultFormListUpdate.size() > 0) {
+                for (InventoryFormMeter inventoryFormMeter : resultFormListUpdate) {
+                    String sql = "UPDATE s_inventory_form_meter " +
+                            "SET build_picture_total = ? ," +
+                            "change_build_picture_total = ? ," +
+                            "build_picture_money = ? ," +
+                            "change_build_picture_money = ? WHERE id = ?";
+                    jdbcTemplate.update(sql,
+                            inventoryFormMeter.getBuildPictureTotal(),
+                            inventoryFormMeter.getChangeBuildPictureTotal(),
+                            inventoryFormMeter.getBuildPictureMoney(),
+                            inventoryFormMeter.getChangeBuildPictureMoney(),
+                            inventoryFormMeter.getId());
+                }
+                updateForm = resultFormListUpdate.size();
+            }
+            //修改合同工程清单的变更后数量
+            if (InventoryFormListUpdate.size() > 0) {
+                Map<String, BigDecimal> map = InventoryFormListUpdate.stream()
+                        .collect(Collectors.groupingBy(l -> l.getFormNumber(),
+                                Collectors.mapping(ContractInventoryForm::getChangeTotal, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
+                baseMapper.batchUpdateFormByNumber(meterTreeContract.getContractId(), map);
+            }
+
+
+            //修改节点金额放最后,等中间表数据保存完成之后,再去统计
+            if (updateNodeSet.size() > 0){
+                this.asyncCalculateNodeMoney2(updateNodeSet);
+            }
+            return R.success("成功导入:节点("+addNode+")个,"+"新增清单("+addForm+")条,"+"修改清单("+updateForm+")条.");
+        }catch (Exception e){
+            throw new ServiceException("导入失败:"+e.getMessage());
+        }
+    }
+
     @Override
     @Transactional
     public boolean contractUpdate(MeterTreeContractDTO dto) {