浏览代码

Merge remote-tracking branch 'origin/dev' into dev

liyuan 4 月之前
父节点
当前提交
b37a7a1d58

+ 20 - 1
blade-service/blade-los/src/main/java/org/springblade/los/business/sea/controller/BillsController.java

@@ -586,6 +586,16 @@ public class BillsController extends BladeController {
 	}
 
 	/**
+	 * 批量单据请核
+	 */
+	@GetMapping("/checkBillsBatch")
+	@RepeatSubmit
+	public R checkBillsBatch(@RequestParam("billsIds") String billsIds, @RequestParam("url") String url,
+							 @RequestParam("pageStatus") String pageStatus, @RequestParam("pageLabel") String pageLabel) {
+		return billsService.checkBillsBatch(billsIds, url, pageStatus, pageLabel);
+	}
+
+	/**
 	 * 撤销单据请核
 	 */
 	@PostMapping("/revokeCheckBills")
@@ -598,6 +608,15 @@ public class BillsController extends BladeController {
 	}
 
 	/**
+	 * 批量撤销单据请核
+	 */
+	@GetMapping("/revokeCheckBillsBatch")
+	@RepeatSubmit
+	public R revokeCheckBillsBatch(@RequestParam("billsIds") String billsIds) {
+		return R.data(billsService.revokeCheckBillsBatch(billsIds));
+	}
+
+	/**
 	 * 审核通过
 	 */
 	@PostMapping("/passCheck")
