|
@@ -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) {
|