From c631edf462f4ab19403f5194dec743168e2a0e79 Mon Sep 17 00:00:00 2001
From: shiyunteng <shiyunteng@example.com>
Date: 星期一, 07 九月 2026 14:22:10 +0800
Subject: [PATCH] feat:合并开票

---
 platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ToMergeInvoiceDTO.java                   |   66 ++++
 platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractInvoice.java                  |   11 
 platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractInvoiceServiceImpl.java |  739 ++++++++++++++++++++++++++++++++++++-------------
 platformx-business-finance-biz/src/main/resources/mapper/ContractInvoiceMapper.xml                                        |    5 
 platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/HomeInvoiceVo.java                        |    8 
 platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/GenInvoiceInfoVo.java                     |    2 
 platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractInvoiceQueryDTO.java             |    2 
 platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/GenMergeInvoiceDTO.java                  |   34 ++
 platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractInvoiceController.java    |   27 +
 platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractInvoiceService.java          |    6 
 10 files changed, 700 insertions(+), 200 deletions(-)

diff --git a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractInvoiceQueryDTO.java b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractInvoiceQueryDTO.java
index af41368..83339c0 100644
--- a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractInvoiceQueryDTO.java
+++ b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ContractInvoiceQueryDTO.java
@@ -15,4 +15,6 @@
 	private String invoiceCategory;
 
 	private String bwRequestResult;
+
+	private Boolean isMerge;
 }
diff --git a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/GenMergeInvoiceDTO.java b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/GenMergeInvoiceDTO.java
new file mode 100644
index 0000000..e5e7449
--- /dev/null
+++ b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/GenMergeInvoiceDTO.java
@@ -0,0 +1,34 @@
+package com.by4cloud.platformx.business.dto;
+
+import com.by4cloud.platformx.business.vo.ContractOutBoundInvoiceVo;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class GenMergeInvoiceDTO {
+
+	private List<ContractOutBoundInvoiceVo> outBoundInvoiceList;
+
+	private List<String> contractIds;
+
+	private String contractCategory;
+
+	private String busGuestId;
+
+	private String invoiceType;
+
+	private String vehicleNo;
+
+	private String origin;
+
+	private String tonnage;
+
+	private String passengersLimited;
+
+	private String certificateNo;
+
+	private String vehicleData;
+
+	private String remarks;
+}
diff --git a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ToMergeInvoiceDTO.java b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ToMergeInvoiceDTO.java
new file mode 100644
index 0000000..1f31e66
--- /dev/null
+++ b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/dto/ToMergeInvoiceDTO.java
@@ -0,0 +1,66 @@
+package com.by4cloud.platformx.business.dto;
+
+import com.by4cloud.platformx.business.vo.ContractInvoiceBipVo;
+import com.by4cloud.platformx.business.vo.ContractOutBoundInvoiceVo;
+import com.by4cloud.platformx.business.vo.InvoiceItemVo;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class ToMergeInvoiceDTO {
+
+	@Schema(description = "浜ょ◣鍒嗙被")
+	private String invoiceType;
+
+	@Schema(description = "鏈哄姩杞︿氦绋庡垎绫�")
+	private String invoiceVehicleType;
+
+	@Schema(description = "鐢叉柟鍚嶇О")
+	private String partyA;
+
+	@Schema(description = "鐢叉柟绋庡彿")
+	private String partyAOrgCode;
+
+	@Schema(description = "涔欐柟鍚嶇О")
+	private String partyB;
+
+	@Schema(description = "涔欐柟绋庡彿")
+	private String partyBOrgCode;
+
+	@Schema(description = "鐢叉柟寮�鎴疯")
+	private String partyAOpenBank;
+
+	@Schema(description = "鐢叉柟閾惰璐﹀彿")
+	private String partyABankAccount;
+
+	@Schema(description = "涔欐柟寮�鎴疯")
+	private String partyBOpenBank;
+
+	@Schema(description = "涔欐柟閾惰璐﹀彿")
+	private String partyBBankAccount;
+
+	@Schema(description = "寮�绁ㄩ噾棰濓紙鍚◣锛�")
+	private BigDecimal totalPrice;
+
+	@Schema(description = "绋庨")
+	private BigDecimal totalTax;
+
+	@Schema(description = "澶у啓寮�绁ㄩ噾棰�")
+	private String priceWords;
+
+	private String vehicleData;
+
+	private String remarks;
+
+	private ContractInvoiceBipVo bipVo;
+
+	private List<ContractOutBoundInvoiceVo> outBoundInvoiceList;
+
+	private List<InvoiceItemVo> invoiceItemList;
+
+	private List<String> contractIds;
+
+}
diff --git a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractInvoice.java b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractInvoice.java
index 94df9ef..a5dea23 100644
--- a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractInvoice.java
+++ b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/entity/ContractInvoice.java
@@ -22,7 +22,7 @@
 public class ContractInvoice extends BaseModel<ContractInvoice> {
 
 	@Schema(description = "鍏宠仈鍚堝悓ID")
-	@Column(columnDefinition = "bigint not null comment '鍏宠仈鍚堝悓ID'")
+	@Column(columnDefinition = "bigint comment '鍏宠仈鍚堝悓ID'")
 	private Long contractId;
 
 	@Schema(description = "鍙戠エ绫诲瀷")
@@ -137,4 +137,13 @@
 	@Schema(description = "鍙戠エ鏉ユ簮")
 	@Column(columnDefinition="char default '0' comment '鍙戠エ鏉ユ簮 0/绯荤粺鐢熸垚 1/澶栭儴鑾峰彇'")
 	private String invoiceSource;
+
+	@Schema(description = "鏄惁鍚堝苟寮�绁�")
+	@Column(name = "isMerge",columnDefinition="tinyint(1) default 0 comment '鏄惁鍚堝苟寮�绁� 0/鍚� 1/鏄�'")
+	private Boolean isMerge;
+
+	@Schema(description = "鍚堝苟寮�绁ㄥ悎鍚宨d")
+	@Column(columnDefinition="text  comment '鍚堝苟寮�绁ㄥ悎鍚宨d'")
+	private String contractIds;
+
 }
diff --git a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/GenInvoiceInfoVo.java b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/GenInvoiceInfoVo.java
index a7e25d2..88c0b66 100644
--- a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/GenInvoiceInfoVo.java
+++ b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/GenInvoiceInfoVo.java
@@ -77,5 +77,7 @@
 
 	private ContractInvoiceBipVo bipVo;
 
+	private List<String> contractIds;
+
 	private List<InvoiceItemVo> invoiceItemList;
 }
diff --git a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/HomeInvoiceVo.java b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/HomeInvoiceVo.java
index f96e750..6890685 100644
--- a/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/HomeInvoiceVo.java
+++ b/platformx-business-finance-api/src/main/java/com/by4cloud/platformx/business/vo/HomeInvoiceVo.java
@@ -30,4 +30,12 @@
 	private String bwRequestResult;
 
 	private String invoicePreview;
+
+	private String sellerTaxName;
+
+	private String buyerTaxName;
+
+	private String redReversal;
+
+	private String approvalStatus;
 }
diff --git a/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractInvoiceController.java b/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractInvoiceController.java
index 60b0a37..55b75dd 100644
--- a/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractInvoiceController.java
+++ b/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/controller/ContractInvoiceController.java
@@ -107,6 +107,15 @@
 	}
 
 	/**
+	 * 鑾峰彇鍚堝苟寮�绁ㄥ悎鍚屽嚭搴撲俊鎭�
+	 * @return
+	 */
+	@PostMapping("/getMergeContractOutBound" )
+	public R getMergeContractOutBound(@RequestBody Long[] ids) {
+		return contractInvoiceService.getMergeContractOutBound(ids);
+	}
+
+	/**
 	 * 鐢熸垚寮�绁ㄩ瑙堜俊鎭�
 	 * @return
 	 */
@@ -116,6 +125,24 @@
 	}
 
 	/**
+	 * 鐢熸垚寮�绁ㄩ瑙堜俊鎭�
+	 * @return
+	 */
+	@PostMapping("/genMergeInvoiceInfo" )
+	public R genMergeInvoiceInfo(@RequestBody GenMergeInvoiceDTO mergeInvoiceDTO) {
+		return contractInvoiceService.genMergeInvoiceInfo(mergeInvoiceDTO);
+	}
+
+	/**
+	 * 寮�鍚堝苟钃濈エ
+	 * @return
+	 */
+	@PostMapping("/toMergeInvoice" )
+	public R toMergeInvoice(@RequestBody ToMergeInvoiceDTO toMergeInvoiceDTO) {
+		return contractInvoiceService.toMergeInvoice(toMergeInvoiceDTO);
+	}
+
+	/**
 	 * 寮�钃濈エ
 	 * @return
 	 */
diff --git a/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractInvoiceService.java b/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractInvoiceService.java
index ad6d35b..75a750b 100644
--- a/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractInvoiceService.java
+++ b/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/ContractInvoiceService.java
@@ -47,4 +47,10 @@
 	R selectBipByKey(String dictKey);
 
 	R saveAndPush(ContractInvoiceUpateDTO upateDTO);
+
+	R getMergeContractOutBound(Long[] ids);
+
+	R genMergeInvoiceInfo(GenMergeInvoiceDTO mergeInvoiceDTO);
+
+	R toMergeInvoice(ToMergeInvoiceDTO toMergeInvoiceDTO);
 }
diff --git a/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractInvoiceServiceImpl.java b/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractInvoiceServiceImpl.java
index 7724343..b2dae0a 100644
--- a/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractInvoiceServiceImpl.java
+++ b/platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/ContractInvoiceServiceImpl.java
@@ -129,7 +129,38 @@
 				contractInvoiceOutBoundVo.setToInvoiceNum(contractInvoiceOutBoundVo.getInvoiceNum());
 			});
 		}