@@ -657,7 +676,7 @@ public class BillsController extends BladeController {
 							@RequestParam(value = "billType", required = false) String billType,
 							@RequestParam(value = "copyCntr", required = false) String copyCntr,
 							@RequestParam(value = "copyFee", required = false) String copyFee) {
-		return billsService.batchCopyBills(ids, billType, copyCntr,copyFee);
+		return billsService.batchCopyBills(ids, billType, copyCntr, copyFee);
 	}
 
 	/**

+ 4 - 0
blade-service/blade-los/src/main/java/org/springblade/los/business/sea/service/IBillsService.java

@@ -185,4 +185,8 @@ public interface IBillsService extends IService<Bills> {
 	R<String> updateBatchField(UpdateBillsFieldVo updateBillsFieldVo);
 
 	R updateBillType(String ids, String billType);
+
+	R checkBillsBatch(String billsIds, String url, String pageStatus, String pageLabel);
+
+	R revokeCheckBillsBatch(String ids);
 }

+ 317 - 18
blade-service/blade-los/src/main/java/org/springblade/los/business/sea/service/impl/BillsServiceImpl.java

@@ -747,8 +747,7 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 				measurement = measurement.add(details.stream().map(Bills::getMeasurement).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
 
 			}
-		}
-		else if ("MH".equals(bills.getBillType()) && ObjectUtils.isNotNull(bills.getId())) {
+		} else if ("MH".equals(bills.getBillType()) && ObjectUtils.isNotNull(bills.getId())) {
 			Bills details = baseMapper.selectOne(new LambdaQueryWrapper<Bills>()
 				.select(Bills::getAmountDr, Bills::getAmountCr, Bills::getAmountProfit, Bills::getAmountDrUsd, Bills::getAmountCrUsd
 					, Bills::getAmountProfitUsd, Bills::getAmountDrLoc, Bills::getAmountCrLoc, Bills::getAmountProfitLoc
@@ -1414,12 +1413,21 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 				.eq(Bills::getTenantId, AuthUtil.getTenantId())
 				.eq(Bills::getIsDeleted, 0)
 				.eq(Bills::getMasterId, declare.getId()));
-			List<FeeCenter> feeCenters = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
-				.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
-				.eq(FeeCenter::getIsDeleted, 0)
-				.in(FeeCenter::getPid, billsList.stream().map(Bills::getId).collect(Collectors.toList())));
-			if (!feeCenters.isEmpty()) {
-				feeCenterList.addAll(feeCenters);
+			if (!billsList.isEmpty()) {
+				List<FeeCenter> feeCenters = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+					.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+					.eq(FeeCenter::getIsDeleted, 0)
+					.in(FeeCenter::getPid, billsList.stream().map(Bills::getId).collect(Collectors.toList())));
+				if (!feeCenters.isEmpty()) {
+					feeCenterList.addAll(feeCenters);
+				}
+				for (Bills item : billsList) {
+					item.setUpdateUser(AuthUtil.getUserId());
+					item.setUpdateUserName(AuthUtil.getUserName());
+					item.setUpdateTime(new Date());
+					item.setStatus(1);
+				}
+				this.updateBatchById(billsList);
 			}
 		}
 		String status = sysClient.getParamServiceNew("is.profit.margin");
@@ -3655,18 +3663,28 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 				.in(FeeCenter::getPid, Func.toLongList(ids)));
 		}
 		List<PreContainers> preContainersList = new ArrayList<>();
-		if (ObjectUtils.isNotNull(copyFee) && "1".equals(copyCntr)) {
+		if (ObjectUtils.isNotNull(copyCntr) && "1".equals(copyCntr)) {
 			preContainersList = preContainersService.list(new LambdaQueryWrapper<PreContainers>()
 				.eq(PreContainers::getTenantId, AuthUtil.getTenantId())
 				.eq(PreContainers::getIsDeleted, 0)
 				.in(PreContainers::getPid, Func.toLongList(ids)));
 		}
+		String type ="";
+		if ("SE".equals(billsList.get(0).getBusinessType())){
+			type = "HYCK";
+		}else if ("SI".equals(billsList.get(0).getBusinessType())){
+			type = "HYJK";
+		}else if ("AI".equals(billsList.get(0).getBusinessType())){
+			type = "KYJK";
+		}else if ("AE".equals(billsList.get(0).getBusinessType())){
+			type = "KYCK";
+		}
 		BusinessType businessType = bBusinessTypeService.getOne(new LambdaQueryWrapper<BusinessType>()
 			.select(BusinessType::getId)
 			.eq(BusinessType::getTenantId, AuthUtil.getTenantId())
 			.eq(BusinessType::getIsDeleted, 0)
 			.eq(BusinessType::getStatus, 0)
-			.eq(BusinessType::getCode, billsList.get(0).getBusinessTypes()));
+			.eq(BusinessType::getCode, type));
 		if (businessType == null) {
 			throw new RuntimeException("未找到可用业务类型");
 		}
@@ -3674,18 +3692,23 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 		for (Bills item : billsList) {
 			Bills copyBills = new Bills();
 			BeanUtil.copyProperties(item, copyBills);
+			copyBills.setBillType(billType);
 			copyBills.setTemporaryId(item.getId());
 			copyBills.setId(null);
 			BusinessBillNo businessBillNo = new BusinessBillNo();
 			businessBillNo.setBusinessTypeId(businessType.getId());
-			if ("dry".equals(copyBills.getCargoType())) {
-				businessBillNo.setCode(item.getBusinessTypes() + "-PH");
-			} else if ("danger".equals(copyBills.getCargoType())) {
-				businessBillNo.setCode(item.getBusinessTypes() + "-WXP");
-			} else if ("reefer".equals(copyBills.getCargoType())) {
-				businessBillNo.setCode(item.getBusinessTypes() + "-DG");
-			} else {
-				businessBillNo.setCode(item.getBusinessTypes() + "-PH");
+			if ("SE,SI".contains(item.getBusinessType())){
+				if ("dry".equals(copyBills.getCargoType())) {
+					businessBillNo.setCode(type + "-PH");
+				} else if ("danger".equals(copyBills.getCargoType())) {
+					businessBillNo.setCode(type + "-WXP");
+				} else if ("reefer".equals(copyBills.getCargoType())) {
+					businessBillNo.setCode(type + "-DG");
+				} else {
+					businessBillNo.setCode(type + "-PH");
+				}
+			}else{
+				businessBillNo.setCode(type);
 			}
 			R clientBillNo = businessBillNoService.getBillNoLos(businessBillNo);
 			if (!clientBillNo.isSuccess()) {
@@ -3929,4 +3952,280 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 		return R.data("操作成功");
 	}
 
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R checkBillsBatch(String billsIds, String url, String pageStatus, String pageLabel) {
+		List<Long> idList = new ArrayList<>();
+		List<Long> corpIdList = new ArrayList<>();
+		List<Bills> billsList = baseMapper.selectList(new LambdaQueryWrapper<Bills>()
+			.eq(Bills::getTenantId, AuthUtil.getTenantId())
+			.eq(Bills::getIsDeleted, 0)
+			.eq(Bills::getBranchId, AuthUtil.getDeptId())
+			.apply("find_in_set(id,'" + billsIds + "')"));
+		if (billsList.isEmpty()) {
+			throw new RuntimeException("未查到单据信息");
+		}
+		idList.addAll(billsList.stream().map(Bills::getId).collect(Collectors.toList()));
+		corpIdList.addAll(billsList.stream().map(Bills::getCorpId).collect(Collectors.toList()));
+		List<Bills> billsListF = baseMapper.selectList(new LambdaQueryWrapper<Bills>()
+			.eq(Bills::getTenantId, AuthUtil.getTenantId())
+			.eq(Bills::getIsDeleted, 0)
+			.in(Bills::getMasterId, idList));
+		if (!billsListF.isEmpty()) {
+			idList.addAll(billsListF.stream().map(Bills::getId).collect(Collectors.toList()));
+			corpIdList.addAll(billsListF.stream().map(Bills::getCorpId).collect(Collectors.toList()));
+		}
+		List<FeeCenter> feeCenterList = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+			.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+			.eq(FeeCenter::getIsDeleted, 0)
+			.eq(FeeCenter::getPid, idList));
+		if (feeCenterList.isEmpty()) {
+			throw new RuntimeException("请维护费用信息");
+		}
+		List<BCorps> corpsList = ibCorpsService.list(new LambdaQueryWrapper<BCorps>()
+			.eq(BCorps::getTenantId, AuthUtil.getTenantId())
+			.eq(BCorps::getIsDeleted, 0)
+			.eq(BCorps::getId, corpIdList));
+		if (corpsList.isEmpty()) {
+			throw new RuntimeException("未查到客户信息");
+		}
+		Integer actId = null;
+		String processType = "";
+		String checkType = "";
+		if ("SE".equals(billsList.get(0).getBusinessType())) {
+			actId = 1108;
+			processType = "海运出口审核";
+			checkType = "HYCK-DJ";
+		} else if ("SI".equals(billsList.get(0).getBusinessType())) {
+			actId = 1113;
+			processType = "海运进口审核";
+			checkType = "HYJK-DJ";
+		}
+		//获取审批级次
+		List<LosAuditPathsLevels> auditPathsLevels;
+		// 判断是否有审批流,如果审批流已开启就进入审批流,否则直接走申请通过
+		LosAuditPathsActs pathsActs;
+		//是否开启流程
+		LambdaQueryWrapper<LosAuditPathsActs> auditPathsActsLambdaQueryWrapper = new LambdaQueryWrapper<>();
+		auditPathsActsLambdaQueryWrapper
+			.eq(LosAuditPathsActs::getIsEnable, 1)
+			.eq(LosAuditPathsActs::getFidStatus, "status")
+			.eq(LosAuditPathsActs::getTenantId, AuthUtil.getTenantId())
+			.eq(LosAuditPathsActs::getSalesCompanyId, billsList.get(0).getBranchId())
+			.eq(LosAuditPathsActs::getActId, actId);
+		pathsActs = auditPathsActsService.getOne(auditPathsActsLambdaQueryWrapper);
+		//获取审批信息
+		LosAuditPathsActs losAuditPathsActs = auditPathsActsService.getOne(new LambdaQueryWrapper<LosAuditPathsActs>()
+			.eq(LosAuditPathsActs::getActId, actId)
+			.eq(LosAuditPathsActs::getFidStatus, "status")
+			.eq(LosAuditPathsActs::getSalesCompanyId, billsList.get(0).getBranchId())
+			.eq(LosAuditPathsActs::getTenantId, AuthUtil.getTenantId()));
+		Long pathId = losAuditPathsActs.getPathId();
+		auditPathsLevels = auditPathsLevelsService.list(new LambdaQueryWrapper<LosAuditPathsLevels>()
+			.eq(LosAuditPathsLevels::getTenantId, AuthUtil.getTenantId()).eq(LosAuditPathsLevels::getPathId, pathId));
+		String status = sysClient.getParamServiceNew("is.profit.margin");
+		for (Bills declare : billsList) {
+			if ("MH".equals(declare.getBillType())) {
+				throw new RuntimeException("分单不允许提交请核,请填加到主单在提交请核");
+			}
+			if ("SE".equals(declare.getBusinessType())) {
+				if (ObjectUtils.isNull(declare.getActualEtd())) {
+					throw new RuntimeException("实际开船日期不能为空");
+				}
+			} else if ("SI".equals(declare.getBusinessType())) {
+				if (ObjectUtils.isNull(declare.getActualEta())) {
+					throw new RuntimeException("实际到港日期不能为空");
+				}
+			}
+			String texts = "";
+			if (ObjectUtils.isNull(declare.getMblno())) {
+				texts = texts + "提单号、";
+			}
+			if (ObjectUtils.isNull(declare.getVesselId())) {
+				texts = texts + "船名、";
+			}
+			if (ObjectUtils.isNull(declare.getVoyageNo())) {
+				texts = texts + "航次、";
+			}
+			if (ObjectUtils.isNull(declare.getPodId())) {
+				texts = texts + "卸货港、";
+			}
+			if (ObjectUtils.isNull(declare.getCarrierId())) {
+				texts = texts + "船公司、";
+			}
+			if (ObjectUtils.isNull(declare.getCyId())) {
+				texts = texts + "场站、";
+			}
+			if (ObjectUtils.isNotNull(texts)) {
+				throw new RuntimeException("单号:" + declare.getBillNo() + "," + texts + "不能为空");
+			}
+			if ("1".equals(status)) {
+				List<Bills> billFs = billsListF.stream().filter(e -> e.getMasterId().equals(declare.getId())).collect(Collectors.toList());
+				List<Long> idListF = new ArrayList<>();
+				if (!billFs.isEmpty()) {
+					idListF.addAll(billFs.stream().map(Bills::getId).collect(Collectors.toList()));
+				}
+				List<FeeCenter> feeCenterListPS = feeCenterList.stream().filter(e -> e.getFeeCnName().equals("PS") &&
+					(e.getPid().equals(declare.getId()) || (!idListF.isEmpty() && idListF.contains(e.getPid())))).collect(Collectors.toList());
+				List<FeeCenter> feeCenterListHY = feeCenterList.stream().filter(e -> e.getFeeCnName().equals("海运费") &&
+					(e.getPid().equals(declare.getId()) || (!idListF.isEmpty() && idListF.contains(e.getPid())))).collect(Collectors.toList());
+				if (!feeCenterListPS.isEmpty() && feeCenterListHY.isEmpty()) {
+					throw new RuntimeException("PS费与海运费需同时存在,当前缺少海运费用信息");
+				}
+				if (!feeCenterListPS.isEmpty()) {
+					BigDecimal amountHYD = feeCenterList.stream()
+						.filter(e -> e.getFeeCnName().equals("海运费") && "USD".equals(e.getCurCode()) && "D".equals(e.getDc()) &&
+							(e.getPid().equals(declare.getId()) || (!idListF.isEmpty() && idListF.contains(e.getPid()))))
+						.map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+					BigDecimal amountHYC = feeCenterList.stream()
+						.filter(e -> e.getFeeCnName().equals("海运费") && "USD".equals(e.getCurCode()) && "C".equals(e.getDc()) &&
+							(e.getPid().equals(declare.getId()) || (!idListF.isEmpty() && idListF.contains(e.getPid()))))
+						.map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+					BigDecimal amountPSD = feeCenterList.stream()
+						.filter(e -> e.getFeeCnName().equals("PS") && "USD".equals(e.getCurCode()) && "D".equals(e.getDc()) &&
+							(e.getPid().equals(declare.getId()) || (!idListF.isEmpty() && idListF.contains(e.getPid()))))
+						.map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+					BigDecimal amountPSC = feeCenterList.stream()
+						.filter(e -> e.getFeeCnName().equals("PS") && "USD".equals(e.getCurCode()) && "C".equals(e.getDc()) &&
+							(e.getPid().equals(declare.getId()) || (!idListF.isEmpty() && idListF.contains(e.getPid()))))
+						.map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+					if (("PP".equals(declare.getMpaymode()) && ("MM".equals(declare.getBillType()) || "DD".equals(declare.getBillType()))) ||
+						("CC".equals(declare.getMpaymode()) && "MH".equals(declare.getBillType()))) {
+						BCorps bCorps = corpsList.stream().filter(e -> e.getId().equals(declare.getCorpId())).findFirst().orElse(null);
+						if (bCorps != null) {
+							BigDecimal PSAmount = amountPSC.subtract(amountPSD);
+							BigDecimal HYAmount = amountHYD.subtract(amountHYC);
+							BigDecimal rate = new BigDecimal("0.00");
+							if (PSAmount.compareTo(new BigDecimal("0.00")) > 0 && HYAmount.compareTo(new BigDecimal("0.00")) > 0) {
+								rate = PSAmount.divide(HYAmount, MathContext.DECIMAL32).setScale(2, RoundingMode.HALF_UP);
+							} else {
+								throw new RuntimeException("海运费利润:" + HYAmount + ",  PS利润:" + PSAmount);
+							}
+							if (ObjectUtils.isNotNull(bCorps) && ObjectUtils.isNotNull(bCorps.getPsRate()) && new BigDecimal(bCorps.getPsRate()).compareTo(new BigDecimal("0.00")) == 0) {
+								throw new RuntimeException("往来单位PS规则为空或零,不能存在PS费用");
+							}
+							if (new BigDecimal(bCorps.getPsRate()).compareTo(rate) < 0) {
+								throw new RuntimeException("PS比例高,公司实际分成比例:" + rate + ".系统比例为:" + bCorps.getPsRate());
+							}
+						}
+					} else {
+						throw new RuntimeException("只有预付、直单和主单,或分单和到付才可以输入PS");
+					}
+				} /*else if (!feeCenterListPS.isEmpty() && feeCenterListHY.isEmpty()) {
+				throw new RuntimeException("PS费与海运费需同时存在,当前缺少PS费用信息");
+			} else if (!feeCenterListPS.isEmpty()) {
+				throw new RuntimeException("PS费与海运费需同时存在,当前缺少海运费用信息");
+			}*/
+			}
+			//审批数据
+			LosAuditProecessDTO auditProecessDTO = new LosAuditProecessDTO();
+			auditProecessDTO.setTimes(1);
+			auditProecessDTO.setProcessType(processType);
+			// 没开启审批流直接走 通过流程
+			if (pathsActs == null || pathsActs.getIsEnable() == 2) {
+				throw new SecurityException("当前租户未查询到审批流配置");
+			} else {
+				if (CollectionUtils.isEmpty(auditPathsLevels)) {
+					throw new SecurityException("开启审批失败:未查询到审批信息");
+				}
+				// 绑定审核类型
+				auditProecessDTO.setCheckType(checkType);
+				// 追加跳转路由url
+				auditProecessDTO.setUrl(url);
+				auditProecessDTO.setPageStatus(pageStatus);
+				auditProecessDTO.setPageLabel(pageLabel);
+				auditProecessDTO.setOrderRemark(declare.getRemarks());
+				auditProecessDTO.setPathsLevelsList(auditPathsLevels);
+				auditProecessDTO.setActId(1);
+				auditProecessDTO.setSrcBillId(declare.getId());
+				auditProecessDTO.setBillId(declare.getId());
+				auditProecessDTO.setBillNo(declare.getBillNo());
+				auditProecessDTO.setSendUserId(AuthUtil.getUserId());
+				auditProecessDTO.setSendName(AuthUtil.getUserName());
+				auditProecessDTO.setSendTime(new Date());
+				auditProecessDTO.setBillTime(declare.getCreateTime());
+				auditProecessDTO.setTenantId(AuthUtil.getTenantId());
+				auditProecessDTO.setCorpId(declare.getCorpId());
+				auditProecessDTO.setCorpsName(declare.getCorpCnName());
+				auditProecessDTO.setReferenceNumber(declare.getMblno());
+				auditProecessDTO.setMorderNo(declare.getMblno());
+				auditProecessDTO.setBookingAgentId(declare.getBookingAgentId());
+				auditProecessDTO.setBookingAgentCnName(declare.getBookingAgentCnName());
+				auditProecessDTO.setSalesCompanyId(Long.parseLong(declare.getBranchId()));
+				auditProecessDTO.setPayAmount(declare.getAmountCrLoc());
+				auditProecessDTO.setReceivableAmount(declare.getAmountDrLoc());
+				auditProecessDTO.setGrossProfit(declare.getAmountProfit());
+				auditProecessDTO.setGrossProfitUsd(declare.getAmountProfitUsd());
+				auditProecessDTO.setGrossProfitLoc(declare.getAmountProfitLoc());
+				auditProecessDTO.setSrcId(declare.getSrcId());
+				auditProecessDTO.setSrcCnName(declare.getSrcCnName());
+				auditProecessDTO.setSrcEnName(declare.getSrcEnName());
+				if ("SE".equals(declare.getBusinessType())) {
+					auditProecessDTO.setEtd(declare.getEtd());
+				} else if ("SI".equals(declare.getBusinessType())) {
+					auditProecessDTO.setEtd(declare.getEta());
+				}
+				R financeProcess = auditProecessService.createFinanceProcess(auditProecessDTO);
+				if (!financeProcess.isSuccess()) {
+					throw new SecurityException("操作失败,请联系管理员");
+				}
+			}
+			declare.setUpdateUser(AuthUtil.getUserId());
+			declare.setUpdateUserName(AuthUtil.getUserName());
+			declare.setUpdateTime(new Date());
+			declare.setStatus(1);
+		}
+		for (Bills declare : billsListF) {
+			declare.setUpdateUser(AuthUtil.getUserId());
+			declare.setUpdateUserName(AuthUtil.getUserName());
+			declare.setUpdateTime(new Date());
+			declare.setStatus(1);
+		}
+		if (!billsListF.isEmpty()) {
+			this.updateBatchById(billsListF);
+		}
+		this.updateBatchById(billsList);
+		return R.success("操作成功");
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R revokeCheckBillsBatch(String ids) {
+		List<Bills> billsList = baseMapper.selectList(new LambdaQueryWrapper<Bills>()
+			.eq(Bills::getTenantId, AuthUtil.getTenantId())
+			.eq(Bills::getIsDeleted, 0)
+			.eq(Bills::getBranchId, AuthUtil.getDeptId())
+			.apply("find_in_set(id,'" + ids + "')"));
+		if (billsList.isEmpty()) {
+			throw new RuntimeException("未查到单据信息");
+		}
+		for (Bills declare : billsList) {
+			if (3 == declare.getStatus()) {
+				throw new SecurityException("审核已通过,撤销失败");
+			}
+			R financeProcess = auditProecessService.deteleByBillId(declare.getId());
+			if (!financeProcess.isSuccess()) {
+				throw new SecurityException("操作失败,请联系管理员");
+			}
+			declare.setStatus(0);
+		}
+		this.updateBatchById(billsList);
+		List<Long> idList = new ArrayList<>();
+		idList.addAll(billsList.stream().map(Bills::getId).collect(Collectors.toList()));
+		List<Bills> billsListF = baseMapper.selectList(new LambdaQueryWrapper<Bills>()
+			.eq(Bills::getTenantId, AuthUtil.getTenantId())
+			.eq(Bills::getIsDeleted, 0)
+			.in(Bills::getMasterId, idList));
+		if (!billsListF.isEmpty()) {
+			for (Bills declare : billsListF) {
+				if (3 == declare.getStatus()) {
+					throw new SecurityException("审核已通过,撤销失败");
+				}
+				declare.setStatus(0);
+			}
+			this.updateBatchById(billsListF);
+		}
+		return R.data("操作成功");
+	}
+
 }

