浏览代码

合同工程清单所有接口

qianxb 1 年之前
父节点
当前提交
378ef48063

+ 1 - 1
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/entity/ChangeTokenInventory.java

@@ -57,7 +57,7 @@ public class ChangeTokenInventory extends BaseEntity {
      * 合同工程清单id
      * 合同工程清单id
      */
      */
     @ApiModelProperty(value = "合同工程清单id")
     @ApiModelProperty(value = "合同工程清单id")
-    private Long inventoryFormId;
+    private Long contractFormId;
     /**
     /**
      * 变更前数量
      * 变更前数量
      */
      */

+ 6 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/entity/ContractInventoryForm.java

@@ -191,6 +191,12 @@ public class ContractInventoryForm extends BaseEntity {
     @ApiModelProperty(value = "节点层级")
     @ApiModelProperty(value = "节点层级")
     @ExcelIgnore
     @ExcelIgnore
     private Integer nodeTier;
     private Integer nodeTier;
+    /**
+     * 生成变更时划分数量,零号变更时存入
+     */
+    @ApiModelProperty(value = "生成变更时划分数量,零号变更时存入")
+    @ExcelIgnore
+    private Integer buildChangeTotal;
 
 
 
 
 
 

+ 6 - 1
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/vo/ContractInventoryFormVO.java

@@ -16,12 +16,14 @@
  */
  */
 package org.springblade.meter.vo;
 package org.springblade.meter.vo;
 
 
+import com.alibaba.excel.annotation.ExcelIgnore;
+import io.swagger.annotations.ApiModelProperty;
 import org.springblade.meter.entity.ContractInventoryForm;
 import org.springblade.meter.entity.ContractInventoryForm;
 import lombok.Data;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.EqualsAndHashCode;
 
 
 /**
 /**
- * 合同工程清单表视图实体类
+ * 合同工程清单VO
  *
  *
  * @author BladeX
  * @author BladeX
  * @since 2023-11-29
  * @since 2023-11-29
@@ -31,4 +33,7 @@ import lombok.EqualsAndHashCode;
 public class ContractInventoryFormVO extends ContractInventoryForm {
 public class ContractInventoryFormVO extends ContractInventoryForm {
 	private static final long serialVersionUID = 1L;
 	private static final long serialVersionUID = 1L;
 
 
+	@ApiModelProperty(value = "是否增补节点")
+	private String isSupplementName;
+
 }
 }

+ 8 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/vo/FormTreeVO.java

@@ -1,5 +1,7 @@
 package org.springblade.meter.vo;
 package org.springblade.meter.vo;
 
 
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@@ -57,5 +59,11 @@ public class FormTreeVO implements INode<FormTreeVO> {
     @ApiModelProperty(value = "清单名称")
     @ApiModelProperty(value = "清单名称")
     private String formName;
     private String formName;
 
 
+    @ApiModelProperty(value = "是否锁定0否1是")
+    private Integer isLock;
+
+    @ApiModelProperty(value = "章编号")
+    private String chapterNumber;
+
 
 
 }
 }

+ 40 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/vo/InventoryFormDetailVO.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.ContractInventoryForm;
+
+import java.util.List;
+
+/**
+ * 合同工程清单详情VO,包含下级清单集合
+ *
+ * @author BladeX
+ * @since 2023-11-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class InventoryFormDetailVO extends ContractInventoryForm {
+	private static final long serialVersionUID = 1L;
+
+	@ApiModelProperty(value = "下级节点集合")
+	private List<ContractInventoryFormVO> list;
+
+}

+ 35 - 26
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/ContractInventoryFormController.java

@@ -25,7 +25,9 @@ import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.meter.vo.ContractInventoryFormVO;
 import org.springblade.meter.vo.FormTreeVO;
 import org.springblade.meter.vo.FormTreeVO;
+import org.springblade.meter.vo.InventoryFormDetailVO;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -76,25 +78,28 @@ public class ContractInventoryFormController extends BladeController {
 	}
 	}
 
 
 	/**
 	/**
-	 * 详情
+	 * 获取节点详情
 	 */
 	 */
 	@GetMapping("/detail")
 	@GetMapping("/detail")
 	@ApiOperationSupport(order = 2)
 	@ApiOperationSupport(order = 2)
-	@ApiOperation(value = "详情", notes = "传入contractInventoryForm")
-	public R<ContractInventoryForm> detail(ContractInventoryForm contractInventoryForm) {
-		ContractInventoryForm detail = contractInventoryFormService.getOne(Condition.getQueryWrapper(contractInventoryForm));
-		return R.data(detail);
+	@ApiOperation(value = "获取节点详情", notes = "传入当前节点id")
+	public R<InventoryFormDetailVO> detail(Long id) {
+		InventoryFormDetailVO vo = contractInventoryFormService.detail(id);
+		return R.data(vo);
 	}
 	}
 
 
 	/**
 	/**
-	 * 分页 合同工程清单表
+	 * 锁定节点
 	 */
 	 */
-	@GetMapping("/list")
+	@GetMapping("/lockNode")
 	@ApiOperationSupport(order = 3)
 	@ApiOperationSupport(order = 3)
-	@ApiOperation(value = "分页", notes = "传入contractInventoryForm")
-	public R<IPage<ContractInventoryForm>> list(ContractInventoryForm contractInventoryForm, Query query) {
-		IPage<ContractInventoryForm> pages = contractInventoryFormService.page(Condition.getPage(query), Condition.getQueryWrapper(contractInventoryForm));
-		return R.data(pages);
+	@ApiOperation(value = "锁定节点", notes = "传入当前节点id,和状态0为锁定,1为解锁")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "id", value = "当前节点id", required = true),
+			@ApiImplicitParam(name = "status", value = "状态0为锁定,1为解锁", required = true)
+	})
+	public R<String> lockNode(Long id,Long contractId,Integer status) {
+		return contractInventoryFormService.lockNode(id,contractId,status);
 	}
 	}
 
 
 
 