-		return R.ok(invoiceOutBoundVoList.stream().filter(item->item.getUnitPrice().compareTo(new BigDecimal("0"))>0).collect(Collectors.toList()));
+		return R.ok(invoiceOutBoundVoList.stream().filter(item -> item.getUnitPrice().compareTo(new BigDecimal("0")) > 0).collect(Collectors.toList()));
+	}
+
+	@Override
+	public R getMergeContractOutBound(Long[] ids) {
+		if (CollUtil.isEmpty(Arrays.asList(ids))) {
+			return R.failed("璇烽�夋嫨鍚堝苟寮�绁ㄧ殑鍚堝悓");
+		}
+		MPJLambdaWrapper<ContractOutBound> wrapper = new MPJLambdaWrapper<ContractOutBound>()
+				.selectAll(ContractOutBound.class)
+				.in(ContractOutBound::getContractId, ids);
+		List<ContractInvoiceOutBoundVo> invoiceOutBoundVoList = contractOutBoundMapper.selectJoinList(ContractInvoiceOutBoundVo.class, wrapper);
+		if (CollUtil.isNotEmpty(invoiceOutBoundVoList)) {
+			invoiceOutBoundVoList.stream().forEach(contractInvoiceOutBoundVo -> {
+
+				contractInvoiceOutBoundVo.setInvoiceNum(contractInvoiceOutBoundVo.getOutBoundNum().subtract(contractInvoiceOutBoundVo.getInvoiceNum()));
+				ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
+						.in(ContractSubjectMatter::getContractId, ids)
+						.eq(ContractSubjectMatter::getMaterialCode, contractInvoiceOutBoundVo.getSubjectMatterCode())
+						.eq(StrUtil.isNotBlank(contractInvoiceOutBoundVo.getLineNo()), ContractSubjectMatter::getLineNo, contractInvoiceOutBoundVo.getLineNo())
+						.last("limit 1"));
+				if (ObjUtil.isNotNull(subjectMatter)) {
+					contractInvoiceOutBoundVo.setUnitPrice(subjectMatter.getUnitPrice());
+					if (subjectMatter.getAdvanceNum().compareTo(new BigDecimal("0")) > 0) {
+						contractInvoiceOutBoundVo.setInvoiceNum(contractInvoiceOutBoundVo.getOutBoundNum().subtract(subjectMatter.getAdvanceNum()));
+					}
+				}
+				contractInvoiceOutBoundVo.setToInvoiceNum(contractInvoiceOutBoundVo.getInvoiceNum());
+			});
+		}
+		return R.ok(invoiceOutBoundVoList.stream().filter(item -> item.getUnitPrice().compareTo(new BigDecimal("0")) > 0).collect(Collectors.toList()));
+
 	}
 
 	@Override
@@ -147,7 +178,7 @@
 				contractInvoiceOutBoundVo.setToInvoiceNum(contractInvoiceOutBoundVo.getInvoiceNum());
 			});
 		}
-		return R.ok(invoiceOutBoundVoList.stream().filter(item->item.getUnitPrice().compareTo(new BigDecimal("0"))>0).collect(Collectors.toList()));
+		return R.ok(invoiceOutBoundVoList.stream().filter(item -> item.getUnitPrice().compareTo(new BigDecimal("0")) > 0).collect(Collectors.toList()));
 	}
 
 	@Override
@@ -165,8 +196,8 @@
 		if (CollUtil.isEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
 			return R.failed("璇烽�夋嫨寮�绁ㄥ嚭搴撳崟鍚庡啀鎿嶄綔");
 		}
-		genInvoiceInfoDTO.setOutBoundInvoiceList(genInvoiceInfoDTO.getOutBoundInvoiceList().stream().filter(item->
-				item.getInvoiceNum().compareTo(new BigDecimal("0"))>0).collect(Collectors.toList()));
+		genInvoiceInfoDTO.setOutBoundInvoiceList(genInvoiceInfoDTO.getOutBoundInvoiceList().stream().filter(item ->
+				item.getInvoiceNum().compareTo(new BigDecimal("0")) > 0).collect(Collectors.toList()));
 		if (CollUtil.isEmpty(genInvoiceInfoDTO.getOutBoundInvoiceList())) {
 			return R.failed("璇烽�夋嫨寮�绁ㄥ嚭搴撳崟鍚庢垨璋冩暣寮�绁ㄦ暟閲忓啀鎿嶄綔");
 		}
@@ -189,7 +220,7 @@
 			}
 			SysDept b = r.getData();
 			BusinessCustomer customer = businessCustomerMapper.selectById(contract.getPartyAId());
-			if (ObjUtil.isNull(customer)){
+			if (ObjUtil.isNull(customer)) {
 				return R.failed("鑾峰彇璐柟鍗曚綅寮傚父");
 			}
 			BigDecimal advanceAmount = new BigDecimal("0");
@@ -205,7 +236,7 @@
 				return R.failed("寮�绁ㄩ噾棰濊秴鍑哄悎鍚岀璁㈤樁娈靛簲鏀堕噾棰�:" + schedule.getPlannedAmount() + ",璇疯皟鏁村紑绁ㄦ暟閲�");
 			}
 			GenInvoiceInfoVo vo = genAdvanceInvoiceInfoVo(genInvoiceInfoDTO, contract, b);
-			vo = transBipVo(vo,b,customer);
+			vo = transBipVo(vo, b, customer);
 			return R.ok(vo);
 		}
 
@@ -227,11 +258,11 @@
 		}
 		SysDept b = r.getData();
 		BusinessCustomer customer = businessCustomerMapper.selectById(contract.getPartyAId());
-		if (ObjUtil.isNull(customer)){
+		if (ObjUtil.isNull(customer)) {
 			return R.failed("鑾峰彇璐柟鍗曚綅寮傚父");
 		}
 		//鏈哄姩杞﹀紑绁�
-		if (StrUtil.equals(genInvoiceInfoDTO.getInvoiceType(), "3") || StrUtil.equals(genInvoiceInfoDTO.getInvoiceType(), "4")) {
+		if (StrUtil.equals(genInvoiceInfoDTO.getInvoiceType(), "4")) {
 			if (StrUtil.isBlank(genInvoiceInfoDTO.getVehicleNo())) {
 				return R.failed("鏈哄姩杞﹀紑绁ㄨ杈撳叆杞︽灦鍙�");
 			}
@@ -245,20 +276,136 @@
 				return r1;
 			}
 			JSONObject request1 = genQueryVehDetailParam(genInvoiceInfoDTO.getVehicleNo(), b);
-			R<JSONObject> r2 = requestQueryVehicleDetail(request1,genInvoiceInfoDTO);
+			R<JSONObject> r2 = requestQueryVehicleDetail(request1, genInvoiceInfoDTO);
 			if (!r2.isOk()) {
 				return r2;
 			}
-			r2.getData().put("contact",b.getOrgContact());
+			r2.getData().put("contact", b.getOrgContact());
 			genInvoiceInfoDTO.setVehicleData(r2.getData().toString());
 		}
 
 		GenInvoiceInfoVo vo = genInvoiceInfoVo(genInvoiceInfoDTO, contract, b);
-		vo = transBipVo(vo,b,customer);
+		vo = transBipVo(vo, b, customer);
 		return R.ok(vo);
 	}
 