+ 8 - 0
blade-service/blade-los/src/main/java/org/springblade/los/finance/fee/controller/FeeCenterController.java

@@ -326,5 +326,13 @@ public class FeeCenterController extends BladeController {
 		return R.data(feeCenterService.getFeeCenterCorpIds(billId, dc, type));
 	}
 
+	/**
+	 * 批量修改结算单位
+	 */
+	@PostMapping("/updateCorpBatch")
+	@RepeatSubmit
+	public R updateCorpBatch(@RequestBody Bills bills) {
+		return feeCenterService.updateCorpBatch(bills);
+	}
 
 }

+ 18 - 0
blade-service/blade-los/src/main/java/org/springblade/los/finance/fee/controller/FinAccBillsController.java

@@ -229,6 +229,15 @@ public class FinAccBillsController extends BladeController {
 	}
 
 	/**
+	 * 批量生成账单
+	 */
+	@GetMapping("/generateBillBatch")
+	@RepeatSubmit
+	public R generateBillBatch(@RequestParam("billsIds") String billsIds) {
+		return finAccBillsService.generateBillBatch(billsIds);
+	}
+
+	/**
 	 * 撤销账单
 	 */
 	@PostMapping("/revokeBill")
@@ -239,6 +248,15 @@ public class FinAccBillsController extends BladeController {
 		return finAccBillsService.revokeBill(finAccBills);
 	}
 