@@ -102,42 +107,46 @@ public class ContractInventoryFormController extends BladeController {
 	/**
 	/**
 	 * 新增 合同工程清单表
 	 * 新增 合同工程清单表
 	 */
 	 */
-	@PostMapping("/save")
+	@PostMapping("/add")
 	@ApiOperationSupport(order = 4)
 	@ApiOperationSupport(order = 4)
 	@ApiOperation(value = "新增", notes = "传入contractInventoryForm")
 	@ApiOperation(value = "新增", notes = "传入contractInventoryForm")
-	public R save(@Valid @RequestBody ContractInventoryForm contractInventoryForm) {
-		return R.status(contractInventoryFormService.save(contractInventoryForm));
+	public R<String> add(@Valid @RequestBody ContractInventoryForm form) {
+		contractInventoryFormService.add(form);
+		return R.success("新增成功");
 	}
 	}
 
 
 	/**
 	/**
 	 * 修改 合同工程清单表
 	 * 修改 合同工程清单表
 	 */
 	 */
-	@PostMapping("/update")
+	@PostMapping("/updateForm")
 	@ApiOperationSupport(order = 5)
 	@ApiOperationSupport(order = 5)
 	@ApiOperation(value = "修改", notes = "传入contractInventoryForm")
 	@ApiOperation(value = "修改", notes = "传入contractInventoryForm")
-	public R update(@Valid @RequestBody ContractInventoryForm contractInventoryForm) {
-		return R.status(contractInventoryFormService.updateById(contractInventoryForm));
+	public R<String> updateForm(@Valid @RequestBody ContractInventoryForm form) {
+		contractInventoryFormService.updateForm(form);
+		return R.success("修改成功");
 	}
 	}
 
 
 	/**
 	/**
-	 * 新增或修改 合同工程清单表
+	 * 排序 合同工程清单表
 	 */
 	 */
-	@PostMapping("/submit")
+	@PostMapping("/sort")
 	@ApiOperationSupport(order = 6)
 	@ApiOperationSupport(order = 6)
-	@ApiOperation(value = "新增或修改", notes = "传入contractInventoryForm")
-	public R submit(@Valid @RequestBody ContractInventoryForm contractInventoryForm) {
-		return R.status(contractInventoryFormService.saveOrUpdate(contractInventoryForm));
+	@ApiOperation(value = "排序", notes = "传入排序后的id,字符串拼接逗号分隔")
+	public R submit(@Valid @RequestParam String ids) {
+		contractInventoryFormService.sort(ids);
+		return R.success("排序完成");
 	}
 	}
 
 
 	
 	
 	/**
 	/**
 	 * 删除 合同工程清单表
 	 * 删除 合同工程清单表
 	 */
 	 */
-	@PostMapping("/remove")
+	@GetMapping("/delete")
 	@ApiOperationSupport(order = 7)
 	@ApiOperationSupport(order = 7)
-	@ApiOperation(value = "逻辑删除", notes = "传入ids")
-	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
-		return R.status(contractInventoryFormService.deleteLogic(Func.toLongList(ids)));
+	@ApiOperation(value = "删除单个节点", notes = "传入id")
+	public R delete(@ApiParam(value = "id", required = true) @RequestParam Long id,@RequestParam Long contractId) {
+		contractInventoryFormService.delete(id,contractId);
+		return R.success("删除成功");
 	}
 	}
 
 
 	
 	