-	private GenInvoiceInfoVo transBipVo(GenInvoiceInfoVo vo,SysDept comp,BusinessCustomer customer) {
+	@Override
+	public R genMergeInvoiceInfo(GenMergeInvoiceDTO mergeInvoiceDTO) {
+		R<SysDept> r = remoteDeptService.getById(SecurityUtils.getUser().getCompId());
+		if (!r.isOk()) {
+			return R.failed("鑾峰彇寮�绁ㄥ崟浣嶅紓甯�");
+		}
+		SysDept b = r.getData();
+		BusinessCustomer customer = businessCustomerMapper.selectById(mergeInvoiceDTO.getBusGuestId());
+		if (ObjUtil.isNull(customer)) {
+			return R.failed("鑾峰彇璐柟鍗曚綅寮傚父");
+		}
+
+		GenInvoiceInfoVo vo = genMergeInvoiceVo(mergeInvoiceDTO, customer, b);
+		vo = transBipVo(vo, b, customer);
+		return R.ok(vo);
+	}
+
+	private GenInvoiceInfoVo genMergeInvoiceVo(GenMergeInvoiceDTO mergeInvoiceDTO, BusinessCustomer customer, SysDept b) {
+		GenInvoiceInfoVo vo = new GenInvoiceInfoVo();
+		vo.setPartyA(customer.getCompanyName());
+		vo.setPartyAOrgCode(customer.getCreditCode());
+		vo.setPartyAOpenBank(customer.getBankName());
+		vo.setPartyABankAccount(customer.getBankAccount());
+		vo.setPartyB(b.getOrgName());
+		vo.setPartyBOrgCode(b.getOrgCode());
+		vo.setPartyBOpenBank(b.getOrgBank());
+		vo.setPartyBBankAccount(b.getOrgBankAccount());
+		vo.setInvoiceType(customer.getInvoiceType());
+		vo.setRemarks(mergeInvoiceDTO.getRemarks());
+		vo.setOutBoundInvoiceList(mergeInvoiceDTO.getOutBoundInvoiceList());
+		vo.setContractIds(mergeInvoiceDTO.getContractIds());
+		if (StrUtil.isNotBlank(mergeInvoiceDTO.getInvoiceType())) {
+			vo.setInvoiceVehicleType(mergeInvoiceDTO.getInvoiceType());
+		}
+
+		List<InvoiceItemVo> invoiceItemVoList = new ArrayList<>();
+		List<String> erpCode = new ArrayList<>();
+		List<ContractOutBoundMergeVo> mergeOutBounds = new ArrayList<>();
+
+		if (CollUtil.isNotEmpty(mergeInvoiceDTO.getOutBoundInvoiceList())) {
+			mergeInvoiceDTO.getOutBoundInvoiceList().stream().forEach(contractOutBoundInvoiceVo -> {
+				ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
+				ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
+						.eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
+						.eq(StrUtil.isNotBlank(contractOutBound.getLineNo()), ContractSubjectMatter::getLineNo, contractOutBound.getLineNo())
+						.eq(ContractSubjectMatter::getContractId, contractOutBound.getContractId()).last("limit 1"));
+				if (!CollUtil.contains(erpCode, contractOutBound.getSubjectMatterCode() + subjectMatter.getUnitPrice())) {
+					erpCode.add(contractOutBound.getSubjectMatterCode() + subjectMatter.getUnitPrice());
+					ContractOutBoundMergeVo mergeVo = new ContractOutBoundMergeVo();
+					mergeVo.setMaterialCode(contractOutBound.getSubjectMatterCode() + subjectMatter.getUnitPrice());
+					mergeVo.setMaterialInternalName(contractOutBound.getSubjectMatterName());
+					mergeVo.setQuantity(contractOutBoundInvoiceVo.getInvoiceNum());
+					Product product = new Product();
+					List<String> smjList = new ArrayList<>();
+					smjList.add(smj);
+					smjList.add(smjsc);
+					smjList.add(smjzt);
+					if (("" + SecurityUtils.getUser().getCompId()).equals(smj) || ("" + SecurityUtils.getUser().getCompId()).equals(smjsc) ||
+							("" + SecurityUtils.getUser().getCompId()).equals(smjzt)) {
+						product = productMapper.selectOne(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, contractOutBound.getSubjectMatterCode())
+								.in(Product::getCompId, smjList).last("limit 1"));
+					} else {
+						product = productMapper.selectOne(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, contractOutBound.getSubjectMatterCode())
+								.eq(Product::getCompId, SecurityUtils.getUser().getCompId()).last("limit 1"));
+					}
+
+					if (ObjUtil.isNotNull(product)) {
+						mergeVo.setTaxClass(product.getTaxClass());
+						mergeVo.setSpecification(product.getProductType());
+						mergeVo.setTaxRate(new BigDecimal(product.getTaxRate()));
+						mergeVo.setTaxCode(product.getTaxCode());
+					}
+					if (ObjUtil.isNotNull(subjectMatter)) {
+						mergeVo.setUnitPrice(subjectMatter.getUnitPrice());
+						mergeVo.setUnit(subjectMatter.getUnit());
+						if (StrUtil.equals(product.getErpCode(), "water_bill")) {
+							mergeVo.setItemName("*" + product.getTaxClass() + "*姘磋垂");
+						} else if (StrUtil.equals(product.getErpCode(), "electricity_bill")) {
+							mergeVo.setItemName("*" + product.getTaxClass() + "*鐢佃垂");
+						} else if (StrUtil.equals(product.getErpCode(), "house_rental")) {
+							mergeVo.setItemName("*" + product.getTaxClass() + "*鎴垮眿绉熻祦");
+						} else {
+							mergeVo.setItemName("*" + product.getTaxClass() + "*" + subjectMatter.getMaterialName());
+						}
+					}
+					mergeOutBounds.add(mergeVo);
+				} else {
+					List<ContractOutBoundMergeVo> filteredList = mergeOutBounds.stream()
+							.filter(item -> item.getMaterialCode().equals(subjectMatter.getMaterialCode() + subjectMatter.getUnitPrice())) // 闃叉绌烘寚閽堬紝寤鸿甯搁噺鍦ㄥ墠
+							.collect(Collectors.toList());
+					if (CollUtil.isNotEmpty(filteredList)) {
+						filteredList.get(0).setQuantity(filteredList.get(0).getQuantity().add(contractOutBound.getOutBoundNum()));
+					}
+				}
+			});
+			if (CollUtil.isNotEmpty(mergeOutBounds)) {
+				invoiceItemVoList = BeanUtil.copyToList(mergeOutBounds, InvoiceItemVo.class);
+				invoiceItemVoList.stream().filter(invoiceItem -> invoiceItem.getUnitPrice().compareTo(new BigDecimal("0")) > 0)
+						.forEach(invoiceItemVo -> {
+//				for (InvoiceItemVo invoiceItemVo:invoiceItemVoList) {
+							BigDecimal itemPrice = invoiceItemVo.getUnitPrice().multiply(invoiceItemVo.getQuantity());
+							BigDecimal itemPriceTax = itemPrice.divide(new BigDecimal("100").add(invoiceItemVo.getTaxRate()), 2, RoundingMode.HALF_UP).multiply(invoiceItemVo.getTaxRate());
+							invoiceItemVo.setPriceTax(itemPriceTax);
+							invoiceItemVo.setPriceNoTax(itemPrice.subtract(itemPriceTax));
+							invoiceItemVo.setPriceAndTax(itemPrice);
+						});
+				vo.setTotalPrice(invoiceItemVoList.stream().map(item -> item.getPriceAndTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
+				vo.setTotalTax(invoiceItemVoList.stream().map(item -> item.getPriceTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
+				vo.setInvoiceItemList(invoiceItemVoList);
+				vo.setPriceWords(Convert.digitToChinese(vo.getTotalPrice()));
+			}
+		}
+
+		return vo;
+	}
+
+	private GenInvoiceInfoVo transBipVo(GenInvoiceInfoVo vo, SysDept comp, BusinessCustomer customer) {
 		ContractInvoiceBipVo bipVo = new ContractInvoiceBipVo();
 		bipVo.setDjrq(DateUtil.today());
 		bipVo.setKpzz(comp.getBipCode());
@@ -284,7 +431,7 @@
 		return vo;
 	}
 
-	private R requestQueryVehicleDetail(JSONObject request,GenInvoiceInfoDTO invoiceInfoDTO) {
+	private R requestQueryVehicleDetail(JSONObject request, GenInvoiceInfoDTO invoiceInfoDTO) {
 		String requestId = IdUtil.fastUUID();
 
 		log.info("鏈哄姩杞﹀悎鏍艰瘉鏌ヨ鎺ュ彛鍏ュ弬锛歿},", request.toJSONString());
@@ -300,16 +447,16 @@
 		if (CollUtil.isNotEmpty(models)) {
 			JSONObject model = (JSONObject) models.get(0);
 			if (StrUtil.isNotBlank(invoiceInfoDTO.getOrigin())) {
-				model.put("origin",invoiceInfoDTO.getOrigin());
+				model.put("origin", invoiceInfoDTO.getOrigin());
 			}
 			if (StrUtil.isNotBlank(invoiceInfoDTO.getTonnage())) {
-				model.put("tonnage",invoiceInfoDTO.getTonnage());
+				model.put("tonnage", invoiceInfoDTO.getTonnage());
 			}
 			if (StrUtil.isNotBlank(invoiceInfoDTO.getPassengersLimited())) {
-				model.put("passengersLimited",invoiceInfoDTO.getPassengersLimited());
+				model.put("passengersLimited", invoiceInfoDTO.getPassengersLimited());
 			}
-			model.put("origin",invoiceInfoDTO.getOrigin());
-			model.put("vehicleNo",invoiceInfoDTO.getVehicleNo());
+			model.put("origin", invoiceInfoDTO.getOrigin());
+			model.put("vehicleNo", invoiceInfoDTO.getVehicleNo());
 			return R.ok(model);
 		}
 		return R.failed("鏈哄姩杞﹀悎鏍艰瘉鏌ヨ寮傚父");
@@ -385,6 +532,71 @@
 		List<InvoiceItemVo> invoiceItemVoList = new ArrayList<>();
 		List<String> erpCode = new ArrayList<>();
 		List<ContractOutBoundMergeVo> mergeOutBounds = new ArrayList<>();
+		if (genInvoiceInfoDTO.getInvoiceType().equals("3")){
+			String[] vehiclenNoList = genInvoiceInfoDTO.getVehicleNo().split(",");
+			for (int i = 0; i < vehiclenNoList.length; i++) {
+				ContractOutBound contractOutBound = contractOutBoundMapper.selectById(genInvoiceInfoDTO.getOutBoundInvoiceList().get(0).getContractOutBoundId());
+				ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
+						.eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
+						.eq(StrUtil.isNotBlank(contractOutBound.getLineNo()), ContractSubjectMatter::getLineNo, contractOutBound.getLineNo())
+						.eq(ContractSubjectMatter::getContractId, contract.getId()).last("limit 1"));
+				ContractOutBoundMergeVo mergeVo = new ContractOutBoundMergeVo();
+				mergeVo.setMaterialCode(contractOutBound.getSubjectMatterCode() + subjectMatter.getUnitPrice());
+				mergeVo.setMaterialInternalName(contractOutBound.getSubjectMatterName());
+				mergeVo.setQuantity(new BigDecimal("1"));
+				Product product = new Product();
+				List<String> smjList = new ArrayList<>();
+				smjList.add(smj);
+				smjList.add(smjsc);
+				smjList.add(smjzt);
+				if (("" + SecurityUtils.getUser().getCompId()).equals(smj) || ("" + SecurityUtils.getUser().getCompId()).equals(smjsc) ||
+						("" + SecurityUtils.getUser().getCompId()).equals(smjzt)) {
+					product = productMapper.selectOne(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, contractOutBound.getSubjectMatterCode())
+							.in(Product::getCompId, smjList).last("limit 1"));
+				} else {
+					product = productMapper.selectOne(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, contractOutBound.getSubjectMatterCode())
+							.eq(Product::getCompId, SecurityUtils.getUser().getCompId()).last("limit 1"));
+				}
+
+				if (ObjUtil.isNotNull(product)) {
+					mergeVo.setTaxClass(product.getTaxClass());
+					mergeVo.setSpecification(vehiclenNoList[i]);
+					mergeVo.setTaxRate(new BigDecimal(product.getTaxRate()));
+					mergeVo.setTaxCode(product.getTaxCode());
+				}
+				if (ObjUtil.isNotNull(subjectMatter)) {
+					mergeVo.setUnitPrice(subjectMatter.getUnitPrice());
+					mergeVo.setUnit(subjectMatter.getUnit());
+					if (StrUtil.equals(product.getErpCode(), "water_bill")) {
+						mergeVo.setItemName("*" + product.getTaxClass() + "*姘磋垂");
+					} else if (StrUtil.equals(product.getErpCode(), "electricity_bill")) {
+						mergeVo.setItemName("*" + product.getTaxClass() + "*鐢佃垂");
+					} else if (StrUtil.equals(product.getErpCode(), "house_rental")) {
+						mergeVo.setItemName("*" + product.getTaxClass() + "*鎴垮眿绉熻祦");
+					} else {
+						mergeVo.setItemName("*" + product.getTaxClass() + "*" + subjectMatter.getMaterialName());
+					}
+				}
+				mergeOutBounds.add(mergeVo);
+			}
+			if (CollUtil.isNotEmpty(mergeOutBounds)) {
+				invoiceItemVoList = BeanUtil.copyToList(mergeOutBounds, InvoiceItemVo.class);
+				invoiceItemVoList.stream().filter(invoiceItem -> invoiceItem.getUnitPrice().compareTo(new BigDecimal("0")) > 0)
+						.forEach(invoiceItemVo -> {
+//				for (InvoiceItemVo invoiceItemVo:invoiceItemVoList) {
+							BigDecimal itemPrice = invoiceItemVo.getUnitPrice().multiply(invoiceItemVo.getQuantity());
+							BigDecimal itemPriceTax = itemPrice.divide(new BigDecimal("100").add(invoiceItemVo.getTaxRate()), 2, RoundingMode.HALF_UP).multiply(invoiceItemVo.getTaxRate());
+							invoiceItemVo.setPriceTax(itemPriceTax);
+							invoiceItemVo.setPriceNoTax(itemPrice.subtract(itemPriceTax));
+							invoiceItemVo.setPriceAndTax(itemPrice);
+						});
+				vo.setTotalPrice(invoiceItemVoList.stream().map(item -> item.getPriceAndTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
+				vo.setTotalTax(invoiceItemVoList.stream().map(item -> item.getPriceTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
+				vo.setInvoiceItemList(invoiceItemVoList);
+				vo.setPriceWords(Convert.digitToChinese(vo.getTotalPrice()));
+			}
+			return vo;
+		}
 //		List<ContractOutBound> outBounds = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery()
 //				.in(ContractOutBound::getId, genInvoiceInfoDTO.getOutBoundInvoiceList().stream().map(item->item.getContractOutBoundId()).collect(Collectors.toList())));
 		if (!StrUtil.equals(contract.getContractCategory(), "water_house")) {
@@ -393,12 +605,12 @@
 					ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
 					ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
 							.eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
-							.eq(StrUtil.isNotBlank(contractOutBound.getLineNo()),ContractSubjectMatter::getLineNo,contractOutBound.getLineNo())
+							.eq(StrUtil.isNotBlank(contractOutBound.getLineNo()), ContractSubjectMatter::getLineNo, contractOutBound.getLineNo())
 							.eq(ContractSubjectMatter::getContractId, contract.getId()).last("limit 1"));
-					if (!CollUtil.contains(erpCode, contractOutBound.getSubjectMatterCode()+subjectMatter.getUnitPrice())) {
-						erpCode.add(contractOutBound.getSubjectMatterCode()+subjectMatter.getUnitPrice());
+					if (!CollUtil.contains(erpCode, contractOutBound.getSubjectMatterCode() + subjectMatter.getUnitPrice())) {
+						erpCode.add(contractOutBound.getSubjectMatterCode() + subjectMatter.getUnitPrice());
 						ContractOutBoundMergeVo mergeVo = new ContractOutBoundMergeVo();
-						mergeVo.setMaterialCode(contractOutBound.getSubjectMatterCode()+subjectMatter.getUnitPrice());
+						mergeVo.setMaterialCode(contractOutBound.getSubjectMatterCode() + subjectMatter.getUnitPrice());
 						mergeVo.setMaterialInternalName(contractOutBound.getSubjectMatterName());
 						mergeVo.setQuantity(contractOutBoundInvoiceVo.getInvoiceNum());
 						Product product = new Product();
@@ -406,11 +618,11 @@
 						smjList.add(smj);
 						smjList.add(smjsc);
 						smjList.add(smjzt);
-						if ((""+SecurityUtils.getUser().getCompId()).equals(smj)||(""+SecurityUtils.getUser().getCompId()).equals(smjsc)||
-								(""+SecurityUtils.getUser().getCompId()).equals(smjzt)){
+						if (("" + SecurityUtils.getUser().getCompId()).equals(smj) || ("" + SecurityUtils.getUser().getCompId()).equals(smjsc) ||
+								("" + SecurityUtils.getUser().getCompId()).equals(smjzt)) {
 							product = productMapper.selectOne(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, contractOutBound.getSubjectMatterCode())
 									.in(Product::getCompId, smjList).last("limit 1"));
-						}else {
+						} else {
 							product = productMapper.selectOne(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, contractOutBound.getSubjectMatterCode())
 									.eq(Product::getCompId, SecurityUtils.getUser().getCompId()).last("limit 1"));
 						}
@@ -437,7 +649,7 @@
 						mergeOutBounds.add(mergeVo);
 					} else {
 						List<ContractOutBoundMergeVo> filteredList = mergeOutBounds.stream()
-								.filter(item -> item.getMaterialCode().equals(subjectMatter.getMaterialCode()+subjectMatter.getUnitPrice())) // 闃叉绌烘寚閽堬紝寤鸿甯搁噺鍦ㄥ墠
+								.filter(item -> item.getMaterialCode().equals(subjectMatter.getMaterialCode() + subjectMatter.getUnitPrice())) // 闃叉绌烘寚閽堬紝寤鸿甯搁噺鍦ㄥ墠
 								.collect(Collectors.toList());
 						if (CollUtil.isNotEmpty(filteredList)) {
 							filteredList.get(0).setQuantity(filteredList.get(0).getQuantity().add(contractOutBound.getOutBoundNum()));
@@ -446,15 +658,15 @@
 				});
 				if (CollUtil.isNotEmpty(mergeOutBounds)) {
 					invoiceItemVoList = BeanUtil.copyToList(mergeOutBounds, InvoiceItemVo.class);
-					invoiceItemVoList.stream().filter(invoiceItem->invoiceItem.getUnitPrice().compareTo(new BigDecimal("0"))>0)
+					invoiceItemVoList.stream().filter(invoiceItem -> invoiceItem.getUnitPrice().compareTo(new BigDecimal("0")) > 0)
 							.forEach(invoiceItemVo -> {
 //				for (InvoiceItemVo invoiceItemVo:invoiceItemVoList) {
-						BigDecimal itemPrice = invoiceItemVo.getUnitPrice().multiply(invoiceItemVo.getQuantity());
-						BigDecimal itemPriceTax = itemPrice.divide(new BigDecimal("100").add(invoiceItemVo.getTaxRate()), 2, RoundingMode.HALF_UP).multiply(invoiceItemVo.getTaxRate());
-						invoiceItemVo.setPriceTax(itemPriceTax);
-						invoiceItemVo.setPriceNoTax(itemPrice.subtract(itemPriceTax));
-						invoiceItemVo.setPriceAndTax(itemPrice);
-					});
+								BigDecimal itemPrice = invoiceItemVo.getUnitPrice().multiply(invoiceItemVo.getQuantity());
+								BigDecimal itemPriceTax = itemPrice.divide(new BigDecimal("100").add(invoiceItemVo.getTaxRate()), 2, RoundingMode.HALF_UP).multiply(invoiceItemVo.getTaxRate());
+								invoiceItemVo.setPriceTax(itemPriceTax);
+								invoiceItemVo.setPriceNoTax(itemPrice.subtract(itemPriceTax));
+								invoiceItemVo.setPriceAndTax(itemPrice);
+							});
 					vo.setTotalPrice(invoiceItemVoList.stream().map(item -> item.getPriceAndTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
 					vo.setTotalTax(invoiceItemVoList.stream().map(item -> item.getPriceTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
 					vo.setInvoiceItemList(invoiceItemVoList);
@@ -510,15 +722,15 @@
 				});
 				if (CollUtil.isNotEmpty(mergeOutBounds)) {
 					invoiceItemVoList = BeanUtil.copyToList(mergeOutBounds, InvoiceItemVo.class);
-					invoiceItemVoList.stream().filter(invoiceItem->invoiceItem.getUnitPrice().compareTo(new BigDecimal("0"))>0)
+					invoiceItemVoList.stream().filter(invoiceItem -> invoiceItem.getUnitPrice().compareTo(new BigDecimal("0")) > 0)
 							.forEach(invoiceItemVo -> {
 //				for (InvoiceItemVo invoiceItemVo:invoiceItemVoList) {
-						BigDecimal itemPrice = invoiceItemVo.getPriceAndTax();
-						BigDecimal itemPriceTax = itemPrice.divide(new BigDecimal("100").add(invoiceItemVo.getTaxRate()), 2, RoundingMode.HALF_UP).multiply(invoiceItemVo.getTaxRate());
-						invoiceItemVo.setPriceTax(itemPriceTax);
-						invoiceItemVo.setPriceNoTax(itemPrice.subtract(itemPriceTax));
+								BigDecimal itemPrice = invoiceItemVo.getPriceAndTax();
+								BigDecimal itemPriceTax = itemPrice.divide(new BigDecimal("100").add(invoiceItemVo.getTaxRate()), 2, RoundingMode.HALF_UP).multiply(invoiceItemVo.getTaxRate());
+								invoiceItemVo.setPriceTax(itemPriceTax);
+								invoiceItemVo.setPriceNoTax(itemPrice.subtract(itemPriceTax));
 
-					});
+							});
 					vo.setTotalPrice(invoiceItemVoList.stream().map(item -> item.getPriceAndTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
 					vo.setTotalTax(invoiceItemVoList.stream().map(item -> item.getPriceTax()).reduce(BigDecimal.ZERO, BigDecimal::add));
 					vo.setInvoiceItemList(invoiceItemVoList);
@@ -552,7 +764,7 @@
 			genInvoiceInfoDTO.getOutBoundInvoiceList().stream().forEach(contractOutBoundInvoiceVo -> {
 				ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
 				if (ObjUtil.isNotNull(subjectMatter)) {
-					if (!CollUtil.contains(erpCode, subjectMatter.getMaterialCode()+subjectMatter.getUnitPrice())) {
+					if (!CollUtil.contains(erpCode, subjectMatter.getMaterialCode() + subjectMatter.getUnitPrice())) {
 						erpCode.add(subjectMatter.getMaterialCode());
 						ContractOutBoundMergeVo mergeVo = new ContractOutBoundMergeVo();
 						mergeVo.setMaterialCode(subjectMatter.getMaterialCode());
@@ -589,7 +801,7 @@
 			});
 			if (CollUtil.isNotEmpty(mergeOutBounds)) {
 				invoiceItemVoList = BeanUtil.copyToList(mergeOutBounds, InvoiceItemVo.class);
-				invoiceItemVoList.stream().filter(invoiceItem->invoiceItem.getUnitPrice().compareTo(new BigDecimal("0"))>0).forEach(invoiceItemVo -> {
+				invoiceItemVoList.stream().filter(invoiceItem -> invoiceItem.getUnitPrice().compareTo(new BigDecimal("0")) > 0).forEach(invoiceItemVo -> {
 //				for (InvoiceItemVo invoiceItemVo:invoiceItemVoList) {
 					BigDecimal itemPrice = invoiceItemVo.getUnitPrice().multiply(invoiceItemVo.getQuantity());
 					BigDecimal itemPriceTax = itemPrice.divide(new BigDecimal("100").add(invoiceItemVo.getTaxRate()), 2, RoundingMode.HALF_UP).multiply(invoiceItemVo.getTaxRate());
@@ -642,9 +854,9 @@
 			if (advanceAmount.compareTo(schedule.getPlannedAmount()) > 0) {
 				return R.failed("寮�绁ㄩ噾棰濊秴鍑哄悎鍚岀璁㈤樁娈靛簲鏀堕噾棰�:" + schedule.getPlannedAmount() + ",璇疯皟鏁村紑绁ㄦ暟閲�");
 			}
-			GenInvoiceInfoVo vo = BeanUtil.copyProperties(toInvoiceDTO,GenInvoiceInfoVo.class);
+			GenInvoiceInfoVo vo = BeanUtil.copyProperties(toInvoiceDTO, GenInvoiceInfoVo.class);
 			//鍙戠エ淇濆瓨
-			ContractInvoice invoice = saveContractInvoice(vo, contract, toInvoiceDTO.getOutBoundInvoiceList(), DateUtil.current() + "", "1");
+			ContractInvoice invoice = saveContractInvoice(vo, contract, toInvoiceDTO.getOutBoundInvoiceList(), DateUtil.current() + "", "1",null);
 			//鍚姩娴佺▼
 			ProcessInstanceParamDto dto = new ProcessInstanceParamDto();
 			Map<String, Object> map = BeanUtil.beanToMap(invoice);
@@ -662,9 +874,9 @@
 			});
 			return R.ok();
 		}
-		GenInvoiceInfoVo vo = BeanUtil.copyProperties(toInvoiceDTO,GenInvoiceInfoVo.class);
+		GenInvoiceInfoVo vo = BeanUtil.copyProperties(toInvoiceDTO, GenInvoiceInfoVo.class);
 		//鍙戠エ淇濆瓨
-		ContractInvoice invoice = saveContractInvoice(vo, contract, toInvoiceDTO.getOutBoundInvoiceList(), DateUtil.current() + "", "0");
+		ContractInvoice invoice = saveContractInvoice(vo, contract, toInvoiceDTO.getOutBoundInvoiceList(), DateUtil.current() + "", "0",null);
 		//鍚姩娴佺▼
 		ProcessInstanceParamDto dto = new ProcessInstanceParamDto();
 		Map<String, Object> map = BeanUtil.beanToMap(invoice);
@@ -693,6 +905,32 @@
 				contractPaymentScheduleMapper.updateById(schedule);
 			});
 		}
+		return R.ok();
+	}
+
+	@Override
+	public R toMergeInvoice(ToMergeInvoiceDTO toMergeInvoiceDTO) {
+
+		GenInvoiceInfoVo vo = BeanUtil.copyProperties(toMergeInvoiceDTO, GenInvoiceInfoVo.class);
+		//鍙戠エ淇濆瓨
+		ContractInvoice invoice = saveContractInvoice(vo, null, toMergeInvoiceDTO.getOutBoundInvoiceList(),
+				DateUtil.current() + "", "0", toMergeInvoiceDTO.getContractIds());
+		//鍚姩娴佺▼
+		ProcessInstanceParamDto dto = new ProcessInstanceParamDto();
+		Map<String, Object> map = BeanUtil.beanToMap(invoice);
+		dto.setParamMap(map);
+		dto.setFlowName(FlowNameEnum.閿�鍞寕璐﹀鎵�.name());
+		R r1 = remoteFlowProcessService.startProcessInstance(dto);
+		if (r1.getCode() == 1) {
+			return R.failed("娴佺▼鍚姩澶辫触");
+		}
+		//鏇存柊鍚堝悓鍑哄簱鍗曠姸鎬�
+		toMergeInvoiceDTO.getOutBoundInvoiceList().stream().forEach(contractOutBoundInvoiceVo -> {
+			ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
+			contractOutBound.setInvoiceStatus("1");
+			contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().add(contractOutBoundInvoiceVo.getInvoiceNum()));
+			contractOutBoundMapper.updateById(contractOutBound);
+		});
 		return R.ok();
 	}
 
@@ -755,15 +993,18 @@
 		data.put("invoiceTotalPriceTax", vo.getTotalPrice());
 		data.put("buyerBankName", vo.getPartyAOpenBank());
 		data.put("buyerBankNumber", vo.getPartyABankAccount());
-		data.put("remarks",vo.getRemarks());
+		data.put("remarks", vo.getRemarks());
 		jsonObject.put("data", data);
 		return jsonObject;
 	}
 
 	private ContractInvoice saveContractInvoice(GenInvoiceInfoVo genInvoiceInfoVo, Contract contract,
-												List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList, String serialNo, String advanceFlag) {
+												List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList, String serialNo, String advanceFlag,
+												List<String> contractIds) {
 		ContractInvoice invoice = new ContractInvoice();
-		invoice.setContractId(contract.getId());
+		if (ObjUtil.isNotNull(contract)) {
+			invoice.setContractId(contract.getId());
+		}
 		invoice.setInvoiceCategory("1");
 		invoice.setRedReversal("0");
 		invoice.setSerialNo(serialNo);
@@ -782,6 +1023,10 @@
 				.collect(Collectors.joining(",")));
 		invoice.setInvoicePreviewParam(JSONObject.toJSONString(outBoundInvoiceVoList));
 		invoice.setAdvanceFlag(advanceFlag);
+		if (CollUtil.isNotEmpty(contractIds)) {
+			invoice.setIsMerge(true);
+			invoice.setContractIds(contractIds.toString());
+		}
 		baseMapper.insert(invoice);
 		return invoice;
 	}
@@ -790,6 +1035,8 @@
 	public R getContractInvoiceList(Long contractId) {
 		List<ContractInvoice> invoiceList = baseMapper.selectList(Wrappers.<ContractInvoice>lambdaQuery()
 				.eq(ContractInvoice::getContractId, contractId)
+				.or()
+				.like(ContractInvoice::getContractIds,contractId)
 				.orderByDesc(ContractInvoice::getCreateTime));
 		return R.ok(invoiceList);
 	}
@@ -799,9 +1046,14 @@
 		ContractInvoice blueInvoice = baseMapper.selectById(invoiceId);
 		blueInvoice.setRedReversal("2");
 		baseMapper.updateById(blueInvoice);
-		Contract contract = contractMapper.selectById(blueInvoice.getContractId());
 		ContractInvoice invoice = new ContractInvoice();
-		invoice.setContractId(blueInvoice.getContractId());
+		if (!blueInvoice.getIsMerge()){
+			invoice.setContractId(blueInvoice.getContractId());
+		}
+		if (blueInvoice.getIsMerge()){
+			invoice.setContractIds(blueInvoice.getContractIds());
+			invoice.setIsMerge(true);
+		}
 		invoice.setTaxNo(blueInvoice.getTaxNo());
 		invoice.setSellerTaxName(blueInvoice.getSellerTaxName());
 		invoice.setBuyerTaxName(blueInvoice.getBuyerTaxName());
@@ -810,11 +1062,11 @@
 		invoice.setInvoiceTotalPrice(blueInvoice.getInvoiceTotalPrice());
 		invoice.setInvoiceTotalPriceTax(blueInvoice.getInvoiceTotalPriceTax());
 
-		ToInvoiceDTO toInvoiceDTO = BeanUtil.copyProperties(JSONObject.parseObject(blueInvoice.getInvoicePreview()),ToInvoiceDTO.class);
+		ToInvoiceDTO toInvoiceDTO = BeanUtil.copyProperties(JSONObject.parseObject(blueInvoice.getInvoicePreview()), ToInvoiceDTO.class);
 		toInvoiceDTO.setTotalPrice(toInvoiceDTO.getTotalPrice().multiply(new BigDecimal(-1)));
 		toInvoiceDTO.setTotalTax(toInvoiceDTO.getTotalTax().multiply(new BigDecimal(-1)));
-		if (CollUtil.isNotEmpty(toInvoiceDTO.getInvoiceItemList())){
-			toInvoiceDTO.getInvoiceItemList().stream().forEach(item->{
+		if (CollUtil.isNotEmpty(toInvoiceDTO.getInvoiceItemList())) {
+			toInvoiceDTO.getInvoiceItemList().stream().forEach(item -> {
 				item.setPriceTax(item.getPriceTax().multiply(new BigDecimal("-1")));
 				item.setPriceNoTax(item.getPriceNoTax().multiply(new BigDecimal("-1")));
 				item.setPriceAndTax(item.getPriceAndTax().multiply(new BigDecimal("-1")));
@@ -839,8 +1091,11 @@
 		ProcessInstanceParamDto dto = new ProcessInstanceParamDto();
 		Map<String, Object> map = BeanUtil.beanToMap(invoice);
 		dto.setParamMap(map);
-		if (StrUtil.equals(contract.getContractCategory(), "water_house")) {
-			map.put("contractCategory", "water_house");
+		if (!blueInvoice.getIsMerge()){
+			Contract contract = contractMapper.selectById(blueInvoice.getContractId());
+			if (StrUtil.equals(contract.getContractCategory(), "water_house")) {
+				map.put("contractCategory", "water_house");
+			}
 		}
 		dto.setParamMap(map);
 		dto.setFlowName(FlowNameEnum.閿�鍞寕璐﹀鎵�.name());
@@ -852,7 +1107,7 @@
 		return R.ok();
 	}
 
-	private JSONObject genRedInvoice(Contract contract, ContractInvoice blueInvoice,ContractInvoice redInvoice, String redConfirmSerialNo) {
+	private JSONObject genRedInvoice(ContractInvoice blueInvoice, ContractInvoice redInvoice, String redConfirmSerialNo) {
 		JSONObject jsonObject = new JSONObject();
 		jsonObject.put("taxNo", redInvoice.getTaxNo());
 		jsonObject.put("redConfirmSerialNo", redConfirmSerialNo);
@@ -886,7 +1141,7 @@
 //			invoiceDetail.put("goodsPrice", invoiceItemVo.getUnitPrice());
 			invoiceDetail.put("goodsTotalPrice", invoiceItemVo.getPriceNoTax());
 			invoiceDetail.put("goodsTotalTax", invoiceItemVo.getPriceTax());
-			if (vo.getInvoiceVehicleType().equals("3")||vo.getInvoiceVehicleType().equals("4")){
+			if (StrUtil.isNotBlank(vo.getInvoiceVehicleType())&&(vo.getInvoiceVehicleType().equals("3") || vo.getInvoiceVehicleType().equals("4"))) {
 				invoiceDetail.put("goodsSpecification", invoiceItemVo.getSpecification());
 			}
 			invoiceDetailsList.add(invoiceDetail);
@@ -934,7 +1189,7 @@
 		return R.ok();
 	}
 
-	private void pushBipInvoicePdf(ContractInvoice contractInvoice){
+	private void pushBipInvoicePdf(ContractInvoice contractInvoice) {
 		String accessToken = "";
 		if (redisTemplate.hasKey("BIP_TOKEN")) {
 			accessToken = (String) redisTemplate.opsForValue().get("BIP_TOKEN");
@@ -1162,67 +1417,67 @@
 		JSONArray bodyItem = new JSONArray();
 		for (InvoiceItemVo invoiceItemVo : vo.getBipVo().getItemList()) {
 			JSONObject item = new JSONObject();
-			item.put("expenseItemCode",invoiceItemVo.getJjsx());//缁忔祹浜嬮」
+			item.put("expenseItemCode", invoiceItemVo.getJjsx());//缁忔祹浜嬮」
 			item.put("invoiceNo", contractInvoice.getInvoiceNo());
 			item.put("taxRate", invoiceItemVo.getTaxRate());
 			item.put("oriTaxAmount", invoiceItemVo.getPriceTax());
 			item.put("oriTaxIncludedAmount", invoiceItemVo.getPriceAndTax());
 			item.put("_status", "Insert");
 			JSONObject freeChId = new JSONObject();
-			freeChId.put("GX08",invoiceItemVo.getHsdy());//鏍哥畻鍗曞厓
-			freeChId.put("YSYF31",invoiceItemVo.getSfjs());//鏄惁璁$◣
-			freeChId.put("JT04",invoiceItemVo.getHsjylx());//鏍哥畻浜ゆ槗绫诲瀷 0101 闆嗗洟澶栭儴 01020301 涓夌骇鍒嗗瓙鍏徃闂� 01020302 涓夌骇鍒嗗叕鍙镐笌瀛愬瓙鍏徃涔嬮棿
-			freeChId.put("JT06",invoiceItemVo.getKxmx());//娆鹃」鏄庣粏
-			freeChId.put("JT32",invoiceItemVo.getZyys());//浣滀笟瑕佺礌
-			freeChId.put("zzbkfl",invoiceItemVo.getBkfl());//鏉垮潡鍒嗙被
-			freeChId.put("JT12",invoiceItemVo.getCpwlfl());//浜у搧鐗╂枡鍒嗙被
-			item.put("freeChId",freeChId);
+			freeChId.put("GX08", invoiceItemVo.getHsdy());//鏍哥畻鍗曞厓
+			freeChId.put("YSYF31", invoiceItemVo.getSfjs());//鏄惁璁$◣
+			freeChId.put("JT04", invoiceItemVo.getHsjylx());//鏍哥畻浜ゆ槗绫诲瀷 0101 闆嗗洟澶栭儴 01020301 涓夌骇鍒嗗瓙鍏徃闂� 01020302 涓夌骇鍒嗗叕鍙镐笌瀛愬瓙鍏徃涔嬮棿
+			freeChId.put("JT06", invoiceItemVo.getKxmx());//娆鹃」鏄庣粏
+			freeChId.put("JT32", invoiceItemVo.getZyys());//浣滀笟瑕佺礌
+			freeChId.put("zzbkfl", invoiceItemVo.getBkfl());//鏉垮潡鍒嗙被
+			freeChId.put("JT12", invoiceItemVo.getCpwlfl());//浜у搧鐗╂枡鍒嗙被
+			item.put("freeChId", freeChId);
 			bodyItem.add(item);
 		}
 		data.put("bodyItem", bodyItem);
 		JSONObject freeChId = new JSONObject();
-		freeChId.put("YSYF_SFZY",vo.getBipVo().getSfzy());//鏄惁涓昏惀
-		freeChId.put("fk_038",vo.getBipVo().getPzzdr());//鍑瘉鍒跺崟浜�
-		freeChId.put("YSYF_08",vo.getBipVo().getSfnbwl());//鏄惁鍐呴儴寰�鏉�
-		freeChId.put("YSYF24",vo.getBipVo().getSfjyjs());//鏄惁绠�鏄撹绋�
-		freeChId.put("fk_002",vo.getBipVo().getFjzs());//闄勪欢1
-		freeChId.put("GX08",vo.getBipVo().getHsdy());//鏍哥畻鍗曞厓
-		freeChId.put("TzMY042",contract.getExpirationDate());//棰勮鍥炴鏃ユ湡
+		freeChId.put("YSYF_SFZY", vo.getBipVo().getSfzy());//鏄惁涓昏惀
+		freeChId.put("fk_038", vo.getBipVo().getPzzdr());//鍑瘉鍒跺崟浜�
+		freeChId.put("YSYF_08", vo.getBipVo().getSfnbwl());//鏄惁鍐呴儴寰�鏉�
+		freeChId.put("YSYF24", vo.getBipVo().getSfjyjs());//鏄惁绠�鏄撹绋�
+		freeChId.put("fk_002", vo.getBipVo().getFjzs());//闄勪欢1
+		freeChId.put("GX08", vo.getBipVo().getHsdy());//鏍哥畻鍗曞厓
+		freeChId.put("TzMY042", contract.getExpirationDate());//棰勮鍥炴鏃ユ湡
 		data.put("freeChId", freeChId);
-		data.put("remarks",vo.getBipVo().getZy());//鎽樿
+		data.put("remarks", vo.getBipVo().getZy());//鎽樿
 		jsonObject.put("data", data);
 		return jsonObject;
 	}
 
 	private String transEconomic(String economicMatters) {
-		if (economicMatters.equals("1")){
+		if (economicMatters.equals("1")) {
 			return "09001006";
 		}
-		if (economicMatters.equals("2")){
+		if (economicMatters.equals("2")) {
 			return "09004003";
 		}
-		if (economicMatters.equals("3")){
+		if (economicMatters.equals("3")) {
 			return "09003005";
 		}
-		if (economicMatters.equals("4")){
+		if (economicMatters.equals("4")) {
 			return "09002042";
 		}
-		if (economicMatters.equals("5")){
+		if (economicMatters.equals("5")) {
 			return "09002002";
 		}
-		if (economicMatters.equals("6")){
+		if (economicMatters.equals("6")) {
 			return "09004001";
 		}
-		if (economicMatters.equals("7")){
+		if (economicMatters.equals("7")) {
 			return "09003002001";
 		}
-		if (economicMatters.equals("8")){
+		if (economicMatters.equals("8")) {
 			return "09003002002";
 		}
-		if (economicMatters.equals("9")){
+		if (economicMatters.equals("9")) {
 			return "09003002003";
 		}
-		if (economicMatters.equals("10")){
+		if (economicMatters.equals("10")) {
 			return "09003003";
 		}
 		return "";
@@ -1282,9 +1537,9 @@
 			return;
 		}
 		SysDept dept = r.getData();
-		Contract contract = contractMapper.selectById(invoice.getContractId());
+
 		GenInvoiceInfoVo vo = BeanUtil.copyProperties(JSONObject.parseObject(invoice.getInvoicePreview()), GenInvoiceInfoVo.class);
-		vo.setContractCategory(contract.getContractCategory());
+
 		invoice.setApprovalStatus("1");
 		baseMapper.updateById(invoice);
 		invoice.setBwRequestResult("0");
@@ -1292,7 +1547,7 @@
 		//钃濈エ
 		if (invoice.getInvoiceCategory().equals("1")) {
 			// TODO 寮�钃濈エ鎺ュ彛鏈哄姩杞﹂攢鍞�
-			if (StrUtil.equals(vo.getInvoiceVehicleType(), "4")) {
+			if (StrUtil.equals(vo.getInvoiceVehicleType(), "4")&&bwFlag) {
 				JSONObject request = genBlueInvoiceVehicle(vo, invoice.getSerialNo(), dept);
 				String requestId = IdUtil.fastUUID();
 				invoice.setBwRequestId(requestId);
@@ -1318,7 +1573,7 @@
 			}
 
 			// TODO 寮�钃濈エ鎺ュ彛鏈哄姩杞︿笓鐢�
-			if (StrUtil.equals(vo.getInvoiceVehicleType(), "3")) {
+			if (StrUtil.equals(vo.getInvoiceVehicleType(), "3")&&bwFlag) {
 				JSONObject request = genBlueInvoiceVehiclePre(vo, invoice.getSerialNo(), dept);
 				String requestId = IdUtil.fastUUID();
 				invoice.setBwRequestId(requestId);
@@ -1344,7 +1599,7 @@
 			}
 
 			// TODO 寮�钃濈エ鎺ュ彛 闈炴満鍔ㄨ溅
-			if (!StrUtil.equals(vo.getInvoiceVehicleType(), "3")&&!StrUtil.equals(vo.getInvoiceVehicleType(), "4")) {
+			if (!StrUtil.equals(vo.getInvoiceVehicleType(), "3") && !StrUtil.equals(vo.getInvoiceVehicleType(), "4")&&bwFlag) {
 				JSONObject request = genBlueInvoice(vo, invoice.getSerialNo(), dept);
 				String requestId = IdUtil.fastUUID();
 				invoice.setBwRequestId(requestId);
@@ -1372,83 +1627,129 @@
 					}
 				}
 			}
-			if (StrUtil.isNotBlank(vo.getAdvanceInvoice())) {
-				contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
-				contractMapper.updateById(contract);
-				return;
-			}
-			if (!StrUtil.equals(contract.getContractCategory(), "water_house")) {
-				//鍚堝悓鐘舵��
-				contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
-				if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
-					contract.setBillingStatus("3");
+			//闈炲悎骞跺紑绁�
+			if (!invoice.getIsMerge()) {
+				Contract contract = contractMapper.selectById(invoice.getContractId());
+				vo.setContractCategory(contract.getContractCategory());
+				if (StrUtil.isNotBlank(vo.getAdvanceInvoice())) {
+					contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
+					contractMapper.updateById(contract);
+					return;
 				}
-				if (contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0&&
-						contract.getBillingAmout().compareTo(contract.getAmount()) == 0){
-					contract.setContractStatus(3);
-				}
-				if (contract.getBillingAmout().compareTo(contract.getAmount()) < 0) {
-					contract.setBillingStatus("1");
-					List<ContractOutBound> outBoundList = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery()
-							.eq(ContractOutBound::getContractId, contract.getId())
-							.apply("invoice_num < out_bound_num"));
-					if (CollUtil.isNotEmpty(outBoundList)) {
-						contract.setBillingStatus("2");
-					}
-
-				}
-				//闃叉閲嶅瀹″紑绁ㄥ鏍搁�氳繃鍚� 寮�绁ㄩ噾棰濊秴鍑哄悎鍚岄噾棰�
-				if (contract.getBillingAmout().compareTo(contract.getAmount()) > 0) {
-					contract.setBillingAmout(contract.getAmount());
-				}
-				contractMapper.updateById(contract);
-
-			} else {
-				//鍒ゆ柇 寰幆鏄惁瀹屾垚
-				List<ContractExecDate> execDateList = contractExecDateMapper.selectList(Wrappers.<ContractExecDate>lambdaQuery().eq(ContractExecDate::getContractId, contract.getId())
-						.eq(ContractExecDate::getGenFlag, "0"));
-				if (CollUtil.isEmpty(execDateList)) {
-					//鍒ゆ柇鏄惁鏈夊彲寮�绁ㄨ褰�
-					List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
-							.eq(ContractPaymentSchedule::getContractId, contract.getId()).eq(ContractPaymentSchedule::getInvoiceFlag, "0"));
-					if (CollUtil.isEmpty(scheduleList)) {
-						contract.setBillingStatus("3");
-					} else {
-						contract.setBillingStatus("2");
-					}
+				if (!StrUtil.equals(contract.getContractCategory(), "water_house")) {
+					//鍚堝悓鐘舵��
 					contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
 					if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
 						contract.setBillingStatus("3");
 					}
-					if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0 &&
-							contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0) {
-						contract.setBillingStatus("3");
+					if (contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0 &&
+							contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
 						contract.setContractStatus(3);
+					}
+					if (contract.getBillingAmout().compareTo(contract.getAmount()) < 0) {
+						contract.setBillingStatus("1");
+						List<ContractOutBound> outBoundList = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery()
+								.eq(ContractOutBound::getContractId, contract.getId())
+								.apply("invoice_num < out_bound_num"));
+						if (CollUtil.isNotEmpty(outBoundList)) {
+							contract.setBillingStatus("2");
+						}
+
 					}
 					//闃叉閲嶅瀹″紑绁ㄥ鏍搁�氳繃鍚� 寮�绁ㄩ噾棰濊秴鍑哄悎鍚岄噾棰�
 					if (contract.getBillingAmout().compareTo(contract.getAmount()) > 0) {
 						contract.setBillingAmout(contract.getAmount());
 					}
+					contractMapper.updateById(contract);
+
 				} else {
-					//鍒ゆ柇鏄惁鏈夊彲寮�绁ㄨ褰�
-					List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
-							.eq(ContractPaymentSchedule::getContractId, contract.getId()));
-					if (CollUtil.isEmpty(scheduleList)) {
-						contract.setBillingStatus("1");
+					//鍒ゆ柇 寰幆鏄惁瀹屾垚
+					List<ContractExecDate> execDateList = contractExecDateMapper.selectList(Wrappers.<ContractExecDate>lambdaQuery().eq(ContractExecDate::getContractId, contract.getId())
+							.eq(ContractExecDate::getGenFlag, "0"));
+					if (CollUtil.isEmpty(execDateList)) {
+						//鍒ゆ柇鏄惁鏈夊彲寮�绁ㄨ褰�
+						List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
+								.eq(ContractPaymentSchedule::getContractId, contract.getId()).eq(ContractPaymentSchedule::getInvoiceFlag, "0"));
+						if (CollUtil.isEmpty(scheduleList)) {
+							contract.setBillingStatus("3");
+						} else {
+							contract.setBillingStatus("2");
+						}
+						contract.setBillingAmout(vo.getTotalPrice().add(contract.getBillingAmout()));
+						if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
+							contract.setBillingStatus("3");
+						}
+						if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0 &&
+								contract.getPaidAmount().compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0) {
+							contract.setBillingStatus("3");
+							contract.setContractStatus(3);
+						}
+						//闃叉閲嶅瀹″紑绁ㄥ鏍搁�氳繃鍚� 寮�绁ㄩ噾棰濊秴鍑哄悎鍚岄噾棰�
+						if (contract.getBillingAmout().compareTo(contract.getAmount()) > 0) {
+							contract.setBillingAmout(contract.getAmount());
+						}
 					} else {
-						contract.setBillingStatus("2");
+						//鍒ゆ柇鏄惁鏈夊彲寮�绁ㄨ褰�
+						List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
+								.eq(ContractPaymentSchedule::getContractId, contract.getId()));
+						if (CollUtil.isEmpty(scheduleList)) {
+							contract.setBillingStatus("1");
+						} else {
+							contract.setBillingStatus("2");
+						}
+					}
+
+					contractMapper.updateById(contract);
+				}
+				baseMapper.updateById(invoice);
+				return;
+			} else {
+				//鍚堝苟寮�绁�
+				List<String> result = Arrays.stream(invoice.getContractIds().replace("[", "").replace("]", "").split(","))
+						.map(String::trim)
+						.filter(s -> !s.isEmpty())
+						.collect(Collectors.toList());
+				if (CollUtil.isNotEmpty(result)) {
+					for (String cid : result) {
+						Contract contract = contractMapper.selectById(cid);
+						BigDecimal contractBillAmount = new BigDecimal("0");
+						if (CollUtil.isNotEmpty(vo.getOutBoundInvoiceList())) {
+							for (ContractOutBoundInvoiceVo outBoundInvoiceVo : vo.getOutBoundInvoiceList()) {
+								ContractOutBound contractOutBound = contractOutBoundMapper.selectById(outBoundInvoiceVo.getContractOutBoundId());
+								if (ObjUtil.isNotNull(contractOutBound) && contractOutBound.getContractId().equals(contract.getId())) {
+									ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
+											.eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
+											.eq(StrUtil.isNotBlank(contractOutBound.getLineNo()), ContractSubjectMatter::getLineNo, contractOutBound.getLineNo())
+											.eq(ContractSubjectMatter::getContractId, contract.getId()).last("limit 1"));
+									if (ObjUtil.isNotNull(subjectMatter) && ObjUtil.isNotNull(subjectMatter.getUnitPrice())) {
+										contractBillAmount = contractBillAmount.add(outBoundInvoiceVo.getInvoiceNum().multiply(subjectMatter.getUnitPrice()));
+
+									}
+								}
+							}
+						}
+						contract.setBillingAmout(contract.getBillingAmout().add(contractBillAmount));
+						contract.setBillingStatus("1");
+						List<ContractOutBound> outBoundList = contractOutBoundMapper.selectList(Wrappers.<ContractOutBound>lambdaQuery()
+								.eq(ContractOutBound::getContractId, contract.getId())
+								.apply("invoice_num < out_bound_num"));
+						if (CollUtil.isNotEmpty(outBoundList)) {
+							contract.setBillingStatus("2");
+						}
+						if (contract.getBillingAmout().compareTo(contract.getAmount()) == 0) {
+							contract.setBillingStatus("3");
+						}
+						contractMapper.updateById(contract);
 					}
 				}
-
-				contractMapper.updateById(contract);
 			}
-			baseMapper.updateById(invoice);
+
 		}
 		//绾㈢エ
 		if (invoice.getInvoiceCategory().equals("2")) {
 			// TODO 寮�绾㈢エ鎺ュ彛
 			ContractInvoice blueInvoice = baseMapper.selectById(invoice.getBlueInvoiceId());
-			JSONObject request = genRedInvoice(contract,blueInvoice, invoice, invoice.getSerialNo());
+			JSONObject request = genRedInvoice(blueInvoice, invoice, invoice.getSerialNo());
 			String requestId = IdUtil.fastUUID();
 			invoice.setBwRequestId(requestId);
 			invoice.setBwRequestParam(request.toJSONString());
@@ -1480,58 +1781,100 @@
 					}
 				}
 			}
-			baseMapper.updateById(invoice);
-			contract.setBillingAmout(contract.getBillingAmout().add(invoice.getInvoiceTotalPriceTax()));
-			//闃叉閲嶅瀹″紑绁ㄥ鏍搁�氳繃鍚� 寮�绁ㄩ噾棰濅负璐�
-			if (contract.getBillingAmout().compareTo(new BigDecimal("0")) < 0) {
-				contract.setBillingAmout(new BigDecimal("0"));
-			}
-			contractMapper.updateById(contract);
-			blueInvoice.setRedReversal("1");
-			baseMapper.updateById(blueInvoice);
-			if (StrUtil.isNotBlank(vo.getAdvanceInvoice())) {
-				//杩樺師棰勫紑鏁伴噺
-				List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList = BeanUtil.copyToList(JSONArray.parseArray(blueInvoice.getInvoicePreviewParam()), ContractOutBoundInvoiceVo.class);
-				if (CollUtil.isNotEmpty(outBoundInvoiceVoList)) {
-					outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
-						ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
-						if (ObjUtil.isNotNull(subjectMatter)) {
-							subjectMatter.setAdvanceNum(subjectMatter.getAdvanceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
-							if (subjectMatter.getAdvanceNum().compareTo(new BigDecimal("0")) <= 0) {
-								subjectMatter.setAdvanceNum(new BigDecimal("0"));
+			if (!invoice.getIsMerge()) {
+				Contract contract = contractMapper.selectById(invoice.getContractId());
+				baseMapper.updateById(invoice);
+				contract.setBillingAmout(contract.getBillingAmout().add(invoice.getInvoiceTotalPriceTax()));
+				//闃叉閲嶅瀹″紑绁ㄥ鏍搁�氳繃鍚� 寮�绁ㄩ噾棰濅负璐�
+				if (contract.getBillingAmout().compareTo(new BigDecimal("0")) < 0) {
+					contract.setBillingAmout(new BigDecimal("0"));
+				}
+				contractMapper.updateById(contract);
+				blueInvoice.setRedReversal("1");
+				baseMapper.updateById(blueInvoice);
+				if (StrUtil.isNotBlank(vo.getAdvanceInvoice())) {
+					//杩樺師棰勫紑鏁伴噺
+					List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList = BeanUtil.copyToList(JSONArray.parseArray(blueInvoice.getInvoicePreviewParam()), ContractOutBoundInvoiceVo.class);
+					if (CollUtil.isNotEmpty(outBoundInvoiceVoList)) {
+						outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
+							ContractSubjectMatter subjectMatter = contractSubjectMatterMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
+							if (ObjUtil.isNotNull(subjectMatter)) {
+								subjectMatter.setAdvanceNum(subjectMatter.getAdvanceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
+								if (subjectMatter.getAdvanceNum().compareTo(new BigDecimal("0")) <= 0) {
+									subjectMatter.setAdvanceNum(new BigDecimal("0"));
+								}
+								contractSubjectMatterMapper.updateById(subjectMatter);
 							}
-							contractSubjectMatterMapper.updateById(subjectMatter);
+						});
+					}
+					return;
+				}
+				//鏇存柊鍚堝悓寮�绁ㄧ姸鎬� 鍓嶆彁鍑哄簱瀹屾垚
+				contract.setBillingStatus("2");
+				contractMapper.updateById(contract);
+				if (!StrUtil.equals(contract.getContractCategory(), "water_house")) {
+					//鏇存柊鍚堝悓鍑哄簱鍗曠姸鎬�
+					List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList = BeanUtil.copyToList(JSONArray.parseArray(blueInvoice.getInvoicePreviewParam()), ContractOutBoundInvoiceVo.class);
+					if (CollUtil.isNotEmpty(outBoundInvoiceVoList)) {
+						outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
+							ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
+							contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
+							contractOutBoundMapper.updateById(contractOutBound);
+						});
+					}
+				} else {
+					//鏇存柊鍚堝悓鎴跨 姘寸數 璐瑰紑绁ㄧ姸鎬�
+					List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList = BeanUtil.copyToList(JSONArray.parseArray(blueInvoice.getInvoicePreviewParam()), ContractOutBoundInvoiceVo.class);
+					if (CollUtil.isNotEmpty(outBoundInvoiceVoList)) {
+						outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
+							ContractPaymentSchedule schedule = contractPaymentScheduleMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
+							schedule.setInvoiceFlag("0");
+							contractPaymentScheduleMapper.updateById(schedule);
+						});
+					}
+				}
+			}else {
+				blueInvoice.setRedReversal("1");
+				baseMapper.updateById(blueInvoice);
+				//鍚堝苟寮�绁�
+				List<String> result = Arrays.stream(invoice.getContractIds().replace("[", "").replace("]", "").split(","))
+						.map(String::trim)
+						.filter(s -> !s.isEmpty())
+						.collect(Collectors.toList());
+				if (CollUtil.isNotEmpty(result)) {
+					for (String cid : result) {
+						Contract contract = contractMapper.selectById(cid);
+						if (CollUtil.isNotEmpty(vo.getOutBoundInvoiceList())) {
+							for (ContractOutBoundInvoiceVo outBoundInvoiceVo : vo.getOutBoundInvoiceList()) {
+								BigDecimal contractBillAmount = new BigDecimal("0");
+								if (CollUtil.isNotEmpty(vo.getOutBoundInvoiceList())) {
+										ContractOutBound contractOutBound = contractOutBoundMapper.selectById(outBoundInvoiceVo.getContractOutBoundId());
+										if (ObjUtil.isNotNull(contractOutBound) && contractOutBound.getContractId().equals(contract.getId())) {
+											ContractSubjectMatter subjectMatter = subjectMatterMapper.selectOne(Wrappers.<ContractSubjectMatter>lambdaQuery()
+													.eq(ContractSubjectMatter::getMaterialCode, contractOutBound.getSubjectMatterCode())
+													.eq(StrUtil.isNotBlank(contractOutBound.getLineNo()), ContractSubjectMatter::getLineNo, contractOutBound.getLineNo())
+													.eq(ContractSubjectMatter::getContractId, contract.getId()).last("limit 1"));
+											if (ObjUtil.isNotNull(subjectMatter) && ObjUtil.isNotNull(subjectMatter.getUnitPrice())) {
+												contractBillAmount = contractBillAmount.add(outBoundInvoiceVo.getInvoiceNum().multiply(subjectMatter.getUnitPrice()));
+											}
+											contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().subtract(outBoundInvoiceVo.getInvoiceNum()));
+											contractOutBoundMapper.updateById(contractOutBound);
+										}
+								}
+								//鏇存柊鍚堝悓寮�绁ㄧ姸鎬� 鍓嶆彁鍑哄簱瀹屾垚
+								contract.setBillingStatus("2");
+								contract.setBillingAmout(contract.getBillingAmout().add(invoice.getInvoiceTotalPriceTax()));
+								//闃叉閲嶅瀹″紑绁ㄥ鏍搁�氳繃鍚� 寮�绁ㄩ噾棰濅负璐�
+								if (contract.getBillingAmout().compareTo(new BigDecimal("0")) < 0) {
+									contract.setBillingAmout(new BigDecimal("0"));
+								}
+								contractMapper.updateById(contract);
+							}
 						}
-					});
-				}
-				return;
-			}
-			//鏇存柊鍚堝悓寮�绁ㄧ姸鎬� 鍓嶆彁鍑哄簱瀹屾垚
-			contract.setBillingStatus("2");
-			contractMapper.updateById(contract);
-			if (!StrUtil.equals(contract.getContractCategory(), "water_house")) {
-				//鏇存柊鍚堝悓鍑哄簱鍗曠姸鎬�
-				List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList = BeanUtil.copyToList(JSONArray.parseArray(blueInvoice.getInvoicePreviewParam()), ContractOutBoundInvoiceVo.class);
-				if (CollUtil.isNotEmpty(outBoundInvoiceVoList)) {
-					outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
-						ContractOutBound contractOutBound = contractOutBoundMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
-						contractOutBound.setInvoiceNum(contractOutBound.getInvoiceNum().subtract(contractOutBoundInvoiceVo.getInvoiceNum()));
-						contractOutBoundMapper.updateById(contractOutBound);
-					});
-				}
-			} else {
-				//鏇存柊鍚堝悓鎴跨 姘寸數 璐瑰紑绁ㄧ姸鎬�
-				List<ContractOutBoundInvoiceVo> outBoundInvoiceVoList = BeanUtil.copyToList(JSONArray.parseArray(blueInvoice.getInvoicePreviewParam()), ContractOutBoundInvoiceVo.class);
-				if (CollUtil.isNotEmpty(outBoundInvoiceVoList)) {
-					outBoundInvoiceVoList.stream().forEach(contractOutBoundInvoiceVo -> {
-						ContractPaymentSchedule schedule = contractPaymentScheduleMapper.selectById(contractOutBoundInvoiceVo.getContractOutBoundId());
-						schedule.setInvoiceFlag("0");
-						contractPaymentScheduleMapper.updateById(schedule);
-					});
+					}
 				}
 			}
 		}
-
 	}
 
 	private JSONObject genBlueInvoiceVehiclePre(GenInvoiceInfoVo vo, String serialNo, SysDept dept) {
@@ -1549,7 +1892,7 @@
 		data.put("invoiceTypeCode", "01");
 		data.put("invoiceType", "0");
 		data.put("serialNo", serialNo);
-		data.put("invoiceSpecialMark","14");//鐗瑰畾涓氬姟鏍囪瘑	14-鏈哄姩杞�
+		data.put("invoiceSpecialMark", "14");//鐗瑰畾涓氬姟鏍囪瘑	14-鏈哄姩杞�
 //		data.put("taxationMethod","2");
 //		data.put("taxationLabel","02");//鍙戠エ绫诲瀷浠g爜涓衡��01-鏁扮數鍙戠エ锛堝鍊肩◣涓撶敤鍙戠エ锛夈��02-鏁扮數鍙戠エ锛堟櫘閫氬彂绁級鈥濇椂涓斿緛绋庢柟寮忎负鈥�2-宸寰佺◣鈥濇椂蹇呭~
 		List<JSONObject> invoiceDetailsList = new ArrayList<>();
@@ -1937,8 +2280,8 @@
 
 	@Override
 	public R selectBipByKey(String dictKey) {
-		List<BipDict> bipDictList = bipDictMapper.selectList(Wrappers.<BipDict>lambdaQuery().eq(BipDict::getDictKey,dictKey));
-		if (CollUtil.isNotEmpty(bipDictList)){
+		List<BipDict> bipDictList = bipDictMapper.selectList(Wrappers.<BipDict>lambdaQuery().eq(BipDict::getDictKey, dictKey));
+		if (CollUtil.isNotEmpty(bipDictList)) {
 			// 鏉冮檺鍐呴儴闂�
 			List<TreeNode<Long>> collect = bipDictList.stream()
 					.map(dict -> {
@@ -1951,7 +2294,7 @@
 					})
 					.collect(Collectors.toList());
 
-			return R.ok(TreeUtil.build(collect,0L));
+			return R.ok(TreeUtil.build(collect, 0L));
 		}
 		return R.failed("瀛楀吀鑾峰彇澶辫触");
 	}
@@ -1962,7 +2305,7 @@
 		invoice.setInvoicePreview(upateDTO.getInvoicePreview());
 		baseMapper.updateById(invoice);
 		R r = bipPush(invoice.getId());
-		if (!r.isOk()){
+		if (!r.isOk()) {
 			return r;
 		}
 		return bipPushPdf(invoice.getId());
diff --git a/platformx-business-finance-biz/src/main/resources/mapper/ContractInvoiceMapper.xml b/platformx-business-finance-biz/src/main/resources/mapper/ContractInvoiceMapper.xml
index 4dc90be..78dcce9 100644
--- a/platformx-business-finance-biz/src/main/resources/mapper/ContractInvoiceMapper.xml
+++ b/platformx-business-finance-biz/src/main/resources/mapper/ContractInvoiceMapper.xml
@@ -468,6 +468,9 @@
 		<if test="queryDTO.invoiceCategory !=null and queryDTO.invoiceCategory !=''">
 			AND t.invoice_category = #{queryDTO.invoiceCategory}
 		</if>
+		<if test="queryDTO.isMerge !=null and queryDTO.isMerge !=''">
+			AND t.is_merge = #{queryDTO.isMerge}
+		</if>
 		<if test="queryDTO.bwRequestResult !=null and queryDTO.bwRequestResult !=''">
 			AND t.bw_request_result = #{queryDTO.bwRequestResult}
 		</if>
@@ -570,7 +573,7 @@
 		update_time,
 		del_flag,
 		comp_id,
-		(select count(1) from contract_invoice ci where ci.del_flag = '0' and ci.contract_id = c.id) invoiceNum,
+		(select count(1) from contract_invoice ci where ci.del_flag = '0' and (ci.contract_id = c.id or FIND_IN_SET(c.id,REPLACE(REPLACE(ci.contract_ids,'[', ''), ']', '')))) invoiceNum,
 		(select planned_amount from contract_payment_schedule cps where cps.del_flag='0' and cps.stage_name='鍚堝悓绛捐' and cps.contract_id = c.id) advanceAmount
 		FROM
 		contract c

--
Gitblit v1.9.1