+	/**
+	 * 批量撤销账单
+	 */
+	@GetMapping("/revokeBillBatch")
+	@RepeatSubmit
+	public R revokeBillBatch(@RequestParam("billsIds") String billsIds) {
+		return finAccBillsService.revokeBillBatch(billsIds);
+	}
+
 
 	/**
 	 * 删除 业务-财务账单

+ 2 - 0
blade-service/blade-los/src/main/java/org/springblade/los/finance/fee/service/IFeeCenterService.java

@@ -91,4 +91,6 @@ public interface IFeeCenterService extends IService<FeeCenter> {
 	R submitTradeYfk(FeeCenter feeCenter);
 
 	boolean removeTradeYfk(List<FeeCenter> feeCenterList);
+
+	R updateCorpBatch(Bills bills);
 }

+ 4 - 0
blade-service/blade-los/src/main/java/org/springblade/los/finance/fee/service/IFinAccBillsService.java

@@ -82,4 +82,8 @@ public interface IFinAccBillsService extends IService<FinAccBills> {
     List<Map<String, Object>> listFeeCountByCorp(String dc,Long corpId);
 
 	List<FeeCountByCorpExcel> listFeeCountByCorpExport(String dc, Long corpId);
+
+	R generateBillBatch(String billsIds);
+
+	R revokeBillBatch(String billsIds);
 }

+ 48 - 26
blade-service/blade-los/src/main/java/org/springblade/los/finance/fee/service/impl/FeeCenterServiceImpl.java

@@ -384,7 +384,7 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 						feeCenter.setQuantity(new BigDecimal("1"));
 						feeCenter.setAmount(feeCenter.getPrice().multiply(feeCenter.getQuantity()));
 					}
-					if (ObjectUtils.isNull(feeCenter.getAmount())){
+					if (ObjectUtils.isNull(feeCenter.getAmount())) {
 						feeCenter.setAmount(new BigDecimal("0"));
 					}
 					list.add(feeCenter);
@@ -475,7 +475,7 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 						feeCenter.setQuantity(new BigDecimal("1"));
 						feeCenter.setAmount(items.getPrice().multiply(new BigDecimal("1")));
 					}
-					if (ObjectUtils.isNotNull(feeCenter.getAmount())){
+					if (ObjectUtils.isNotNull(feeCenter.getAmount())) {
 						feeCenter.setAmount(new BigDecimal("0"));
 					}
 					list.add(feeCenter);
@@ -564,7 +564,7 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 						feeCenter.setQuantity(new BigDecimal("1"));
 						feeCenter.setAmount(items.getPrice().multiply(new BigDecimal("1")));
 					}
-					if (ObjectUtils.isNotNull(feeCenter.getAmount())){
+					if (ObjectUtils.isNotNull(feeCenter.getAmount())) {
 						feeCenter.setAmount(new BigDecimal("0"));
 					}
 					list.add(feeCenter);
@@ -599,13 +599,13 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 				.eq(BCorps::getTenantId, AuthUtil.getTenantId())
 				.eq(BCorps::getIsDeleted, 0));
 			for (FeeCenter feeCenter : list) {
-				if (!bCorpsList.isEmpty()){
-					BCorps bCorps = bCorpsList.stream().filter(e-> e.getId().equals(feeCenter.getCorpId())).findFirst().orElse(null);
-					if (bCorps != null){
+				if (!bCorpsList.isEmpty()) {
+					BCorps bCorps = bCorpsList.stream().filter(e -> e.getId().equals(feeCenter.getCorpId())).findFirst().orElse(null);
+					if (bCorps != null) {
 						feeCenter.setShortName(bCorps.getShortName());
 					}
-					BCorps bCorps1 = bCorpsList.stream().filter(e-> e.getId().equals(feeCenter.getBillCorpId())).findFirst().orElse(null);
-					if (bCorps1 != null){
+					BCorps bCorps1 = bCorpsList.stream().filter(e -> e.getId().equals(feeCenter.getBillCorpId())).findFirst().orElse(null);
+					if (bCorps1 != null) {
 						feeCenter.setBillCorpEnName(bCorps1.getShortName());
 					}
 				}
@@ -684,8 +684,8 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 			amountDrUsd = list.stream().filter(e -> "D".equals(e.getDc()) && "USD".equals(e.getCurCode())).map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
 			amountCr = list.stream().filter(e -> "C".equals(e.getDc()) && "CNY".equals(e.getCurCode())).map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
 			amountCrUsd = list.stream().filter(e -> "C".equals(e.getDc()) && "USD".equals(e.getCurCode())).map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
-			amountDrLoc = list.stream().filter(e -> "D".equals(e.getDc()) ).map(FeeCenter::getAmountLoc).reduce(BigDecimal.ZERO, BigDecimal::add);
-			amountCrLoc = list.stream().filter(e -> "C".equals(e.getDc()) ).map(FeeCenter::getAmountLoc).reduce(BigDecimal.ZERO, BigDecimal::add);
+			amountDrLoc = list.stream().filter(e -> "D".equals(e.getDc())).map(FeeCenter::getAmountLoc).reduce(BigDecimal.ZERO, BigDecimal::add);
+			amountCrLoc = list.stream().filter(e -> "C".equals(e.getDc())).map(FeeCenter::getAmountLoc).reduce(BigDecimal.ZERO, BigDecimal::add);
 
 			if ("SE".equals(list.get(0).getBusinessType()) || "SI".equals(list.get(0).getBusinessType())) {
 				Bills bills = billsMapper.selectById(list.get(0).getPid());
@@ -966,8 +966,8 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 		List<FeeCenter> feeCenterList = new ArrayList<>();
 		if (ObjectUtils.isNotNull(list) && !list.isEmpty()) {
 			Date date = list.get(0).getBillDate();
-			BigDecimal exrateD = bCurrencyService.getCnyExrate(date,"USD", "D", "1");
-			BigDecimal exrateC = bCurrencyService.getCnyExrate(date,"USD", "C", "1");
+			BigDecimal exrateD = bCurrencyService.getCnyExrate(date, "USD", "D", "1");
+			BigDecimal exrateC = bCurrencyService.getCnyExrate(date, "USD", "C", "1");
 			for (FeeCenter feeCenter : list) {
 				if (feeCenter.getId() == null) {
 					feeCenter.setCreateTime(new Date());
@@ -1253,13 +1253,13 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 					if (ObjectUtils.isNull(item.getDiscountExrate())) {
 						throw new RuntimeException("首款、尾款优惠汇率不能为空");
 					}
-					if (!bCorpsList.isEmpty()){
-						BCorps bCorps = bCorpsList.stream().filter(e-> e.getId().equals(item.getCorpId())).findFirst().orElse(null);
-						if (bCorps != null){
+					if (!bCorpsList.isEmpty()) {
+						BCorps bCorps = bCorpsList.stream().filter(e -> e.getId().equals(item.getCorpId())).findFirst().orElse(null);
+						if (bCorps != null) {
 							item.setShortName(bCorps.getShortName());
 						}
-						BCorps bCorps1 = bCorpsList.stream().filter(e-> e.getId().equals(item.getBillCorpId())).findFirst().orElse(null);
-						if (bCorps1 != null){
+						BCorps bCorps1 = bCorpsList.stream().filter(e -> e.getId().equals(item.getBillCorpId())).findFirst().orElse(null);
+						if (bCorps1 != null) {
 							item.setBillCorpEnName(bCorps1.getShortName());
 						}
 					}
@@ -1321,13 +1321,13 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 						feeCenter.setPodEnName(agent.getPodEnName());
 					}
 				}
-				if (!bCorpsList.isEmpty()){
-					BCorps bCorps = bCorpsList.stream().filter(e-> e.getId().equals(feeCenter.getCorpId())).findFirst().orElse(null);
-					if (bCorps != null){
+				if (!bCorpsList.isEmpty()) {
+					BCorps bCorps = bCorpsList.stream().filter(e -> e.getId().equals(feeCenter.getCorpId())).findFirst().orElse(null);
+					if (bCorps != null) {
 						feeCenter.setShortName(bCorps.getShortName());
 					}
-					BCorps bCorps1 = bCorpsList.stream().filter(e-> e.getId().equals(feeCenter.getBillCorpId())).findFirst().orElse(null);
-					if (bCorps1 != null){
+					BCorps bCorps1 = bCorpsList.stream().filter(e -> e.getId().equals(feeCenter.getBillCorpId())).findFirst().orElse(null);
+					if (bCorps1 != null) {
 						feeCenter.setBillCorpEnName(bCorps1.getShortName());
 					}
 				}
@@ -1471,9 +1471,9 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 							}
 						}
 					}
-					if (ObjectUtils.isNotNull(items.getQuantity())){
+					if (ObjectUtils.isNotNull(items.getQuantity())) {
 						feeCenter.setQuantity(items.getQuantity());
-					}else{
+					} else {
 						feeCenter.setQuantity(new BigDecimal("0"));
 					}
 					feeCenter.setAmount(items.getPrice().multiply(items.getQuantity()));
@@ -1543,9 +1543,9 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 							}
 						}
 					}
-					if (ObjectUtils.isNotNull(items.getQuantity())){
+					if (ObjectUtils.isNotNull(items.getQuantity())) {
 						feeCenter.setQuantity(items.getQuantity());
-					}else{
+					} else {
 						feeCenter.setQuantity(new BigDecimal("0"));
 					}
 					feeCenter.setAmount(items.getPrice().multiply(items.getQuantity()));
@@ -1629,4 +1629,26 @@ public class FeeCenterServiceImpl extends ServiceImpl<FeeCenterMapper, FeeCenter
 		return true;
 	}
 
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R updateCorpBatch(Bills bills) {
+		if (ObjectUtils.isNull(bills.getCorpId()) || ObjectUtils.isNull(bills.getFeeCenterListD()) || bills.getFeeCenterListD().isEmpty()) {
+			throw new RuntimeException("缺少必要参数");
+		}
+		for (FeeCenter item : bills.getFeeCenterListD()) {
+			if (1 == item.getAccStatus()) {
+				throw new RuntimeException("费用:" + item.getFeeCnName() + "已生成账单");
+			}
+			item.setUpdateTime(new Date());
+			item.setUpdateUser(AuthUtil.getUserId());
+			item.setUpdateUserName(AuthUtil.getUserName());
+			item.setCorpId(bills.getCorpId());
+			item.setCorpCnName(bills.getCorpCnName());
+			item.setCorpEnName(bills.getCorpEnName());
+			item.setShortName(bills.getShortName());
+		}
+		this.updateBatchById(bills.getFeeCenterListD());
+		return R.data(bills.getFeeCenterListD());
+	}
+
 }

+ 385 - 1
blade-service/blade-los/src/main/java/org/springblade/los/finance/fee/service/impl/FinAccBillsServiceImpl.java

@@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.AllArgsConstructor;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
 import org.springblade.los.Util.IDeptUtils;
 import org.springblade.los.basic.business.entity.BusinessType;
 import org.springblade.los.basic.business.service.IBusinessTypeService;
@@ -235,7 +236,7 @@ public class FinAccBillsServiceImpl extends ServiceImpl<FinAccBillsMapper, FinAc
 			data.setBusinessBillNo(item.getBillNo());
 			data.setBusinessDate(item.getBillDate());
 			if ("SEA".equals(item.getBusinessType()) || "SIA".equals(item.getBusinessType())
-			|| "AEA".equals(item.getBusinessType()) || "AIA".equals(item.getBusinessType())) {
+				|| "AEA".equals(item.getBusinessType()) || "AIA".equals(item.getBusinessType())) {
 				Amends amends = amendsList.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(new Amends());
 				data.setSrcId(amends.getSrcId());
 				data.setSrcCnName(amends.getSrcCnName());
@@ -510,6 +511,389 @@ public class FinAccBillsServiceImpl extends ServiceImpl<FinAccBillsMapper, FinAc
 		}
 	}
 
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R generateBillBatch(String billsIds) {
+		List<FeeCenter> feeCenterListOld = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+			.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+			.eq(FeeCenter::getIsDeleted, 0)
+			.eq(FeeCenter::getAccStatus, 0));
+		if (feeCenterListOld.isEmpty()) {
+			throw new RuntimeException("没找到可生成账单费用信息");
+		}
+		List<FeeCenter> feeCenterList = new ArrayList<>();
+		List<FinAccBills> finAccBillsList = new ArrayList<>();
+		String deptId = "";
+		String deptName = "";
+		String branchId = deptUtils.getDeptPid() + "";
+		//获取部门ids对应中文名
+		if (ObjectUtils.isNotNull(deptUtils.getDeptPid() + "")) {
+			deptId = deptUtils.getDeptPid() + "";
+			R<List<String>> res = sysClient.getDeptNames(deptUtils.getDeptPid() + "");
+			if (res.isSuccess() && ObjectUtils.isNotNull(res.getData())) {
+				deptName = String.join(",", res.getData());
+			}
+		}
+		List<Bills> billsList = new ArrayList<>();
+		List<Amends> amendsList = new ArrayList<>();
+		List<Long> ids = Func.toLongList(billsIds);
+		String status = sysClient.getParamService("generate.billing.rules");
+		for (FeeCenter item : feeCenterListOld) {
+			if (1 == item.getAccStatus()) {
+				throw new RuntimeException("费用:" + item.getFeeCnName() + "已生成账单");
+			}
+			boolean amountStatus = true;
+			if (new BigDecimal("0.00").compareTo(item.getAmount()) > 0) {
+				amountStatus = false;
+			}
+			if ("1".equals(status)) {
+				if (ObjectUtils.isNotNull(item.getPid()) && ObjectUtils.isNotNull(item.getCorpId()) &&
+					ObjectUtils.isNotNull(item.getDc()) && ObjectUtils.isNotNull(item.getElementsId()) && ObjectUtils.isNotNull(item.getCurCode())) {
+					item.setBillKey(item.getPid() + "-" + item.getCorpId() + "-" + item.getDc() + "-" + item.getElementsCode() + "-" + item.getCurCode() + "-" + amountStatus);
+				} else {
+					throw new RuntimeException("单据号、单位、费用类型、核算要素不能为空");
+				}
+			} else {
+				if (ObjectUtils.isNotNull(item.getPid()) && ObjectUtils.isNotNull(item.getCorpId()) &&
+					ObjectUtils.isNotNull(item.getDc()) && ObjectUtils.isNotNull(item.getFeeId()) && ObjectUtils.isNotNull(item.getCurCode())) {
+					item.setBillKey(item.getPid() + "-" + item.getCorpId() + "-" + item.getDc() + "-" + item.getFeeCode() + "-" + item.getCurCode() + "-" + amountStatus);
+				} else {
+					throw new RuntimeException("单据号、单位、费用类型、费用名称不能为空");
+				}
+			}
+
+		}
+		BusinessType businessType = bBusinessTypeService.getOne(new LambdaQueryWrapper<BusinessType>()
+			.eq(BusinessType::getTenantId, AuthUtil.getTenantId())
+			.eq(BusinessType::getIsDeleted, 0)
+			.eq(BusinessType::getStatus, 0)
+			.eq(BusinessType::getCode, "HYZD"));
+		if (businessType == null) {
+			throw new RuntimeException("未找到可用业务类型");
+		}
+		List<FeeCenter> reducelList = feeCenterListOld.stream().filter(distinctByKey(FeeCenter::getBillKey)).collect(Collectors.toList());
+		if (ObjectUtils.isNotNull(ids) && !ids.isEmpty()) {
+			billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
+				.eq(Bills::getTenantId, AuthUtil.getTenantId())
+				.eq(Bills::getIsDeleted, 0)
+				.in(Bills::getId, ids));
+			for (Bills item : billsList) {
+				String texts = "";
+				if (ObjectUtils.isNull(item.getMblno())) {
+					texts = texts + "提单号、";
+				}
+				if (ObjectUtils.isNull(item.getVesselId())) {
+					texts = texts + "船名、";
+				}
+				if (ObjectUtils.isNull(item.getVoyageNo())) {
+					texts = texts + "航次、";
+				}
+				if (ObjectUtils.isNull(item.getPodId())) {
+					texts = texts + "卸货港、";
+				}
+				if (ObjectUtils.isNull(item.getCarrierId())) {
+					texts = texts + "船公司、";
+				}
+				if (ObjectUtils.isNull(item.getCyId())) {
+					texts = texts + "场站、";
+				}
+				if (ObjectUtils.isNotNull(texts)) {
+					throw new RuntimeException("单号:" + item.getBillNo() + "," + texts + "不能为空");
+				}
+				item.setBillingStatus(item.getBillingStatus() + reducelList.size());
+				item.setBillSort(item.getVesselId() + item.getVoyageNo());
+				billsMapper.updateById(item);
+			}
+			if (billsList.stream().filter(distinctByKey(Bills::getBillSort)).count() > 1) {
+				throw new RuntimeException("请选择同一船名航次下的业务生成账单");
+			}
+			amendsList = amendsMapper.selectList(new LambdaQueryWrapper<Amends>()
+				.eq(Amends::getTenantId, AuthUtil.getTenantId())
+				.eq(Amends::getIsDeleted, 0)
+				.in(Amends::getId, ids));
+		}
+		for (FeeCenter item : reducelList) {
+			BigDecimal amountCNY = feeCenterListOld.stream()
+				.filter(e -> e.getBillKey().equals(item.getBillKey()) && item.getCurCode().equals(e.getCurCode())
+					&& "CNY".equals(e.getCurCode()))
+				.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+			BigDecimal amountUSD = feeCenterListOld.stream()
+				.filter(e -> e.getBillKey().equals(item.getBillKey()) && item.getCurCode().equals(e.getCurCode())
+					&& "USD".equals(e.getCurCode()))
+				.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+			FinAccBills data = new FinAccBills();
+			data.setCreateTime(new Date());
+			data.setCreateUser(AuthUtil.getUserId());
+			data.setCreateUserName(AuthUtil.getUserName());
+			data.setCreateDept(deptId);
+			data.setCreateDeptName(deptName);
+			data.setBranchId(branchId);
+			data.setDeptId(deptUtils.getDeptPid());
+			data.setDeptName(deptName);
+			BusinessBillNo businessBillNo = new BusinessBillNo();
+			businessBillNo.setBusinessTypeId(businessType.getId());
+			businessBillNo.setCode("HYZD");
+			R clientBillNo = businessBillNoService.getBillNoLos(businessBillNo);
+			if (!clientBillNo.isSuccess()) {
+				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+				return R.fail(500, "生成订单编号失败");
+			}
+			data.setBillNo((String) clientBillNo.getData());
+			data.setBillDate(new Date());
+			data.setAccountType("");
+			data.setAccountDc(item.getDc());
+			data.setAccountDate(item.getBillDate());
+			data.setBillKey(item.getBillKey());
+			data.setBusinessType(item.getBusinessType());
+			data.setBusinessBillId(item.getPid());
+			data.setBusinessBillNo(item.getBillNo());
+			data.setBusinessDate(item.getBillDate());
+			if ("SEA".equals(item.getBusinessType()) || "SIA".equals(item.getBusinessType())
+				|| "AEA".equals(item.getBusinessType()) || "AIA".equals(item.getBusinessType())) {
+				Amends amends = amendsList.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(new Amends());
+				data.setSrcId(amends.getSrcId());
+				data.setSrcCnName(amends.getSrcCnName());
+				data.setSrcEnName(amends.getSrcEnName());
+				data.setSrcType(amends.getSrcType());
+				data.setOperatorId(amends.getOperatorId());
+				data.setOperatorName(amends.getOperatorName());
+				data.setQuantityCntrDescr(amends.getQuantityCntrDescr());
+				data.setTeamId(amends.getTeamId());
+				data.setTeamName(amends.getTeamName());
+			} else if ("SE".equals(item.getBusinessType()) || "SI".equals(item.getBusinessType())) {
+				Bills bills = billsList.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(new Bills());
+				data.setSrcId(bills.getSrcId());
+				data.setSrcCnName(bills.getSrcCnName());
+				data.setSrcEnName(bills.getSrcEnName());
+				data.setSrcType(bills.getSrcType());
+				data.setOperatorId(bills.getOperatorId());
+				data.setOperatorName(bills.getOperatorName());
+				data.setQuantityCntrDescr(bills.getQuantityCntrDescr());
+				data.setCorpArgreementNo(bills.getCorpArgreementNo());
+				data.setRefno(bills.getRefno());
+				data.setBookingNo(bills.getBookingNo());
+				data.setPolNamePrint(bills.getPolNamePrint());
+				data.setPodNamePrint(bills.getPodNamePrint());
+				data.setTeamId(bills.getTeamId());
+				data.setTeamName(bills.getTeamName());
+			} else {
+				data.setSrcId(item.getSrcId());
+				data.setSrcCnName(item.getSrcCnName());
+				data.setSrcEnName(item.getSrcEnName());
+				data.setSrcType(item.getSrcType());
+				data.setOperatorId(item.getCreateUser());
+				data.setOperatorName(item.getCreateUserName());
+			}
+			data.setPaymode(item.getPaymode());
+			data.setAccelementid(item.getElementsId());
+			data.setAccelementname(item.getElementsCnName());
+			data.setCorpId(item.getCorpId());
+			data.setCorpCnName(item.getCorpCnName());
+			data.setCorpEnName(item.getCorpEnName());
+			data.setBillCorpId(item.getBillCorpId());
+			data.setBillCorpCnName(item.getBillCorpCnName());
+			data.setBillCorpEnName(item.getBillCorpEnName());
+			data.setVesselId(item.getVesselId());
+			data.setVesselCnName(item.getVesselCnName());
+			data.setVesselEnName(item.getVesselEnName());
+			data.setVoyageNo(item.getVoyageNo());
+			data.setMblno(item.getMblno());
+			data.setHblno(item.getHblno());
+			data.setEtd(item.getEtd());
+			data.setEta(item.getEta());
+			data.setPolId(item.getPolId());
+			data.setPolCnName(item.getPolCnName());
+			data.setPolEnName(item.getPolEnName());
+			data.setPodId(item.getPodId());
+			data.setPodCnName(item.getPodCnName());
+			data.setPodCode(item.getPodCode());
+			data.setPodEnName(item.getPodEnName());
+			BigDecimal amountDrLoc = new BigDecimal("0.00");
+			BigDecimal amountCrLoc = new BigDecimal("0.00");
+			if ("CNY".equals(item.getCurCode())) {
+				if ("D".equals(item.getDc())) {
+					data.setAmountDr(amountCNY);
+					data.setAmountCr(new BigDecimal("0.00"));
+				} else {
+					data.setAmountCr(amountCNY);
+					data.setAmountDr(new BigDecimal("0.00"));
+				}
+				data.setAmountDrUsd(new BigDecimal("0.00"));
+				data.setAmountCrUsd(new BigDecimal("0.00"));
+			} else {
+				if ("D".equals(item.getDc())) {
+					data.setAmountDrUsd(amountUSD);
+					data.setAmountCrUsd(new BigDecimal("0.00"));
+				} else {
+					data.setAmountDrUsd(new BigDecimal("0.00"));
+					data.setAmountCrUsd(amountUSD);
+				}
+				data.setAmountDr(new BigDecimal("0.00"));
+				data.setAmountCr(new BigDecimal("0.00"));
+			}
+
+			if (ObjectUtils.isNotNull(data.getAmountCrUsd()) && ObjectUtils.isNotNull(item.getExrate())) {
+				BigDecimal crCny = data.getAmountCrUsd().multiply(item.getExrate());
+				amountCrLoc = amountCrLoc.add(data.getAmountCr()).add(crCny);
+			}
+			if (ObjectUtils.isNotNull(data.getAmountDrUsd()) && ObjectUtils.isNotNull(item.getExrate())) {
+				BigDecimal drCny = data.getAmountDrUsd().multiply(item.getExrate());
+				amountDrLoc = amountDrLoc.add(data.getAmountDr()).add(drCny);
+			}
+			data.setAmountDrLoc(amountDrLoc);
+			data.setAmountCrLoc(amountCrLoc);
+			this.saveOrUpdate(data);
+			finAccBillsList.add(data);
+			List<FeeCenter> feeCenterList1 = feeCenterListOld.stream()
+				.filter(e -> e.getBillKey().equals(item.getBillKey())).collect(Collectors.toList());
+			for (FeeCenter feeCenterItem : feeCenterList1) {
+				feeCenterItem.setAccBillId(data.getId());
+				feeCenterItem.setAccBillNo(data.getBillNo());
+				feeCenterItem.setAccDate(data.getBillDate());
+				feeCenterItem.setAccAmount(amountDrLoc.add(amountCrLoc));
+				feeCenterItem.setAccStatus(1);
+				feeCenterItem.setAccById(AuthUtil.getUserId());
+				feeCenterItem.setAccByName(AuthUtil.getUserName());
+				feeCenterItem.setAuditStatus("2");
+				feeCenterList.add(feeCenterItem);
+			}
+		}
+		feeCenterService.saveOrUpdateBatch(feeCenterList);
+		return R.data("操作成功");
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R revokeBillBatch(String billsIds) {
+		List<FeeCenter> feeCenterListOld = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+			.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+			.eq(FeeCenter::getIsDeleted, 0)
+			.eq(FeeCenter::getAccStatus, 0));
+		if (feeCenterListOld.isEmpty()) {
+			throw new RuntimeException("没找到可生成账单费用信息");
+		}
+		List<FeeCenter> feeCenterList = new ArrayList<>();
+		List<Bills> billsList = new ArrayList<>();
+		List<Long> ids = Func.toLongList(billsIds);
+		if (ObjectUtils.isNotNull(ids) && !ids.isEmpty()) {
+			billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
+				.eq(Bills::getTenantId, AuthUtil.getTenantId())
+				.eq(Bills::getIsDeleted, 0)
+				.in(Bills::getId, ids));
+		}
+		List<Long> finAccBillsIds = feeCenterListOld.stream().map(FeeCenter::getAccBillId).distinct().collect(Collectors.toList());
+		String finAccBillsBillNo = feeCenterListOld.stream().map(FeeCenter::getBillNo).distinct().collect(Collectors.joining(","));
+		if (!finAccBillsIds.isEmpty()) {
+			List<FinInvoicesItems> finInvoicesItems = finInvoicesItemsMapper.selectList(new LambdaQueryWrapper<FinInvoicesItems>()
+				.eq(FinInvoicesItems::getTenantId, AuthUtil.getTenantId())
+				.eq(FinInvoicesItems::getIsDeleted, 0)
+				.in(FinInvoicesItems::getAccBillId, finAccBillsIds));
+			if (!finInvoicesItems.isEmpty()) {
+				List<Long> finInvoicesIds = finInvoicesItems.stream().map(FinInvoicesItems::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+				String finInvoices = finInvoicesMapper.selectList(new LambdaQueryWrapper<FinInvoices>()
+					.eq(FinInvoices::getTenantId, AuthUtil.getTenantId())
+					.eq(FinInvoices::getIsDeleted, 0)
+					.in(FinInvoices::getId, finInvoicesIds)).stream().map(FinInvoices::getBillNo).collect(Collectors.joining(","));
+				throw new RuntimeException("账单已生成发票单,撤销失败! 发票单号为:" + finInvoices);
+			}
+			List<FinStlBillsItems> finStlBillsItemsCHK = finStlBillsItemsMapper.selectList(new LambdaQueryWrapper<FinStlBillsItems>()
+				.eq(FinStlBillsItems::getTenantId, AuthUtil.getTenantId())
+				.eq(FinStlBillsItems::getIsDeleted, 0)
+				.eq(FinStlBillsItems::getItemType, "CHK")
+				.in(FinStlBillsItems::getAccBillId, finAccBillsIds));
+			if (!finStlBillsItemsCHK.isEmpty()) {
+				List<Long> finStlBillsIds = finStlBillsItemsCHK.stream().map(FinStlBillsItems::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+				String finStlBills = finStlBillsMapper.selectList(new LambdaQueryWrapper<FinStlBills>()
+					.eq(FinStlBills::getTenantId, AuthUtil.getTenantId())
+					.eq(FinStlBills::getIsDeleted, 0)
+					.in(FinStlBills::getId, finStlBillsIds)).stream().map(FinStlBills::getBillNo).collect(Collectors.joining(","));
+				throw new RuntimeException("账单已生成对账单,撤销失败! 对账单号为:" + finStlBills);
+			}
+			List<FinStlBillsItems> finStlBillsItemsSTLD = finStlBillsItemsMapper.selectList(new LambdaQueryWrapper<FinStlBillsItems>()
+				.eq(FinStlBillsItems::getTenantId, AuthUtil.getTenantId())
+				.eq(FinStlBillsItems::getIsDeleted, 0)
+				.eq(FinStlBillsItems::getItemType, "STL")
+				.eq(FinStlBillsItems::getDc, "D")
+				.in(FinStlBillsItems::getAccBillId, finAccBillsIds));
+			if (!finStlBillsItemsSTLD.isEmpty()) {
+				List<Long> finStlBillsIds = finStlBillsItemsSTLD.stream().map(FinStlBillsItems::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+				String finStlBills = finStlBillsMapper.selectList(new LambdaQueryWrapper<FinStlBills>()
+					.eq(FinStlBills::getTenantId, AuthUtil.getTenantId())
+					.eq(FinStlBills::getIsDeleted, 0)
+					.in(FinStlBills::getId, finStlBillsIds)).stream().map(FinStlBills::getBillNo).collect(Collectors.joining(","));
+				throw new RuntimeException("账单已生成收款单,撤销失败! 收款单号为:" + finStlBills);
+			}
+			List<FinStlBillsItems> finStlBillsItemsSTLC = finStlBillsItemsMapper.selectList(new LambdaQueryWrapper<FinStlBillsItems>()
+				.eq(FinStlBillsItems::getTenantId, AuthUtil.getTenantId())
+				.eq(FinStlBillsItems::getIsDeleted, 0)
+				.eq(FinStlBillsItems::getItemType, "STL")
+				.eq(FinStlBillsItems::getDc, "C")
+				.in(FinStlBillsItems::getAccBillId, finAccBillsIds));
+			if (!finStlBillsItemsSTLC.isEmpty()) {
+				List<Long> finStlBillsIds = finStlBillsItemsSTLC.stream().map(FinStlBillsItems::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+				String finStlBills = finStlBillsMapper.selectList(new LambdaQueryWrapper<FinStlBills>()
+					.eq(FinStlBills::getTenantId, AuthUtil.getTenantId())
+					.eq(FinStlBills::getIsDeleted, 0)
+					.in(FinStlBills::getId, finStlBillsIds)).stream().map(FinStlBills::getBillNo).collect(Collectors.joining(","));
+				throw new RuntimeException("账单已生成付款单,撤销失败! 付款单号为:" + finStlBills);
+			}
+			List<FinStlBillsItems> finStlBillsItemsFFSQ = finStlBillsItemsMapper.selectList(new LambdaQueryWrapper<FinStlBillsItems>()
+				.eq(FinStlBillsItems::getTenantId, AuthUtil.getTenantId())
+				.eq(FinStlBillsItems::getIsDeleted, 0)
+				.eq(FinStlBillsItems::getItemType, "FFSQ")
+				.in(FinStlBillsItems::getAccBillId, finAccBillsIds));
+			if (!finStlBillsItemsFFSQ.isEmpty()) {
+				List<Long> finStlBillsIds = finStlBillsItemsFFSQ.stream().map(FinStlBillsItems::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+				String finStlBills = finStlBillsMapper.selectList(new LambdaQueryWrapper<FinStlBills>()
+					.eq(FinStlBills::getTenantId, AuthUtil.getTenantId())
+					.eq(FinStlBills::getIsDeleted, 0)
+					.in(FinStlBills::getId, finStlBillsIds)).stream().map(FinStlBills::getBillNo).collect(Collectors.joining(","));
+				throw new RuntimeException("账单已付费申请,撤销失败! 付费申请单号为:" + finStlBills);
+			}
+			List<FinVouchersItems> finVouchersItems = finVouchersItemsMapper.selectList(new LambdaQueryWrapper<FinVouchersItems>()
+				.eq(FinVouchersItems::getTenantId, AuthUtil.getTenantId())
+				.eq(FinVouchersItems::getIsDeleted, 0)
+				.apply("find_in_set(bill_no,'" + finAccBillsBillNo + "')"));
+			if (!finVouchersItems.isEmpty()) {
+				List<Long> finStlBillsIds = finVouchersItems.stream().map(FinVouchersItems::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+				String finVouchers = finStlBillsMapper.selectList(new LambdaQueryWrapper<FinStlBills>()
+					.eq(FinStlBills::getTenantId, AuthUtil.getTenantId())
+					.eq(FinStlBills::getIsDeleted, 0)
+					.in(FinStlBills::getId, finStlBillsIds)).stream().map(FinStlBills::getBillNo).collect(Collectors.joining(","));
+				throw new RuntimeException("账单已生成凭证,撤销失败! 凭证单号为:" + finVouchers);
+			}
+		} else {
+			throw new RuntimeException("未找到账单信息");
+		}
+		this.removeByIds(finAccBillsIds);
+		List<FeeCenter> feeCenterList1 = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+			.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+			.eq(FeeCenter::getIsDeleted, 0)
+			.in(FeeCenter::getAccBillId, finAccBillsIds));
+		for (FeeCenter feeCenterItem : feeCenterList1) {
+			if (0 == feeCenterItem.getAccStatus()) {
+				throw new RuntimeException("费用:" + feeCenterItem.getFeeCnName() + "未生成账单,撤销失败");
+			}
+			feeCenterItem.setAccBillId(0L);
+			feeCenterItem.setAccBillNo("");
+			feeCenterItem.setAccDate(null);
+			feeCenterItem.setAccAmount(new BigDecimal("0.00"));
+			feeCenterItem.setAccStatus(0);
+			feeCenterItem.setAccById(0L);
+			feeCenterItem.setAccByName("");
+			feeCenterList.add(feeCenterItem);
+		}
+		feeCenterService.saveOrUpdateBatch(feeCenterList);
+		for (Bills item : billsList) {
+			if (item.getBillingStatus() == 0) {
+				throw new RuntimeException("撤销账单失败");
+			}
+			item.setBillingStatus(item.getBillingStatus() - finAccBillsIds.size());
+			billsMapper.updateById(item);
+		}
+		return R.data("操作成功");
+	}
+
 	private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
 		Set<Object> seen = ConcurrentHashMap.newKeySet();
 		return t -> seen.add(keyExtractor.apply(t));