+ 10 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ContractInventoryFormMapper.java

@@ -19,7 +19,9 @@ package org.springblade.meter.mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
 import org.springblade.meter.entity.ContractInventoryForm;
 import org.springblade.meter.entity.ContractInventoryForm;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.meter.vo.ContractInventoryFormVO;
 import org.springblade.meter.vo.FormTreeVO;
 import org.springblade.meter.vo.FormTreeVO;
+import org.springblade.meter.vo.InventoryFormDetailVO;
 
 
 import java.util.List;
 import java.util.List;
 
 
@@ -33,4 +35,12 @@ public interface ContractInventoryFormMapper extends BaseMapper<ContractInventor
 
 
 
 
     List<FormTreeVO> getAllNode(@Param("projectId") Long projectId,@Param("contractId") Long contractId);
     List<FormTreeVO> getAllNode(@Param("projectId") Long projectId,@Param("contractId") Long contractId);
+
+    InventoryFormDetailVO getById(@Param("id") Long id);
+
+    List<ContractInventoryFormVO> getChildList(@Param("id") Long id,@Param("contractId") Long contractId);
+
+    void updateNodeLock(@Param("id") Long id,@Param("contractId") Long contractId,@Param("isLock") Integer isLock);
+
+    void updateNode(@Param("id") Long id,@Param("contractId") Long contractId);
 }
 }

+ 25 - 2
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/ContractInventoryFormMapper.xml

@@ -35,13 +35,36 @@
         <result column="is_lock" property="isLock"/>
         <result column="is_lock" property="isLock"/>
         <result column="is_supplement" property="isSupplement"/>
         <result column="is_supplement" property="isSupplement"/>
     </resultMap>
     </resultMap>
+    <update id="updateNodeLock">
+        update s_contract_inventory_form set is_lock = #{isLock} where
+            contract_id = #{contractId} and (id = #{id} or FIND_IN_SET(#{id},ancestors) > 0)
+    </update>
+    <update id="updateNode">
+        update s_contract_inventory_form set is_deleted = 1 where
+            contract_id = #{contractId} and (id = #{id} or FIND_IN_SET(#{id},ancestors) > 0)
+    </update>
     <select id="getAllNode" resultType="org.springblade.meter.vo.FormTreeVO">
     <select id="getAllNode" resultType="org.springblade.meter.vo.FormTreeVO">
-        select id,parent_id,
-               concat(scif.form_number, scif.form_name) as form_name,
+        select id,parent_id,is_lock,chapter_number,
+               if(scif.is_supplement=0,concat(scif.form_number, scif.form_name),concat(scif.form_number, scif.form_name,'[增补]')) as form_name,
                (select COUNT(1) from s_contract_inventory_form
                (select COUNT(1) from s_contract_inventory_form
                     WHERE contract_id = #{contractId} and is_deleted=0 and parent_id = scif.id) as hasChild
                     WHERE contract_id = #{contractId} and is_deleted=0 and parent_id = scif.id) as hasChild
         from s_contract_inventory_form scif
         from s_contract_inventory_form scif
         where project_id = #{projectId} and contract_id = #{contractId} and is_deleted = 0
         where project_id = #{projectId} and contract_id = #{contractId} and is_deleted = 0
+        order by sort
+    </select>
+    <select id="getById" resultType="org.springblade.meter.vo.InventoryFormDetailVO">
+        select * from s_contract_inventory_form where id = #{id}
+    </select>
+    <select id="getChildList" resultType="org.springblade.meter.vo.ContractInventoryFormVO">
+        select form_number,unit,current_price,contract_total,change_price,change_total,if(is_supplement=0,'否','是') as isSupplementName,
+               if(is_supplement=0,form_name,concat(form_name,'[增补]')) as form_name,
+               (select sum(contract_money) from s_contract_inventory_form sci where sci.is_deleted=0 and sci.contract_id = #{contractId}
+                        and (sci.id = scif.id or FIND_IN_SET(scif.id,ancestors) > 0)) as contract_money,
+               (select sum(change_money) from s_contract_inventory_form sci where sci.is_deleted=0 and sci.contract_id = #{contractId}
+                        and (sci.id = scif.id or FIND_IN_SET(scif.id,ancestors) > 0)) as change_money
+        from s_contract_inventory_form scif
+        where is_deleted=0 and contract_id = #{contractId} and parent_id = #{id}
+        order by sort
     </select>
     </select>
 
 
 
 

+ 14 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/IContractInventoryFormService.java

@@ -19,7 +19,9 @@ package org.springblade.meter.service;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.api.R;
 import org.springblade.meter.entity.ContractInventoryForm;
 import org.springblade.meter.entity.ContractInventoryForm;
 import org.springblade.core.mp.base.BaseService;
 import org.springblade.core.mp.base.BaseService;
+import org.springblade.meter.vo.ContractInventoryFormVO;
 import org.springblade.meter.vo.FormTreeVO;
 import org.springblade.meter.vo.FormTreeVO;
+import org.springblade.meter.vo.InventoryFormDetailVO;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
 
 
 import java.util.List;
 import java.util.List;
@@ -36,4 +38,16 @@ public interface IContractInventoryFormService extends BaseService<ContractInven
     R<String> importExcel(MultipartFile file,Long projectId, Long contractId);
     R<String> importExcel(MultipartFile file,Long projectId, Long contractId);
 
 
     List<FormTreeVO> getFormTree(Long projectId, Long contractId);
     List<FormTreeVO> getFormTree(Long projectId, Long contractId);
+
+    InventoryFormDetailVO detail(Long id);
+
+    R<String> lockNode(Long id,Long contractId,Integer status);
+
+    void add(ContractInventoryForm form);
+
+    void updateForm(ContractInventoryForm form);
+
+    void sort(String ids);
+
+    void delete(Long id,Long contractId);
 }
 }

+ 296 - 66
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/ContractInventoryFormServiceImpl.java

@@ -17,17 +17,28 @@
 package org.springblade.meter.service.impl;
 package org.springblade.meter.service.impl;
 
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.excel.util.ExcelUtil;
 import org.springblade.core.excel.util.ExcelUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.meter.entity.ChangeTokenInventory;
 import org.springblade.meter.entity.ContractInventoryForm;
 import org.springblade.meter.entity.ContractInventoryForm;
+import org.springblade.meter.entity.InventoryFormMeter;
 import org.springblade.meter.mapper.ContractInventoryFormMapper;
 import org.springblade.meter.mapper.ContractInventoryFormMapper;
+import org.springblade.meter.service.IChangeTokenFormService;
+import org.springblade.meter.service.IChangeTokenInventoryService;
 import org.springblade.meter.service.IContractInventoryFormService;
 import org.springblade.meter.service.IContractInventoryFormService;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.meter.service.IInventoryFormMeterService;
 import org.springblade.meter.utils.ForestNodeMerger;
 import org.springblade.meter.utils.ForestNodeMerger;
+import org.springblade.meter.vo.ContractInventoryFormVO;
 import org.springblade.meter.vo.FormTreeVO;
 import org.springblade.meter.vo.FormTreeVO;
+import org.springblade.meter.vo.InventoryFormDetailVO;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
@@ -46,8 +57,12 @@ import java.util.stream.Collectors;
  * @since 2023-11-29
  * @since 2023-11-29
  */
  */
 @Service
 @Service
+@AllArgsConstructor
 public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractInventoryFormMapper, ContractInventoryForm> implements IContractInventoryFormService {
 public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractInventoryFormMapper, ContractInventoryForm> implements IContractInventoryFormService {
 
 
+        private final IInventoryFormMeterService formMeterService;
+
+        private final IChangeTokenInventoryService tokenInventoryService;
 
 
     /**
     /**
      * 导入excel
      * 导入excel
@@ -60,41 +75,19 @@ public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractIn
         //校验文件类型
         //校验文件类型
         String filename = file.getOriginalFilename();
         String filename = file.getOriginalFilename();
         String fileSuffix = filename.substring(filename.lastIndexOf(".")+1);
         String fileSuffix = filename.substring(filename.lastIndexOf(".")+1);
-        if (!"xls,xlsx".contains(fileSuffix)){
-            throw new ServiceException("请传入excel文件");
-        }
-        List<ContractInventoryForm> excels = ExcelUtil.read(file, ContractInventoryForm.class);
-        List<Integer> firstNode = new ArrayList<>();
-        //校验必填字段是否为空
-        for (int i = 0; i < excels.size(); i++) {
-            ContractInventoryForm excel = excels.get(i);
-            if (StringUtils.isBlank(excel.getImportNumber()) || StringUtils.isBlank(excel.getFormNumber() ) || StringUtils.isBlank(excel.getFormName())){
-                throw new ServiceException("excel中有必填项未填写,请检查后重新导入");
-            }
-            excel.setProjectId(projectId);
-            excel.setContractId(contractId);
-            excel.setId(SnowFlakeUtil.getId());
-            //保存每个首节点位置
-            if (!excel.getImportNumber().contains("-")){
-                firstNode.add(i);
+        Integer allTotal = 0;
+        Integer nodes = 0;
+        Integer endTotal = 0;
+        try {
+            if (!"xls,xlsx".contains(fileSuffix)){
+                throw new ServiceException("请传入excel文件");
             }
             }
-        }
-        int size = firstNode.size();
-        if (size == 0){
-            throw new ServiceException("未找到首节点,请检查后重新导入");
-        }
-        //根据首节点分成多个数组
-        List<List<ContractInventoryForm>> lists = new ArrayList<>();
-        //只有一个节点,直接单独处理
-        if (size == 1){
-            lists.add(excels);
-        }else {
-            for (int i = 0; i < size-1; i++) {
-                lists.add(excels.subList(firstNode.get(i),firstNode.get(i+1)));
+            List<ContractInventoryForm> excels = ExcelUtil.read(file, ContractInventoryForm.class);
+            if (excels == null || excels.size() == 0){
+                throw new ServiceException("未识别到excel中数据,请检查后重新导入");
             }
             }
-            lists.add(excels.subList(firstNode.get(size-1),excels.size()));
-        }
-        try {
+            allTotal = excels.size();
+            List<Integer> firstNode = new ArrayList<>();
             //获取当前合同的首节点
             //获取当前合同的首节点
             ContractInventoryForm one = this.getOne(new LambdaQueryWrapper<ContractInventoryForm>()
             ContractInventoryForm one = this.getOne(new LambdaQueryWrapper<ContractInventoryForm>()
                     .eq(ContractInventoryForm::getContractId, contractId)
                     .eq(ContractInventoryForm::getContractId, contractId)
@@ -103,6 +96,53 @@ public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractIn
                 throw new ServiceException("未找到当前合同根节点,请联系管理员");
                 throw new ServiceException("未找到当前合同根节点,请联系管理员");
             }
             }
             Long id = one.getId();
             Long id = one.getId();
+            //查询出当前合同下所有的节点,并按照导入编号分组
+            List<ContractInventoryForm> allNode = this.list(new LambdaQueryWrapper<ContractInventoryForm>()
+                    .eq(ContractInventoryForm::getContractId, contractId)
+                    .isNotNull(ContractInventoryForm::getImportNumber));
+            nodes = allNode.size();
+            Map<String, ContractInventoryForm> map = allNode.stream().collect(Collectors.toMap(ContractInventoryForm::getImportNumber, l -> l));
+            //校验必填字段是否为空,设置通用字段,并且通过导入编号对已经存在的节点做标识
+            for (int i = 0; i < excels.size(); i++) {
+                ContractInventoryForm excel = excels.get(i);
+                if (StringUtils.isBlank(excel.getImportNumber()) || StringUtils.isBlank(excel.getFormNumber() ) || StringUtils.isBlank(excel.getFormName())){
+                    throw new ServiceException("excel中有必填项未填写,请检查后重新导入");
+                }
+                excel.setProjectId(projectId);
+                excel.setContractId(contractId);
+                //判断是否已经存在于合同段
+                ContractInventoryForm form = map.get(excel.getImportNumber());
+                if (form == null) {
+                    excel.setId(SnowFlakeUtil.getId());
+                    excel.setStatus(0);
+                }else {
+                    excel.setId(form.getId());
+                    excel.setParentId(form.getParentId());
+                    excel.setAncestors(form.getAncestors());
+                    excel.setParentNumber(form.getParentNumber());
+                    excel.setIsFormNode(form.getIsFormNode());
+                    excel.setStatus(1);
+                }
+                //保存每个首节点位置
+                if (!excel.getImportNumber().contains("-")){
+                    firstNode.add(i);
+                }
+            }
+            int size = firstNode.size();
+            if (size == 0){
+                throw new ServiceException("未找到首节点,请检查后重新导入");
+            }
+            //根据首节点分成多个数组
+            List<List<ContractInventoryForm>> lists = new ArrayList<>();
+            //只有一个节点,直接单独处理
+            if (size == 1){
+                lists.add(excels);
+            }else {
+                for (int i = 0; i < size-1; i++) {
+                    lists.add(excels.subList(firstNode.get(i),firstNode.get(i+1)));
+                }
+                lists.add(excels.subList(firstNode.get(size-1),excels.size()));
+            }
             Map<String,ContractInventoryForm> lastMap = new HashMap<>();
             Map<String,ContractInventoryForm> lastMap = new HashMap<>();
             Map<String,ContractInventoryForm> thisMap = new HashMap<>();
             Map<String,ContractInventoryForm> thisMap = new HashMap<>();
             //循环保存
             //循环保存
@@ -117,30 +157,33 @@ public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractIn
                     String num = fo.getImportNumber();
                     String num = fo.getImportNumber();
                     int i = num.split("-").length - 1;
                     int i = num.split("-").length - 1;
                     fo.setNodeTier(i);
                     fo.setNodeTier(i);
-                    //判断单位,数量,单价是否存在数据,如果有一个存在数据,则为清单节点
-                    if (fo.getContractTotal() != null || StringUtils.isNotBlank(fo.getUnit()) || fo.getBidPrice() != null){
-                        fo.setIsFormNode(1);
-                        if (fo.getContractTotal() != null){
-                            fo.setContractTotal(fo.getContractTotal());
-                            fo.setChangeTotal(fo.getContractTotal());
-                        }
-                        if (fo.getBidPrice() != null){
-                            fo.setCurrentPrice(fo.getBidPrice());
-                            fo.setChangePrice(fo.getBidPrice());
+                    //如果是已经存在的节点则不设置这些值和父编号
+                    if (fo.getStatus() == 0) {
+                        //判断数量,单价是否存在数据,如果有一个存在数据,则为清单节点
+                        if (fo.getContractTotal() != null ||  fo.getBidPrice() != null) {
+                            fo.setIsFormNode(1);
+                            if (fo.getContractTotal() != null) {
+                                fo.setContractTotal(fo.getContractTotal());
+                                fo.setChangeTotal(fo.getContractTotal());
+                            }
+                            if (fo.getBidPrice() != null) {
+                                fo.setCurrentPrice(fo.getBidPrice());
+                                fo.setChangePrice(fo.getBidPrice());
+                            }
+                            if (fo.getContractTotal() != null && fo.getBidPrice() != null) {
+                                fo.setContractMoney(new BigDecimal(fo.getContractTotal()).multiply(fo.getBidPrice()));
+                                fo.setChangeMoney(fo.getContractMoney());
+                            }
+                        } else {
+                            fo.setIsFormNode(0);
                         }
                         }
-                        if (fo.getContractTotal() != null && fo.getBidPrice() != null){
-                            fo.setContractMoney(new BigDecimal(fo.getContractTotal()).multiply(fo.getBidPrice()));
-                            fo.setChangeMoney(fo.getChangeMoney());
+                        if (i == 0) {
+                            continue;
+                        } else if (i == 1) {
+                            fo.setParentNumber(number);
+                        } else {
+                            fo.setParentNumber(num.substring(0, num.lastIndexOf("-")));
                         }
                         }
-                    }else {
-                        fo.setIsFormNode(0);
-                    }
-                    if (i == 0){
-                        continue;
-                    }else if (i == 1){
-                        fo.setParentNumber(number);
-                    }else{
-                        fo.setParentNumber(num.substring(0, num.lastIndexOf("-")));
                     }
                     }
                 }
                 }
                 Map<Integer, List<ContractInventoryForm>> listMap = list.parallelStream().collect(Collectors.groupingBy(ContractInventoryForm::getNodeTier));
                 Map<Integer, List<ContractInventoryForm>> listMap = list.parallelStream().collect(Collectors.groupingBy(ContractInventoryForm::getNodeTier));
@@ -153,15 +196,20 @@ public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractIn
                     }
                     }
                     for (ContractInventoryForm f : forms) {
                     for (ContractInventoryForm f : forms) {
                         ContractInventoryForm fo = lastMap.get(f.getParentNumber());
                         ContractInventoryForm fo = lastMap.get(f.getParentNumber());
+                        if (fo == null){
+                            throw new ServiceException("清单节点:"+f.getFormName()+"未找到上级节点");
+                        }
                         if (fo.getIsFormNode() == 1){
                         if (fo.getIsFormNode() == 1){
                             throw new ServiceException("清单节点:"+fo.getFormName()+"下还有节点,检查后重新上传excel");
                             throw new ServiceException("清单节点:"+fo.getFormName()+"下还有节点,检查后重新上传excel");
                         }
                         }
-                        //设置章编号和清单类型,必须根父节点一致
-                        f.setChapterNumber(fo.getChapterNumber());
-                        f.setFormType(fo.getFormType());
-                        //设置父id和祖籍id
-                        f.setParentId(fo.getId());
-                        f.setAncestors(fo.getAncestors()+","+fo.getId());
+                        if (f.getStatus() == 0) {
+                            //设置章编号和清单类型,必须根父节点一致
+                            f.setChapterNumber(fo.getChapterNumber());
+                            f.setFormType(fo.getFormType());
+                            //设置父id和祖籍id
+                            f.setParentId(fo.getId());
+                            f.setAncestors(fo.getAncestors() + "," + fo.getId());
+                        }
                         thisMap.put(f.getImportNumber(),f);
                         thisMap.put(f.getImportNumber(),f);
                     }
                     }
                     lastMap = thisMap;
                     lastMap = thisMap;
@@ -179,15 +227,19 @@ public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractIn
             if (sb.length() > 0){
             if (sb.length() > 0){
                 throw new ServiceException("以下清单名称:"+sb.deleteCharAt(sb.length()-1)+"。未找到上级节点,请修改excel后重新导入");
                 throw new ServiceException("以下清单名称:"+sb.deleteCharAt(sb.length()-1)+"。未找到上级节点,请修改excel后重新导入");
             }
             }
-            //所有节点设置好数据,比对已经存在的节点,然后移除集合,只保存不存在的
-
-            this.saveBatch(excels);
+            //移除所有已经存在的节点,保存
+            List<ContractInventoryForm> list = excels.stream().filter(l -> l.getStatus() == 0).collect(Collectors.toList());
+            endTotal = list.size();
+            this.saveBatch(list);
 
 
         }catch (Exception e){
         }catch (Exception e){
             throw new ServiceException(e.getMessage());
             throw new ServiceException(e.getMessage());
         }
         }
-
-        return R.data("导入成功");
+        if (nodes == 0) {
+            return R.data("成功导入" + allTotal + "条数据");
+        }else {
+            return R.data("成功新增" + endTotal + "条数据");
+        }
     }
     }
 
 
     /**
     /**
@@ -214,4 +266,182 @@ public class ContractInventoryFormServiceImpl extends BaseServiceImpl<ContractIn
         }
         }
         return ForestNodeMerger.merge(vos);
         return ForestNodeMerger.merge(vos);
     }
     }
+
+    /**
+     * 获取节点详情
+     */
+    @Override
+    public InventoryFormDetailVO detail(Long id) {
+        //查询当前节点详情
+        InventoryFormDetailVO vo = baseMapper.getById(id);
+        //如果是清单节点就直接返回
+        if (vo.getIsFormNode() == 1){
+            return vo;
+        }
+        //查询下级节点集合,并统计合同金额,变更后金额
+        List<ContractInventoryFormVO> list = baseMapper.getChildList(id,vo.getContractId());
+        vo.setList(list);
+        return vo;
+    }
+
+    /**
+     * 锁定节点
+     */
+    @Override
+    public R<String> lockNode(Long id,Long contractId,Integer status) {
+        if (status == 0){
+            //锁定节点
+            baseMapper.updateNodeLock(id,contractId,1);
+            return R.data("当前节点以及子节点已锁定");
+        }else {
+            //解锁节点
+            baseMapper.updateNodeLock(id,contractId,0);
+            return R.data("当前节点以及子节点已解除锁定");
+        }
+
+    }
+
+    /**
+     * 新增 合同工程清单表
+     */
+    @Override
+    public void add(ContractInventoryForm form) {
+        //如果为增补清单,那么节点类型必须为清单节点
+        if (form.getIsSupplement() == 1){
+            if (form.getIsFormNode() == 0){
+                throw new ServiceException("增补清单必须为清单节点");
+            }
+        }
+        //获取父级节点信息,判断是否已经锁定,判断是否为清单节点
+        ContractInventoryForm parentNode = this.getById(form.getParentId());
+        if (parentNode.getIsLock() == 1){
+            throw new ServiceException("当前节点已经被锁定不能新增");
+        }
+        if (parentNode.getIsFormNode() == 1){
+            throw new ServiceException("当前节点为清单节点,不能新增子节点");
+        }
+        //如果父节点有章编号,则判断当前节点章编号是否与父级节点一致
+        if (StringUtils.isNotBlank(parentNode.getChapterNumber())){
+            if (!parentNode.getChapterNumber().equals(form.getChapterNumber())){
+                throw new ServiceException("子节点的章编号,必须与父节点的章编号相同");
+            }
+        }
+        //如果父节点有清单类型,则判断当前节点清单类型是否与父节点一致
+        if (parentNode.getFormType() != null){
+            if (!parentNode.getFormType().equals(form.getFormType())){
+                throw new ServiceException("子节点的清单类型,必须与父节点的清单类型相同");
+            }
+        }
+        //设置祖级节点
+        form.setAncestors(parentNode.getAncestors()+","+parentNode.getId());
+        //如果不是根节点则设置层级
+        if (parentNode.getNodeTier() != null) {
+            int i = form.getFormNumber().split("-").length - 1;
+            if (i != (parentNode.getNodeTier() + 1)){
+                throw new ServiceException("清单编号规则错误,请修改后保存");
+            }
+            form.setNodeTier(i);
+        }
+        this.save(form);
+    }
+
+    /**
+     * 修改 合同工程清单表
+     */
+    @Override
+    public void updateForm(ContractInventoryForm form) {
+        //获取当前节点信息
+        ContractInventoryForm nodeInfo = this.getById(form.getId());
+        //判断节点是否已经锁定
+        if (nodeInfo.getIsLock() == 1){
+            throw new ServiceException("当前节点已经被锁定不能修改");
+        }
+        //如果当前节点类型和修改后的节点类型相同,则不校验
+        if (nodeInfo.getIsFormNode().equals(form.getIsFormNode())) {
+            //相同则先判断修改后节点类型是否为清单类型
+            if (form.getIsFormNode().equals(1)){
+                //判断是否已经被分解或者被变更,包括零号变更
+                Boolean isChange = this.nodeIsChange(nodeInfo);
+                //发生过变更,就去判断单价和数量。没被变更或者修改过,就不去判断单价和数量是否发生改变
+                if (isChange) {
+                    //判断单价和数量是否发生改变
+                    if (nodeInfo.getBidPrice() != null) {
+                        if (!nodeInfo.getBidPrice().equals(form.getBidPrice())) {
+                            throw new ServiceException("当前节点已经做过分解或变更,不能修改中标单价");
+                        }
+                    }
+                    if (nodeInfo.getContractTotal() != null) {
+                        if (!nodeInfo.getContractTotal().equals(form.getContractTotal())) {
+                            throw new ServiceException("当前节点已经做过分解或变更,不能修改合同数量");
+                        }
+                    }
+                }
+            }else {
+                form.setContractMoney(null);
+                form.setChangeMoney(null);
+            }
+        }else {
+            //如果不同则判断修改后节点类型是否为清单节点
+            if (form.getIsFormNode() == 1){
+                //为清单节点:判断当前节点是否还有下级节点
+                long count = this.count(new LambdaQueryWrapper<ContractInventoryForm>()
+                        .eq(ContractInventoryForm::getParentId, nodeInfo.getId()));
+                if (count > 0){
+                    throw new ServiceException("当前节点下存在节点,不能修改为清单节点");
+                }
+            }else {
+                //不为清单节点:判断当前节点是否被分解或者被变更,包括零号变更
+                Boolean isChange = this.nodeIsChange(nodeInfo);
+                if (isChange){
+                    throw new ServiceException("当前节点已被分解或变更,不能修改为非清单节点");
+                }
+                form.setContractMoney(null);
+                form.setChangeMoney(null);
+            }
+        }
+        this.updateById(form);
+    }
+
+    /**
+     * 排序 合同工程清单表
+     */
+    @Override
+    public void sort(String ids) {
+        List<Long> longs = Func.toLongList(ids);
+        for (int i = 0; i < longs.size(); i++) {
+            this.update(new LambdaUpdateWrapper<ContractInventoryForm>()
+                .eq(ContractInventoryForm::getId,longs.get(i))
+                .set(ContractInventoryForm::getSort,i));
+        }
+    }
+
+    /**
+     * 删除单个节点 合同工程清单表
+     */
+    @Override
+    public void delete(Long id,Long contractId) {
+        baseMapper.updateNode(id,contractId);
+    }
+
+    /**
+     * 判断当前节点是否已经分解或变更过,变更过返回true
+     */
+    private Boolean nodeIsChange(ContractInventoryForm form) {
+        if (form.getBuildChangeTotal() != null) {
+            return true;
+        }
+        long count = formMeterService.count(new LambdaQueryWrapper<InventoryFormMeter>()
+                .eq(InventoryFormMeter::getContractFormId, form.getId()));
+        if (count > 0) {
+            return true;
+        }
+        long count1 = tokenInventoryService.count(new LambdaQueryWrapper<ChangeTokenInventory>()
+                .eq(ChangeTokenInventory::getContractFormId, form.getId()));
+        if (count1 > 0) {
+            return true;
+        }
+        return false;
+    }
+
+
 }
 }