ソースを参照

1.箱轨迹海运单据记录动态日期取值修改
2.增加打印费用账单验证提示接口
3.海运出口保存,配箱列表保存增加箱号为空判断
4.发送下货纸相关接口逻辑修改
5.无货返空计算超期箱使费主单为生成费用明细和账单
6.增加app-业务员箱量统计接口
7.app统计,客户走货分析接口逻辑完善及调试

纪新园 1 日 前
コミット
7df0b01df7
17 ファイル変更580 行追加191 行削除
  1. 0 27
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/AppStatistics.java
  2. 4 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/UnshippedGoodsAnalysis.java
  3. 56 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/VoteAndLineCount.java
  4. 2 1
      blade-service/blade-los/src/main/java/org/springblade/los/Util/ArchivesTrajectoryUtils.java
  5. 199 74
      blade-service/blade-los/src/main/java/org/springblade/los/Util/BillUtils.java
  6. 2 0
      blade-service/blade-los/src/main/java/org/springblade/los/Util/IBillUtils.java
  7. 143 3
      blade-service/blade-los/src/main/java/org/springblade/los/Util/OwBoxUsageFeeUtils.java
  8. 2 1
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsMapper.java
  9. 50 13
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsMapper.xml
  10. 2 0
      blade-service/blade-los/src/main/java/org/springblade/los/box/controller/RouteCostController.java
  11. 8 0
      blade-service/blade-los/src/main/java/org/springblade/los/business/sea/controller/BillsController.java
  12. 5 0
      blade-service/blade-los/src/main/java/org/springblade/los/business/sea/service/impl/BillsServiceImpl.java
  13. 5 8
      blade-service/blade-los/src/main/java/org/springblade/los/business/sea/service/impl/ContainersServiceImpl.java
  14. 12 26
      blade-service/blade-los/src/main/java/org/springblade/los/excel/DeliveryPaperExcel.java
  15. 14 5
      blade-service/blade-los/src/main/java/org/springblade/los/statisticAnalysis/controller/StatisticAnalysisController.java
  16. 4 2
      blade-service/blade-los/src/main/java/org/springblade/los/statisticAnalysis/service/IStatisticAnalysisService.java
  17. 72 31
      blade-service/blade-los/src/main/java/org/springblade/los/statisticAnalysis/service/impl/StatisticAnalysisServiceImpl.java

+ 0 - 27
blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/AppStatistics.java

@@ -1,27 +0,0 @@
-package org.springblade.los.statisticAnalysis;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * @author :jixinyuan
- * @date : 2023/11/29
- */
-@Data
-public class AppStatistics {
-
-	/**
-	 * 名称
-	 */
-	private String name;
-	/**
-	 * 数量
-	 */
-	private Long number;
-
-
-
-
-}

+ 4 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/UnshippedGoodsAnalysis.java

@@ -29,6 +29,10 @@ public class UnshippedGoodsAnalysis {
 	 * 未走货天数
 	 */
 	private String unshippedGoodsDays;
+	/**
+	 * 租户
+	 */
+	private String tenantId;
 
 
 }

+ 56 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/VoteAndLineCount.java

@@ -0,0 +1,56 @@
+package org.springblade.los.statisticAnalysis;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author :jixinyuan
+ * @date : 2023/11/29
+ */
+@Data
+public class VoteAndLineCount {
+
+	/**
+	 * 业务员
+	 */
+	private String salesman;
+	/**
+	 * 操作员
+	 */
+	private String operatorName;
+	/**
+	 * 航线
+	 */
+	private String lineName;
+	/**
+	 * 数量
+	 */
+	private Long number;
+	/**
+	 * TEU
+	 */
+	private Integer teu;
+	/**
+	 * 业务类型
+	 */
+	private String businessType;
+	/**
+	 * 租户
+	 */
+	private String tenantId;
+	/**
+	 * 所属公司
+	 */
+	private String branchId;
+	/**
+	 * 开始日期
+	 */
+	private String startDate;
+	/**
+	 * 结束日期
+	 */
+	private String endDate;
+
+
+}

+ 2 - 1
blade-service/blade-los/src/main/java/org/springblade/los/Util/ArchivesTrajectoryUtils.java

@@ -208,6 +208,7 @@ public class ArchivesTrajectoryUtils {
 					archivesTrajectory.setBoxDynamics("装船");
 					archivesTrajectory.setStatus("装船");
 					archivesTrajectory.setEtd(bills.getActualEtd());
+					archivesTrajectory.setNewDate(bills.getActualEtd());
 				} else if ("SI".equals(bills.getBusinessType())) {
 					archivesTrajectory.setPortId(bills.getPodId());
 					archivesTrajectory.setPortCode(bills.getPodCode());
@@ -220,13 +221,13 @@ public class ArchivesTrajectoryUtils {
 					archivesTrajectory.setBoxDynamics("卸船");
 					archivesTrajectory.setStatus("卸船");
 					archivesTrajectory.setEtd(bills.getActualEta());
+					archivesTrajectory.setNewDate(bills.getActualEta());
 				}
 				archivesTrajectory.setContainerNumber(item.getContainerNumber());
 				archivesTrajectory.setBoxType(item.getCntrTypeCode());
 				archivesTrajectory.setBoxCategory(item.getBoxSrcType());
 				archivesTrajectory.setMblno(item.getMblno());
 				archivesTrajectory.setHblno(item.getHblno());
-				archivesTrajectory.setNewDate(new Date());
 				archivesTrajectory.setPodId(bills.getPodId());
 				archivesTrajectory.setPodCode(bills.getPodCode());
 				archivesTrajectory.setPodCname(bills.getPodCnName());

+ 199 - 74
blade-service/blade-los/src/main/java/org/springblade/los/Util/BillUtils.java

@@ -9,7 +9,6 @@ import org.springblade.client.entity.Message;
 import org.springblade.client.feign.IMessageClient;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
-import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.los.basic.business.entity.BusinessType;
 import org.springblade.los.basic.business.service.IBusinessTypeService;
@@ -136,8 +135,8 @@ public class BillUtils implements IBillUtils {
 			containersService.updateBatchById(containersList);
 			List<Containers> containersListNew = new ArrayList<>();
 			for (Containers item : containersList) {
-				Bills bills1 = billsList.stream().filter(e-> e.getId().equals(item.getPid())).findFirst().orElse(null);
-				if (bills1 != null){
+				Bills bills1 = billsList.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(null);
+				if (bills1 != null) {
 					item.setMarks(bills1.getMarks());
 				}
 				item.setSrcSplitOrderId(item.getPid());
@@ -1030,7 +1029,19 @@ public class BillUtils implements IBillUtils {
 		if (ObjectUtils.isNull(ids)) {
 			throw new RuntimeException("缺少必要参数");
 		}
-		List<Long> idList = Func.toLongList(ids);
+		List<Long> idList = new ArrayList<>();
+		Bills bills = billsMapper.selectById(ids);
+		if ("MM".equals(bills.getBillType())) {
+			List<Bills> billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
+				.eq(Bills::getIsDeleted, 0)
+				.eq(Bills::getMasterId, bills.getId()));
+			if (billsList.isEmpty()) {
+				throw new RuntimeException("未查到海运出口单据,发送失败!");
+			}
+			idList.addAll(billsList.stream().map(Bills::getId).collect(Collectors.toList()));
+		} else {
+			idList.add(bills.getId());
+		}
 		List<Bills> billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
 			.eq(Bills::getIsDeleted, 0)
 			.in(Bills::getId, idList));
@@ -1048,35 +1059,32 @@ public class BillUtils implements IBillUtils {
 			.in(SeaContainerNumberItem::getPid, idList)
 			.in(SeaContainerNumberItem::getBoxType, preContainersList.stream().map(PreContainers::getCntrTypeCode)
 				.distinct().collect(Collectors.toList())));
-		if (containerNumberItemList.isEmpty()) {
-			throw new RuntimeException("未选择放箱号,发送失败!");
+		if (!containerNumberItemList.isEmpty()) {
+			for (Bills item : billsList) {
+				if (containerNumberItemList.stream().noneMatch(e -> e.getPid().equals(item.getId()))) {
+					throw new RuntimeException("分单号:" + item.getHblno() + "未选择放箱号,发送失败!");
+				}
+			}
 		}
 		List<DeliveryPaperExcel> excelList = new ArrayList<>();
-		for (Bills item : billsList) {
+		for (PreContainers item : preContainersList) {
 			DeliveryPaperExcel excel = new DeliveryPaperExcel();
-			excel.setEtd(item.getEtd());
-			excel.setPodEnName(item.getPodEnName());
-			excel.setVesselCnName(item.getVesselEnName());
-			excel.setVoyageNo(item.getVoyageNo());
-			excel.setBoxOwner("WFL");
-			excel.setInboundContainerOwner(item.getCarrierEnName());
-			excel.setPotEnName(item.getPotEnName());
-			excel.setMblno(item.getMblno());
-			excel.setHblno(item.getHblno());
-			excel.setQuantityCntrDescr(item.getQuantityCntrDescr());
-			excel.setGrossWeight(item.getGrossWeight());
-			String containerNumber = "";
-			List<PreContainers> preContainers = preContainersList.stream().filter(e -> e.getPid().equals(item.getId()))
-				.collect(Collectors.toList());
-			for (PreContainers containers : preContainers) {
-				List<SeaContainerNumberItem> containerNumberItems = containerNumberItemList.stream().filter(e ->
-					containers.getCntrTypeCode().equals(e.getBoxType()) && 0 != e.getOccupyNum()).collect(Collectors.toList());
-				for (SeaContainerNumberItem numberItem : containerNumberItems) {
-					containerNumber = containerNumber + numberItem.getContainerNumber() + " " + numberItem.getOccupyNum() + "*" +
-						containers.getCntrTypeCode() + "\n";
-				}
+			Bills bills1 = billsList.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(null);
+			if (bills1 != null) {
+				excel.setVesselCnName(bills1.getVesselEnName() + " " + bills1.getVoyageNo());
+				excel.setHblno(bills1.getHblno());
+				excel.setQuantityCntrDescr(bills1.getQuantityCntrDescr());
+				excel.setPodEnName(bills1.getPodEnName());
+				excel.setMblno(bills1.getMblno());
 			}
-			excel.setContainerNumber(containerNumber);
+			SeaContainerNumberItem containerNumberItems = containerNumberItemList.stream().filter(e ->
+					item.getCntrTypeCode().equals(e.getBoxType()) && 0 != e.getOccupyNum() && e.getPid().equals(item.getPid()))
+				.findFirst().orElse(null);
+			if (containerNumberItems != null) {
+				excel.setContainerNumber(containerNumberItems.getContainerNumber());
+				excel.setStationCname(containerNumberItems.getPolStationCname());
+			}
+			excel.setRemarks("");
 			excelList.add(excel);
 		}
 		return excelList;
@@ -1088,7 +1096,19 @@ public class BillUtils implements IBillUtils {
 		if (ObjectUtils.isNull(ids)) {
 			throw new RuntimeException("缺少必要参数");
 		}
-		List<Long> idList = Func.toLongList(ids);
+		List<Long> idList = new ArrayList<>();
+		Bills bills = billsMapper.selectById(ids);
+		if ("MM".equals(bills.getBillType())) {
+			List<Bills> billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
+				.eq(Bills::getIsDeleted, 0)
+				.eq(Bills::getMasterId, bills.getId()));
+			if (billsList.isEmpty()) {
+				throw new RuntimeException("未查到海运出口单据,发送失败!");
+			}
+			idList.addAll(billsList.stream().map(Bills::getId).collect(Collectors.toList()));
+		} else {
+			idList.add(bills.getId());
+		}
 		List<Bills> billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
 			.eq(Bills::getIsDeleted, 0)
 			.in(Bills::getId, idList));
@@ -1106,35 +1126,32 @@ public class BillUtils implements IBillUtils {
 			.in(SeaContainerNumberItem::getPid, idList)
 			.in(SeaContainerNumberItem::getBoxType, preContainersList.stream().map(PreContainers::getCntrTypeCode)
 				.distinct().collect(Collectors.toList())));
-		if (containerNumberItemList.isEmpty()) {
-			throw new RuntimeException("未选择放箱号,发送失败!");
+		if (!containerNumberItemList.isEmpty()) {
+			for (Bills item : billsList) {
+				if (containerNumberItemList.stream().noneMatch(e -> e.getPid().equals(item.getId()))) {
+					throw new RuntimeException("分单号:" + item.getHblno() + "未选择放箱号,发送失败!");
+				}
+			}
 		}
 		List<DeliveryPaperExcel> excelList = new ArrayList<>();
-		for (Bills item : billsList) {
+		for (PreContainers item : preContainersList) {
 			DeliveryPaperExcel excel = new DeliveryPaperExcel();
-			excel.setEtd(item.getEtd());
-			excel.setPodEnName(item.getPodEnName());
-			excel.setVesselCnName(item.getVesselEnName());
-			excel.setVoyageNo(item.getVoyageNo());
-			excel.setBoxOwner("WFL");
-			excel.setInboundContainerOwner(item.getCarrierEnName());
-			excel.setPotEnName(item.getPotEnName());
-			excel.setMblno(item.getMblno());
-			excel.setHblno(item.getHblno());
-			excel.setQuantityCntrDescr(item.getQuantityCntrDescr());
-			excel.setGrossWeight(item.getGrossWeight());
-			String containerNumber = "";
-			List<PreContainers> preContainers = preContainersList.stream().filter(e -> e.getPid().equals(item.getId()))
-				.collect(Collectors.toList());
-			for (PreContainers containers : preContainers) {
-				List<SeaContainerNumberItem> containerNumberItems = containerNumberItemList.stream().filter(e ->
-					containers.getCntrTypeCode().equals(e.getBoxType()) && 0 != e.getOccupyNum()).collect(Collectors.toList());
-				for (SeaContainerNumberItem numberItem : containerNumberItems) {
-					containerNumber = containerNumber + numberItem.getContainerNumber() + " " + numberItem.getOccupyNum() + "*" +
-						containers.getCntrTypeCode() + "\n";
-				}
+			Bills bills1 = billsList.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(null);
+			if (bills1 != null) {
+				excel.setVesselCnName(bills1.getVesselEnName() + " " + bills1.getVoyageNo());
+				excel.setHblno(bills1.getHblno());
+				excel.setQuantityCntrDescr(bills1.getQuantityCntrDescr());
+				excel.setPodEnName(bills1.getPodEnName());
+				excel.setMblno(bills1.getMblno());
 			}
-			excel.setContainerNumber(containerNumber);
+			SeaContainerNumberItem containerNumberItems = containerNumberItemList.stream().filter(e ->
+					item.getCntrTypeCode().equals(e.getBoxType()) && 0 != e.getOccupyNum() && e.getPid().equals(item.getPid()))
+				.findFirst().orElse(null);
+			if (containerNumberItems != null) {
+				excel.setContainerNumber(containerNumberItems.getContainerNumber());
+				excel.setStationCname(containerNumberItems.getPolStationCname());
+			}
+			excel.setRemarks("");
 			excelList.add(excel);
 		}
 		return R.data(excelList);
@@ -1149,6 +1166,24 @@ public class BillUtils implements IBillUtils {
 		if (bills == null) {
 			throw new RuntimeException("未查到海运出口单据,发送失败!");
 		}
+		List<Long> idList = new ArrayList<>();
+		if ("MM".equals(bills.getBillType())) {
+			List<Bills> billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
+				.eq(Bills::getIsDeleted, 0)
+				.eq(Bills::getMasterId, bills.getId()));
+			if (billsList.isEmpty()) {
+				throw new RuntimeException("未查到海运出口单据,发送失败!");
+			}
+			idList.addAll(billsList.stream().map(Bills::getId).collect(Collectors.toList()));
+		} else {
+			idList.add(bills.getId());
+		}
+		List<Bills> billsList = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
+			.eq(Bills::getIsDeleted, 0)
+			.in(Bills::getId, idList));
+		if (billsList.isEmpty()) {
+			throw new RuntimeException("未查到海运出口单据,发送失败!");
+		}
 		StringBuilder text = new StringBuilder();
 		StringBuilder messageBody = new StringBuilder();
 		if ("SOC".equals(bills.getBoxBelongsTo()) && "DD,MH".contains(bills.getBillType())) {
@@ -1173,23 +1208,23 @@ public class BillUtils implements IBillUtils {
 			}
 			List<PreContainers> preContainersList = preContainersService.list(new LambdaQueryWrapper<PreContainers>()
 				.eq(PreContainers::getIsDeleted, 0)
-				.eq(PreContainers::getPid, ids));
+				.in(PreContainers::getPid, idList));
 			if (preContainersList.isEmpty()) {
 				throw new RuntimeException("未查到预配箱型信息,发送失败!");
 			}
 			List<SeaContainerNumberItem> containerNumberItemList = seaContainerNumberItemService.list(new LambdaQueryWrapper<SeaContainerNumberItem>()
 				.eq(SeaContainerNumberItem::getIsDeleted, 0)
-				.eq(SeaContainerNumberItem::getPid, ids)
-				.in(SeaContainerNumberItem::getBoxType, preContainersList.stream().map(PreContainers::getCntrTypeCode)
-					.distinct().collect(Collectors.toList())));
-			if (containerNumberItemList.isEmpty()) {
-				throw new RuntimeException("未选择放箱号,发送失败!");
+				.in(SeaContainerNumberItem::getPid, idList));
+			if (!containerNumberItemList.isEmpty()) {
+				if (containerNumberItemList.stream().noneMatch(e -> e.getPid().equals(bills.getId()))) {
+					throw new RuntimeException("未选择放箱号,发送失败!");
+				}
 			}
 			List<FeeCenter> feeCenterList = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
 				.eq(FeeCenter::getIsDeleted, 0)
 				.eq(FeeCenter::getDc, "D")
 				.eq(FeeCenter::getFeeCode, "HYF")
-				.eq(FeeCenter::getPid, ids));
+				.in(FeeCenter::getPid, idList));
 			if (feeCenterList.isEmpty()) {
 				throw new RuntimeException("未查到应收海运费,发送失败!");
 			}
@@ -1206,18 +1241,22 @@ public class BillUtils implements IBillUtils {
 			boolean status = bills.getEtd().compareTo(date) >= 0;
 			if (status) {
 				for (PreContainers containers : preContainersList) {
-					BigDecimal price = feeCenterList.stream().filter(e -> containers.getCntrTypeCode().equals(e.getUnitNo()))
-						.map(FeeCenter::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
-					List<RouteCostItem> minCostItem = costItemList.stream().filter(e -> containers.getCntrTypeCode().equals(e.getBoxType()))
-						.sorted(Comparator.comparing(RouteCostItem::getSalesPrice))
-						.collect(Collectors.toList());
-					if (price.compareTo(minCostItem.get(0).getSalesPrice()) < 0) {
-						text.append("提单号:").append(bills.getMblno()).append("箱型:").append(containers.getCntrTypeCode()).append("应收海运费:" + price + "小于成本中心海运费:" + minCostItem.get(0).getSalesPrice() + "!");
-						messageBody.append("提单号:").append(bills.getMblno()).append("应收海运费:" + price + "小于成本中心海运费:" + minCostItem.get(0).getSalesPrice() + "!");
-					}
-					if (containerNumberItemList.stream().filter(e -> e.getBoxType().equals(containers.getCntrTypeCode()))
-						.mapToInt(SeaContainerNumberItem::getOccupyNum).sum() != containers.getQuantity()) {
-						text.append("提单号:").append(bills.getMblno()).append("箱型:").append(containers.getCntrTypeCode()).append("箱量与所选放箱号数量不等!");
+					Bills bills1 = billsList.stream().filter(e -> e.getId().equals(containers.getPid())).findFirst().orElse(null);
+					if (bills1 != null) {
+						BigDecimal price = feeCenterList.stream().filter(e -> containers.getCntrTypeCode().equals(e.getUnitNo())
+							&& containers.getPid().equals(e.getPid())).map(FeeCenter::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
+						List<RouteCostItem> minCostItem = costItemList.stream().filter(e -> containers.getCntrTypeCode().equals(e.getBoxType()))
+							.sorted(Comparator.comparing(RouteCostItem::getSalesPrice))
+							.collect(Collectors.toList());
+						if (price.compareTo(minCostItem.get(0).getSalesPrice()) < 0) {
+							text.append("提单号:").append(bills1.getHblno()).append("箱型:").append(containers.getCntrTypeCode()).append("应收海运费:" + price + "小于成本中心海运费:" + minCostItem.get(0).getSalesPrice() + "!");
+							messageBody.append("提单号:").append(bills1.getHblno()).append("应收海运费:").append(price).append("小于成本中心海运费:").append(minCostItem.get(0).getSalesPrice()).append("!");
+						}
+						if (containerNumberItemList.stream().filter(e -> e.getBoxType().equals(containers.getCntrTypeCode())
+								&& containers.getPid().equals(e.getPid()))
+							.mapToInt(SeaContainerNumberItem::getOccupyNum).sum() != containers.getQuantity()) {
+							text.append("提单号:").append(bills1.getHblno()).append("箱型:").append(containers.getCntrTypeCode()).append("箱量与所选放箱号数量不等!");
+						}
 					}
 				}
 			}
@@ -1234,4 +1273,90 @@ public class BillUtils implements IBillUtils {
 			return R.success("操作成功");
 		}
 	}
+
+	@Override
+	public R billVerificationPrompt(String ids) {
+		if (ObjectUtils.isNull(ids)) {
+			throw new RuntimeException("缺少必要参数,发送失败!");
+		}
+		Bills bills = billsMapper.selectById(ids);
+		if (bills == null) {
+			throw new RuntimeException("未查到海运出口单据,发送失败!");
+		}
+		if (!"MM".equals(bills.getBillType())) {
+			StringBuilder text = new StringBuilder();
+			StringBuilder messageBody = new StringBuilder();
+			if ("SOC".equals(bills.getBoxBelongsTo()) && "DD,MH".contains(bills.getBillType())) {
+				SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+				List<RouteCost> costList = routeCostService.list(new LambdaQueryWrapper<RouteCost>()
+					.eq(RouteCost::getPodId, bills.getPolId())
+					.eq(RouteCost::getDestinationId, bills.getPodId())
+					.eq(RouteCost::getShippingCompanyId, bills.getCarrierId())
+					.eq(RouteCost::getBusinessType, bills.getBoxBelongsTo())
+					.apply("DATE_FORMAT(effective_start_date,'%Y-%m-%d') <= '" + formatter.format(bills.getEtd()) + "'")
+					.apply("DATE_FORMAT(effective_end_date,'%Y-%m-%d') >= '" + formatter.format(bills.getEtd()) + "'")
+				);
+				if (costList.isEmpty()) {
+					throw new RuntimeException("请先维护成本!");
+				}
+				List<RouteCostItem> costItemList = routeCostItemService.list(new LambdaQueryWrapper<RouteCostItem>()
+					.eq(RouteCostItem::getIsDeleted, 0)
+					.eq(RouteCostItem::getTenantId, AuthUtil.getTenantId())
+					.in(RouteCostItem::getPid, costList.stream().map(RouteCost::getId).collect(Collectors.toList())));
+				if (costItemList.isEmpty()) {
+					throw new RuntimeException("请先维护成本!");
+				}
+				List<PreContainers> preContainersList = preContainersService.list(new LambdaQueryWrapper<PreContainers>()
+					.eq(PreContainers::getIsDeleted, 0)
+					.eq(PreContainers::getPid, bills.getId()));
+				if (preContainersList.isEmpty()) {
+					throw new RuntimeException("未查到预配箱型信息");
+				}
+				List<FeeCenter> feeCenterList = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+					.eq(FeeCenter::getIsDeleted, 0)
+					.eq(FeeCenter::getDc, "D")
+					.eq(FeeCenter::getFeeCode, "HYF")
+					.eq(FeeCenter::getPid, bills.getId()));
+				if (feeCenterList.isEmpty()) {
+					throw new RuntimeException("未查到应收海运费");
+				}
+				String boxBusinessConnectionTime = sysClient.getParamService("box.business.connection.time");
+				Date date = null;
+				DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+				if (ObjectUtils.isNotNull(boxBusinessConnectionTime)) {
+					try {
+						date = dateFormat.parse(boxBusinessConnectionTime);
+					} catch (ParseException e) {
+						throw new RuntimeException(e);
+					}
+				}
+				boolean status = bills.getEtd().compareTo(date) >= 0;
+				if (status) {
+					for (PreContainers containers : preContainersList) {
+						BigDecimal price = feeCenterList.stream().filter(e -> containers.getCntrTypeCode().equals(e.getUnitNo())
+							&& containers.getPid().equals(e.getPid())).map(FeeCenter::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
+						List<RouteCostItem> minCostItem = costItemList.stream().filter(e -> containers.getCntrTypeCode().equals(e.getBoxType()))
+							.sorted(Comparator.comparing(RouteCostItem::getSalesPrice))
+							.collect(Collectors.toList());
+						if (price.compareTo(minCostItem.get(0).getSalesPrice()) < 0) {
+							text.append("提单号:").append(bills.getHblno()).append("箱型:").append(containers.getCntrTypeCode()).append("应收海运费:" + price + "小于成本中心海运费:" + minCostItem.get(0).getSalesPrice() + "!");
+							messageBody.append("提单号:").append(bills.getHblno()).append("应收海运费:").append(price).append("小于成本中心海运费:").append(minCostItem.get(0).getSalesPrice()).append("!");
+						}
+					}
+				}
+			}
+			if (ObjectUtils.isNotNull(text.toString())) {
+				String url = "/iosBasicData/OceanFreightImport/bills/index";
+				String pageLabel = "海运出口";
+				String pageStatus = "this.$store.getters.domSaleStatus";
+				messageBody.append("发送人:").append(AuthUtil.getUserName());
+				this.sendMessage(bills, url, pageLabel, pageStatus, messageBody.toString(), "2", bills.getOperatorId(), "成本中心");
+				throw new RuntimeException(text.toString());
+			} else {
+				return R.success("操作成功");
+			}
+		} else {
+			return R.success("操作成功");
+		}
+	}
 }

+ 2 - 0
blade-service/blade-los/src/main/java/org/springblade/los/Util/IBillUtils.java

@@ -50,4 +50,6 @@ public interface IBillUtils {
 	R sendDeliveryPaper(String ids);
 
 	R sendVerificationPrompt(String ids);
+
+	R billVerificationPrompt(String ids);
 }

+ 143 - 3
blade-service/blade-los/src/main/java/org/springblade/los/Util/OwBoxUsageFeeUtils.java

@@ -781,27 +781,167 @@ public class OwBoxUsageFeeUtils {
 			tradingBoxItemService.saveOrUpdateBatch(tradingBoxItemOldList);
 		}
 		List<FeeCenter> feeCenterList = new ArrayList<>();
+		List<Long> billIdList = billsList.stream().map(Bills::getId).collect(Collectors.toList());
+		List<FeeCenter> feeCenterListAcc = new ArrayList<>();
+		if (!billIdList.isEmpty()) {
+			feeCenterList = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+				.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+				.eq(FeeCenter::getIsDeleted, 0)
+				.in(FeeCenter::getPid, billIdList));
+		}
+		if (feeCenterList.isEmpty()) {
+			feeCenterList = new ArrayList<>();
+		}
 		if (!feeCenterListD.isEmpty()) {
 			feeCenterService.saveBatch(feeCenterListD);
 			feeCenterList.addAll(feeCenterListD);
+			feeCenterListAcc.addAll(feeCenterListD);
 		}
 		if (!feeCenterListC.isEmpty()) {
 			feeCenterService.saveBatch(feeCenterListC);
 			feeCenterList.addAll(feeCenterListC);
+			feeCenterListAcc.addAll(feeCenterListC);
+			List<Long> idListMh = feeCenterListC.stream().map(FeeCenter::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+			List<Bills> billsArrayList = billsList.stream().filter(e -> idListMh.contains(e.getId())).collect(Collectors.toList());
+			if (!billsArrayList.isEmpty()) {
+				List<Long> masterIdList = billsArrayList.stream().filter(e -> "MH".equals(e.getBillType())).map(Bills::getMasterId)
+					.filter(Objects::nonNull).distinct().collect(Collectors.toList());
+				if (!masterIdList.isEmpty()) {
+					List<Bills> billsList1 = billsMapper.selectList(new LambdaQueryWrapper<Bills>()
+						.eq(Bills::getTenantId, AuthUtil.getTenantId())
+						.eq(Bills::getIsDeleted, 0)
+						.in(Bills::getId, masterIdList));
+					List<FeeCenter> feeCenterListM = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+						.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+						.eq(FeeCenter::getIsDeleted, 0)
+						.in(FeeCenter::getPid, masterIdList));
+					for (Bills item : billsArrayList) {
+						BCorps corps = bCorpsService.getOne(new LambdaQueryWrapper<BCorps>()
+							.eq(BCorps::getTenantId, AuthUtil.getTenantId())
+							.eq(BCorps::getIsDeleted, 0)
+							.eq(BCorps::getEnName, item.getBranchName()));
+						if (corps == null) {
+							throw new RuntimeException("基础资料未查到往来单位" + item.getBranchName());
+						}
+						if (!billsList1.isEmpty()) {
+							Bills billsHYCKM = billsList1.stream().filter(e -> e.getId().equals(item.getMasterId())).findFirst().orElse(null);
+							if (billsHYCKM != null) {
+								BigDecimal amount = feeCenterListC.stream().filter(e -> e.getPid().equals(item.getId()))
+									.map(FeeCenter::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+								FeeCenter feeCenterD = new FeeCenter();
+								feeCenterD.setBookingAgentId(billsHYCKM.getBookingAgentId());
+								feeCenterD.setBookingAgentCnName(billsHYCKM.getBookingAgentCnName());
+								feeCenterD.setBookingAgentEnName(billsHYCKM.getBookingAgentEnName());
+								feeCenterD.setQuantityCntrDescr(billsHYCKM.getQuantityCntrDescr());
+								feeCenterD.setBillBranchId(billsHYCKM.getBranchId());
+								feeCenterD.setBillBranchName(billsHYCKM.getBranchName());
+								feeCenterD.setTeu(billsHYCKM.getTeu());
+								feeCenterD.setBranchId(billsHYCKM.getBranchId());
+								feeCenterD.setBranchName(billsHYCKM.getBranchName());
+								feeCenterD.setPid(billsHYCKM.getId());
+								feeCenterD.setCntrNo(billsHYCKM.getQuantityCntrTypesDescr());
+								feeCenterD.setBillNo(billsHYCKM.getBillNo());
+								feeCenterD.setBusinessType(billsHYCKM.getBusinessType());
+								feeCenterD.setBillType(billsHYCKM.getBillType());
+								feeCenterD.setBillDate(billsHYCKM.getBillDate());
+								feeCenterD.setBillCorpId(billsHYCKM.getCorpId());
+								feeCenterD.setBillCorpCnName(billsHYCKM.getCorpCnName());
+								feeCenterD.setBillCorpEnName(billsHYCKM.getCorpEnName());
+								feeCenterD.setBillShortName(billsHYCKM.getShortName());
+								feeCenterD.setLineId(billsHYCKM.getLineId());
+								feeCenterD.setLineCnName(billsHYCKM.getLineCnName());
+								feeCenterD.setLineEnName(billsHYCKM.getLineEnName());
+								feeCenterD.setVesselId(billsHYCKM.getVesselId());
+								feeCenterD.setVesselCnName(billsHYCKM.getVesselCnName());
+								feeCenterD.setVesselEnName(billsHYCKM.getVesselEnName());
+								feeCenterD.setVoyageNo(billsHYCKM.getVoyageNo());
+								feeCenterD.setMblno(billsHYCKM.getMblno());
+								feeCenterD.setHblno(item.getHblno());
+								feeCenterD.setEtd(billsHYCKM.getEtd());
+								feeCenterD.setEta(billsHYCKM.getEta());
+								feeCenterD.setPolId(billsHYCKM.getPolId());
+								feeCenterD.setPolCode(billsHYCKM.getPolCode());
+								feeCenterD.setPolCnName(billsHYCKM.getPolCnName());
+								feeCenterD.setPolEnName(billsHYCKM.getPolEnName());
+								feeCenterD.setPodId(billsHYCKM.getPodId());
+								feeCenterD.setPodCode(billsHYCKM.getPodCode());
+								feeCenterD.setPodCnName(billsHYCKM.getPodCnName());
+								feeCenterD.setPodEnName(billsHYCKM.getPodEnName());
+								feeCenterD.setPaymode(billsHYCKM.getMpaymode());
+								feeCenterD.setSort(1);
+								feeCenterD.setFeeId(fees.getId());
+								feeCenterD.setFeeCode(fees.getCode());
+								feeCenterD.setFeeCnName(fees.getCnName());
+								feeCenterD.setFeeEnName(fees.getEnName());
+								feeCenterD.setUnitNo("JOB");
+								feeCenterD.setCurCode(feeCenterListC.get(0).getCurCode());
+								feeCenterD.setExrate(feeCenterListC.get(0).getExrate());
+								feeCenterD.setDc("D");
+								feeCenterD.setCorpType("国内直接客户");
+
+								feeCenterD.setCorpId(corps.getId());
+								feeCenterD.setCorpCnName(corps.getCnName());
+								feeCenterD.setCorpEnName(corps.getEnName());
+								feeCenterD.setShortName(corps.getShortName());
+								feeCenterD.setGenerationCorpId(corps.getBookingAgentId());
+								feeCenterD.setGenerationCorpCnName(corps.getBookingAgentCnName());
+								feeCenterD.setGenerationCorpEnName(corps.getBookingAgentEnName());
+								feeCenterD.setQuantity(new BigDecimal("1"));
+								feeCenterD.setPrice(amount);
+								feeCenterD.setAmount(amount);
+								feeCenterD.setAmountLoc(amount.multiply(feeCenterD.getExrate()));
+								feeCenterD.setUnsettledAmount(feeCenterD.getAmount());
+								feeCenterD.setCreateUser(billsHYCKM.getOperatorId());
+								feeCenterD.setCreateUserName(billsHYCKM.getOperatorName());
+								feeCenterD.setCreateTime(new Date());
+								feeCenterService.save(feeCenterD);
+								feeCenterListAcc.add(feeCenterD);
+								List<FeeCenter> feeCenterListMs = feeCenterListM.stream().filter(e -> e.getPid().equals(billsHYCKM.getId()))
+									.collect(Collectors.toList());
+								if (feeCenterListMs.isEmpty()) {
+									feeCenterListMs = new ArrayList<>();
+								}
+								feeCenterListMs.add(feeCenterD);
+								//对应海运进口单据所属公司本位币
+								String exrateType = currencyUtils.standardCurrency(billsHYCKM.getBranchId());
+								Bills billsAmount = costProfitCalculationService.costProfitCalculation(feeCenterListMs, exrateType);
+								if (billsAmount != null) {
+									billsHYCKM.setAccountStatus(billsAmount.getAccountStatus());
+									billsHYCKM.setAmountDr(billsHYCKM.getAmountDr().add(billsAmount.getAmountDr()));
+									billsHYCKM.setOceanFreightDr(billsHYCKM.getOceanFreightDr().add(billsAmount.getOceanFreightDr()));
+									billsHYCKM.setAmountCr(billsHYCKM.getAmountCr().add(billsAmount.getAmountCr()));
+									billsHYCKM.setOceanFreightCr(billsHYCKM.getOceanFreightCr().add(billsAmount.getOceanFreightCr()));
+									billsHYCKM.setAmountProfit(billsHYCKM.getAmountProfit().add(billsAmount.getAmountProfit()));
+									billsHYCKM.setOceanFreightProfit(billsHYCKM.getOceanFreightProfit().add(billsAmount.getOceanFreightProfit()));
+									billsHYCKM.setAmountDrUsd(billsHYCKM.getAmountDrUsd().add(billsAmount.getAmountDrUsd()));
+									billsHYCKM.setAmountCrUsd(billsHYCKM.getAmountCrUsd().add(billsAmount.getAmountCrUsd()));
+									billsHYCKM.setAmountProfitUsd(billsHYCKM.getAmountProfitUsd().add(billsAmount.getAmountProfitUsd()));
+									billsHYCKM.setAmountDrLoc(billsHYCKM.getAmountDrLoc().add(billsAmount.getAmountDrLoc()));
+									billsHYCKM.setAmountCrLoc(billsHYCKM.getAmountCrLoc().add(billsAmount.getAmountCrLoc()));
+									billsHYCKM.setAmountProfitLoc(billsHYCKM.getAmountProfitLoc().add(billsAmount.getAmountProfitLoc()));
+									int version = StringUtil.isBlank(billsHYCKM.getVersion()) ? 1 : Integer.parseInt(billsHYCKM.getVersion());
+									billsHYCKM.setVersion(String.valueOf(version + 1));
+									billsMapper.updateById(billsHYCKM);
+								}
+							}
+						}
+					}
+				}
+			}
 		}
-		if (!feeCenterList.isEmpty()) {
+		if (!feeCenterListAcc.isEmpty()) {
 			List<Bills> billsLists = costProfitCalculationService.costProfitCalculationBatch(feeCenterList, billsList);
 			if (!billsLists.isEmpty()) {
 				for (Bills item : billsLists) {
 					int version = StringUtil.isBlank(item.getVersion()) ? 1 : Integer.parseInt(item.getVersion());
 					item.setVersion(String.valueOf(version + 1));
 					billsMapper.updateById(item);
-					List<FeeCenter> feeCenters = feeCenterList.stream().filter(e -> e.getPid().equals(item.getId()))
+					List<FeeCenter> feeCenters = feeCenterListAcc.stream().filter(e -> e.getPid().equals(item.getId()))
 						.collect(Collectors.toList());
 					String exrateType = currencyUtils.standardCurrency(item.getBranchId());
 					Boolean status = this.generateAccBills(feeCenters, item, exrateType, boxDynamicsRecord, type);
 					if (!status) {
-						failureHandling("1", boxDynamicsRecord, "提单号" + item.getHblno() + "超期箱使费生成账单失败");
+						failureHandling("3", boxDynamicsRecord, "提单号" + item.getHblno() + "超期箱使费生成账单失败");
 						return false;
 					}
 				}

+ 2 - 1
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsMapper.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.los.basic.corps.mapper;
 
+import org.apache.ibatis.annotations.Param;
 import org.springblade.los.basic.corps.entity.BCorps;
 import org.springblade.los.basic.corps.vo.BCorpsVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -41,5 +42,5 @@ public interface CorpsMapper extends BaseMapper<BCorps> {
 	 */
 	List<BCorpsVO> selectBCorpsPage(IPage page, BCorpsVO bCorps);
 
-    List<UnshippedGoodsAnalysis> unshippedGoodsAnalysis(UnshippedGoodsAnalysis unshippedGoodsAnalysis, IPage<UnshippedGoodsAnalysis> page);
+    List<UnshippedGoodsAnalysis> unshippedGoodsAnalysis(@Param("data") UnshippedGoodsAnalysis unshippedGoodsAnalysis, IPage<UnshippedGoodsAnalysis> page);
 }

+ 50 - 13
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsMapper.xml

@@ -104,41 +104,78 @@
     <select id="unshippedGoodsAnalysis"
             resultType="org.springblade.los.statisticAnalysis.UnshippedGoodsAnalysis">
         SELECT
-        corp.cn_name,
-        last_sea.bill_id
+        corp.cn_name as corpName,
+        (CASE last_sea.bill_status
+        WHEN  '0' THEN '接单'
+        WHEN  '1' THEN '退舱'
+        WHEN  '3' THEN '已完成'
+        ELSE '进行中' END) as businessStatus,
+        last_sea.bill_date as businessDate,
+        (CASE last_sea.business_type
+        WHEN  'SE' THEN '海运出口'
+        WHEN  'SI' THEN '海运进口'
+        ELSE '其他' END) as businessType
         FROM
         los_b_corps corp
         LEFT JOIN (
         SELECT
         sb.corp_id,
-        sb.etd,
-        sb.id as bill_id
+        (CASE sb.business_type
+        WHEN  'SE' THEN sb.actual_etd
+        WHEN  'SI' THEN sb.actual_eta
+        ELSE sb.bill_date END) as bill_date,
+        sb.bill_status as bill_status,
+        sb.business_type as business_type
         FROM
         los_sea_bills sb
         INNER JOIN (
         SELECT
         corp_id,
-        MAX(etd) as max_etd
+        (CASE business_type
+        WHEN  'SE' THEN MAX(actual_etd)
+        WHEN  'SI' THEN MAX(actual_eta)
+        ELSE MAX(bill_date) END)
+        as max_etd
         FROM
         los_sea_bills
         WHERE
         is_deleted = '0'
-        AND tenant_id = '128478'
+        AND tenant_id = #{data.tenantId}
+        <if test="data.businessType != null and data.businessType != ''">
+            and business_type = #{data.businessType}
+        </if>
         GROUP BY
         corp_id
         ) latest ON sb.corp_id = latest.corp_id AND sb.etd = latest.max_etd
         WHERE
         sb.is_deleted = '0'
-        AND sb.tenant_id = '128478'
+        AND sb.tenant_id = #{data.tenantId}
+        <if test="data.businessType != null and data.businessType != ''">
+            and sb.business_type = #{data.businessType}
+        </if>
         ) last_sea ON corp.id = last_sea.corp_id
         WHERE
         corp.is_deleted = '0'
-        AND corp.tenant_id = '128478'
-        AND (
-        last_sea.etd IS NULL
-        OR last_sea.etd < DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
-        );
-
+        AND corp.tenant_id = #{data.tenantId}
+        <if test="data.corpName != null and data.corpName != '' ">
+            AND corp.cn_name = #{data.corpName}
+        </if>
+        <if test="data.unshippedGoodsDays != null and data.unshippedGoodsDays != '' and data.unshippedGoodsDays == '1'">
+            AND last_sea.bill_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 2 MONTH) AND DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
+        </if>
+        <if test="data.unshippedGoodsDays != null and data.unshippedGoodsDays != '' and data.unshippedGoodsDays == '2'">
+            AND last_sea.bill_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 3 MONTH) AND DATE_SUB(CURDATE(), INTERVAL 2 MONTH)
+        </if>
+        <if test="data.unshippedGoodsDays != null and data.unshippedGoodsDays != '' and data.unshippedGoodsDays == '3'">
+            AND (
+            last_sea.bill_date IS NULL
+            OR last_sea.bill_date &lt;= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)
+            )
+        </if>
+        <if test="data.unshippedGoodsDays == null or data.unshippedGoodsDays == ''">
+            AND last_sea.bill_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 2 MONTH) AND DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
+        </if>
+        ORDER BY last_sea.bill_date
     </select>
 
 </mapper>

+ 2 - 0
blade-service/blade-los/src/main/java/org/springblade/los/box/controller/RouteCostController.java

@@ -94,6 +94,8 @@ public class RouteCostController extends BladeController {
 			.eq(RouteCost::getIsDeleted, 0)
 			.eq(RouteCost::getBusinessType, routeCost.getBusinessType())
 			.eq(ObjectUtils.isNotNull(routeCost.getStatus()), RouteCost::getStatus, routeCost.getStatus())
+			.eq(ObjectUtils.isNotNull(routeCost.getPodId()), RouteCost::getPodId, routeCost.getPodId())
+			.eq(ObjectUtils.isNotNull(routeCost.getDestinationId()), RouteCost::getDestinationId, routeCost.getDestinationId())
 			.like(ObjectUtils.isNotNull(routeCost.getBusinessNo()), RouteCost::getBusinessNo, routeCost.getBusinessNo())
 			.like(ObjectUtils.isNotNull(routeCost.getTransportationTerms()), RouteCost::getTransportationTerms, routeCost.getTransportationTerms())
 			.and(ObjectUtils.isNotNull(routeCost.getPodCname()), i -> i.like(RouteCost::getPodCname, routeCost.getPodCname()).or()

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

@@ -1146,5 +1146,13 @@ public class BillsController extends BladeController {
 		return R.data(billsList);
 	}
 
+	/**
+	 * 打印费用账单验证提示
+	 */
+	@GetMapping("/billVerificationPrompt")
+	public R billVerificationPrompt(@RequestParam("ids") String ids) {
+		return billUtils.billVerificationPrompt(ids);
+	}
+
 }
 

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

@@ -664,6 +664,11 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 					item.setPackingUnitId(bills.getPackingUnitId());
 				}
 				item.setMarks(bills.getMarks());
+				if (!"MM".equals(bills.getBillType()) && ObjectUtils.isNotNull(item.getContainerNumber())){
+					if( ObjectUtils.isNull(item.getCntrNo())){
+						throw new RuntimeException("放箱号已存在,箱号不能清空");
+					}
+				}
 				if (item.getId() == null) {
 					item.setCreateTime(new Date());
 					item.setCreateUser(AuthUtil.getUserId());

+ 5 - 8
blade-service/blade-los/src/main/java/org/springblade/los/business/sea/service/impl/ContainersServiceImpl.java

@@ -321,14 +321,6 @@ public class ContainersServiceImpl extends ServiceImpl<ContainersMapper, Contain
 			item.setUpdateUser(AuthUtil.getUserId());
 			item.setUpdateUserName(AuthUtil.getUserName());
 			item.setUpdateTime(new Date());
-			if (!billsList.isEmpty()) {
-				Bills bills = billsList.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(null);
-				if (bills != null && !"MM".equals(bills.getBillType())) {
-					if (ObjectUtils.isNotNull(item.getContainerNumber())) {
-						throw new RuntimeException("箱号:" + item.getCntrNo() + "存在放箱号,清除失败");
-					}
-				}
-			}
 		}
 		this.updateBatchById(containersList);
 		return R.data("操作成功");
@@ -583,6 +575,11 @@ public class ContainersServiceImpl extends ServiceImpl<ContainersMapper, Contain
 			if (ObjectUtils.isNull(containers.getHblno())) {
 				containers.setHblno(bills.getHblno());
 			}
+			if (!"MM".equals(bills.getBillType()) && ObjectUtils.isNotNull(containers.getContainerNumber())){
+				if( ObjectUtils.isNull(containers.getCntrNo())){
+					throw new RuntimeException("放箱号已存在,箱号不能清空");
+				}
+			}
 			if (containers.getId() == null) {
 				if (ObjectUtils.isNotNull(containers.getCntrNo()) && !cntrNoCount.isEmpty()) {
 					throw new RuntimeException("箱号不允许重复");

+ 12 - 26
blade-service/blade-los/src/main/java/org/springblade/los/excel/DeliveryPaperExcel.java

@@ -42,42 +42,28 @@ public class DeliveryPaperExcel implements Serializable {
 
 	private static final long serialVersionUID = 1L;
 
-	@ExcelProperty(value = "开船日期")
-	@DateTimeFormat(pattern = "yyyy-MM-dd")
-	@JsonFormat(pattern = "yyyy-MM-dd")
-	private Date etd;
-
-	@ExcelProperty(value = "目的港")
-	private String podEnName;
-
-	@ExcelProperty(value = "船名")
+	@ExcelProperty(value = "船名航次")
 	private String vesselCnName;
 
-	@ExcelProperty(value = "航次")
-	private String voyageNo;
-
-	@ExcelProperty(value = "船主")
-	private String boxOwner;
-
-	@ExcelProperty(value = "入港箱主")
-	private String inboundContainerOwner;
-
-	@ExcelProperty(value = "中转港")
-	private String potEnName;
-
-	@ExcelProperty(value = "主提单号")
-	private String mblno;
-
 	@ExcelProperty(value = "分单号")
 	private String hblno;
 
 	@ExcelProperty(value = "箱型箱量")
 	private String quantityCntrDescr;
 
-	@ExcelProperty(value = "货物毛重")
-	private BigDecimal grossWeight;
+	@ExcelProperty(value = "目的港")
+	private String podEnName;
 
 	@ExcelProperty(value = "放箱号")
 	private String containerNumber;
 
+	@ExcelProperty(value = "提箱地点")
+	private String stationCname;
+
+	@ExcelProperty(value = "备注")
+	private String remarks;
+
+	@ExcelProperty(value = "主提单号")
+	private String mblno;
+
 }

+ 14 - 5
blade-service/blade-los/src/main/java/org/springblade/los/statisticAnalysis/controller/StatisticAnalysisController.java

@@ -14,6 +14,7 @@ import org.springblade.los.excel.BoxNumberProfitExcel;
 import org.springblade.los.statisticAnalysis.BoxNumberProfitQ;
 import org.springblade.los.statisticAnalysis.DecisionAnalysis;
 import org.springblade.los.statisticAnalysis.UnshippedGoodsAnalysis;
+import org.springblade.los.statisticAnalysis.VoteAndLineCount;
 import org.springblade.los.statisticAnalysis.service.IStatisticAnalysisService;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -106,19 +107,27 @@ public class StatisticAnalysisController {
 	}
 
 	/**
-	 * app-票数统计
+	 * app-业务员箱量统计
+	 */
+	@GetMapping("/salesmanBoxCount")
+	public R salesmanBoxCount(VoteAndLineCount count) {
+		return statisticAnalysisService.salesmanBoxCount(count);
+	}
+
+	/**
+	 * app-操作票数统计
 	 */
 	@GetMapping("/voteCount")
-	public R voteCount(BoxNumberProfitQ boxNumberProfit) {
-		return statisticAnalysisService.voteCount(boxNumberProfit);
+	public R voteCount(VoteAndLineCount count) {
+		return statisticAnalysisService.voteCount(count);
 	}
 
 	/**
 	 * app-航线统计
 	 */
 	@GetMapping("/lineCount")
-	public R lineCount(BoxNumberProfitQ boxNumberProfit) {
-		return statisticAnalysisService.lineCount(boxNumberProfit);
+	public R lineCount(VoteAndLineCount count) {
+		return statisticAnalysisService.lineCount(count);
 	}
 
 	/**

+ 4 - 2
blade-service/blade-los/src/main/java/org/springblade/los/statisticAnalysis/service/IStatisticAnalysisService.java

@@ -97,9 +97,11 @@ public interface IStatisticAnalysisService {
 
 	List<AgingAnalysisRDItem> agingAnalysisExportItem(FeeSummaryQ feeSummaryQ);
 
-	R voteCount(BoxNumberProfitQ boxNumberProfit);
+	R voteCount(VoteAndLineCount count);
 
-	R lineCount(BoxNumberProfitQ boxNumberProfit);
+	R lineCount(VoteAndLineCount count);
 
 	R unshippedGoodsAnalysis(UnshippedGoodsAnalysis unshippedGoodsAnalysis, IPage<UnshippedGoodsAnalysis> page);
+
+	R salesmanBoxCount(VoteAndLineCount count);
 }

+ 72 - 31
blade-service/blade-los/src/main/java/org/springblade/los/statisticAnalysis/service/impl/StatisticAnalysisServiceImpl.java

@@ -11,7 +11,6 @@ import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.los.basic.corps.mapper.CorpsMapper;
-import org.springblade.los.basic.corps.vo.BCorpsVO;
 import org.springblade.los.basic.cur.entity.BCurrency;
 import org.springblade.los.basic.cur.service.IBCurrencyService;
 import org.springblade.los.basic.lines.entity.BLines;
@@ -1989,27 +1988,33 @@ public class StatisticAnalysisServiceImpl implements IStatisticAnalysisService {
 	}
 
 	@Override
-	public R voteCount(BoxNumberProfitQ boxNumberProfit) {
+	public R voteCount(VoteAndLineCount count) {
 		LambdaQueryWrapper<Bills> lambdaQueryWrapper = new LambdaQueryWrapper<>();
 		lambdaQueryWrapper.eq(Bills::getTenantId, AuthUtil.getTenantId())
 			.eq(Bills::getIsDeleted, 0)
-			.eq(ObjectUtils.isNotNull(boxNumberProfit.getBusinessType()), Bills::getBusinessType, boxNumberProfit.getBusinessType())
-			.eq(ObjectUtils.isNotNull(boxNumberProfit.getSrcCnName()), Bills::getSrcCnName, boxNumberProfit.getSrcCnName())
-			.eq(ObjectUtils.isNotNull(boxNumberProfit.getOperatorName()), Bills::getOperatorName, boxNumberProfit.getOperatorName());
+			.eq(ObjectUtils.isNotNull(count.getBusinessType()), Bills::getBusinessType, count.getBusinessType());
 		if (!AuthUtil.getUserRole().contains("总部") && !AuthUtil.getUserRole().contains("admin")) {
-			boxNumberProfit.setBranchId(AuthUtil.getDeptId());
+			count.setBranchId(AuthUtil.getDeptId());
 		} else {
-			lambdaQueryWrapper.eq(ObjectUtils.isNotNull(boxNumberProfit.getBranchId()), Bills::getBranchId, boxNumberProfit.getBranchId());
+			lambdaQueryWrapper.eq(ObjectUtils.isNotNull(count.getBranchId()), Bills::getBranchId, count.getBranchId());
 		}
-		if (ObjectUtils.isNotNull(boxNumberProfit.getBillDateList()) && !boxNumberProfit.getBillDateList().isEmpty()) {
-			lambdaQueryWrapper.ge(Bills::getBillDate, boxNumberProfit.getBillDateList().get(0));
-			lambdaQueryWrapper.le(Bills::getBillDate, boxNumberProfit.getBillDateList().get(1));
+		if ("SE".equals(count.getBusinessType())) {
+			lambdaQueryWrapper.ge(ObjectUtils.isNotNull(count.getStartDate()), Bills::getActualEtd, count.getStartDate());
+			lambdaQueryWrapper.le(ObjectUtils.isNotNull(count.getEndDate()), Bills::getActualEtd, count.getEndDate());
+		} else {
+			lambdaQueryWrapper.ge(ObjectUtils.isNotNull(count.getStartDate()), Bills::getActualEta, count.getStartDate());
+			lambdaQueryWrapper.le(ObjectUtils.isNotNull(count.getEndDate()), Bills::getActualEta, count.getEndDate());
 		}
 		List<Bills> billsList = billsMapper.selectList(lambdaQueryWrapper);
-		List<AppStatistics> appStatisticsList = new ArrayList<>();
+		List<VoteAndLineCount> appStatisticsList = new ArrayList<>();
 		if (!billsList.isEmpty()) {
-			for (Bills item : billsList) {
-				AppStatistics appStatistics = new AppStatistics();
+			List<String> operatorName = billsList.stream().map(Bills::getOperatorName).filter(Objects::nonNull)
+				.distinct().collect(Collectors.toList());
+			for (String item : operatorName) {
+				VoteAndLineCount appStatistics = new VoteAndLineCount();
+				appStatistics.setOperatorName(item);
+				appStatistics.setNumber(billsList.stream().filter(e -> ObjectUtils.isNotNull(e.getOperatorName()) &&
+					e.getOperatorName().equals(item)).count());
 				appStatisticsList.add(appStatistics);
 			}
 		}
@@ -2017,36 +2022,38 @@ public class StatisticAnalysisServiceImpl implements IStatisticAnalysisService {
 	}
 
 	@Override
-	public R lineCount(BoxNumberProfitQ boxNumberProfit) {
+	public R lineCount(VoteAndLineCount count) {
 		LambdaQueryWrapper<Bills> lambdaQueryWrapper = new LambdaQueryWrapper<>();
 		lambdaQueryWrapper.eq(Bills::getTenantId, AuthUtil.getTenantId())
 			.eq(Bills::getIsDeleted, 0)
-			.eq(ObjectUtils.isNotNull(boxNumberProfit.getBusinessType()), Bills::getBusinessType, boxNumberProfit.getBusinessType())
-			.eq(ObjectUtils.isNotNull(boxNumberProfit.getSrcCnName()), Bills::getSrcCnName, boxNumberProfit.getSrcCnName())
-			.eq(ObjectUtils.isNotNull(boxNumberProfit.getOperatorName()), Bills::getOperatorName, boxNumberProfit.getOperatorName());
+			.eq(ObjectUtils.isNotNull(count.getBusinessType()), Bills::getBusinessType, count.getBusinessType());
 		if (!AuthUtil.getUserRole().contains("总部") && !AuthUtil.getUserRole().contains("admin")) {
-			boxNumberProfit.setBranchId(AuthUtil.getDeptId());
+			count.setBranchId(AuthUtil.getDeptId());
 		} else {
-			lambdaQueryWrapper.eq(ObjectUtils.isNotNull(boxNumberProfit.getBranchId()), Bills::getBranchId, boxNumberProfit.getBranchId());
+			lambdaQueryWrapper.eq(ObjectUtils.isNotNull(count.getBranchId()), Bills::getBranchId, count.getBranchId());
 		}
-		if (ObjectUtils.isNotNull(boxNumberProfit.getBillDateList()) && !boxNumberProfit.getBillDateList().isEmpty()) {
-			lambdaQueryWrapper.ge(Bills::getBillDate, boxNumberProfit.getBillDateList().get(0));
-			lambdaQueryWrapper.le(Bills::getBillDate, boxNumberProfit.getBillDateList().get(1));
+		if ("SE".equals(count.getBusinessType())) {
+			lambdaQueryWrapper.ge(ObjectUtils.isNotNull(count.getStartDate()), Bills::getActualEtd, count.getStartDate());
+			lambdaQueryWrapper.le(ObjectUtils.isNotNull(count.getEndDate()), Bills::getActualEtd, count.getEndDate());
+		} else {
+			lambdaQueryWrapper.ge(ObjectUtils.isNotNull(count.getStartDate()), Bills::getActualEta, count.getStartDate());
+			lambdaQueryWrapper.le(ObjectUtils.isNotNull(count.getEndDate()), Bills::getActualEta, count.getEndDate());
 		}
 		List<Bills> billsList = billsMapper.selectList(lambdaQueryWrapper);
 		List<BLines> linesList = bLinesService.list(new LambdaQueryWrapper<BLines>()
 			.eq(BLines::getTenantId, AuthUtil.getTenantId())
 			.eq(BLines::getIsDeleted, 0)
 			.eq(BLines::getStatus, 0));
-		List<AppStatistics> appStatisticsList = new ArrayList<>();
+		List<VoteAndLineCount> appStatisticsList = new ArrayList<>();
 		if (!linesList.isEmpty()) {
 			for (BLines item : linesList) {
-				AppStatistics appStatistics = new AppStatistics();
-				appStatistics.setName(item.getCnName());
+				VoteAndLineCount appStatistics = new VoteAndLineCount();
+				appStatistics.setLineName(item.getCnName());
 				if (!billsList.isEmpty()) {
-					appStatistics.setNumber(billsList.stream().filter(e -> item.getId().equals(e.getLineId())).count());
+					appStatistics.setTeu(billsList.stream().filter(e -> item.getId().equals(e.getLineId()))
+						.map(Bills::getTeu).reduce(0, Integer::sum));
 				} else {
-					appStatistics.setNumber(0L);
+					appStatistics.setTeu(0);
 				}
 				appStatisticsList.add(appStatistics);
 			}
@@ -2055,9 +2062,43 @@ public class StatisticAnalysisServiceImpl implements IStatisticAnalysisService {
 	}
 
 	@Override
-	public R unshippedGoodsAnalysis(UnshippedGoodsAnalysis unshippedGoodsAnalysis,IPage<UnshippedGoodsAnalysis> page) {
-		List<UnshippedGoodsAnalysis> analysisList = corpsMapper.unshippedGoodsAnalysis(unshippedGoodsAnalysis,page);
-		page.setRecords(analysisList);
-		return null;
+	public R unshippedGoodsAnalysis(UnshippedGoodsAnalysis unshippedGoodsAnalysis, IPage<UnshippedGoodsAnalysis> page) {
+		unshippedGoodsAnalysis.setTenantId(AuthUtil.getTenantId());
+		List<UnshippedGoodsAnalysis> analysisList = corpsMapper.unshippedGoodsAnalysis(unshippedGoodsAnalysis, page);
+		return R.data(page.setRecords(analysisList));
+	}
+
+	@Override
+	public R salesmanBoxCount(VoteAndLineCount count) {
+		LambdaQueryWrapper<Bills> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+		lambdaQueryWrapper.eq(Bills::getTenantId, AuthUtil.getTenantId())
+			.eq(Bills::getIsDeleted, 0)
+			.eq(ObjectUtils.isNotNull(count.getBusinessType()), Bills::getBusinessType, count.getBusinessType());
+		if (!AuthUtil.getUserRole().contains("总部") && !AuthUtil.getUserRole().contains("admin")) {
+			count.setBranchId(AuthUtil.getDeptId());
+		} else {
+			lambdaQueryWrapper.eq(ObjectUtils.isNotNull(count.getBranchId()), Bills::getBranchId, count.getBranchId());
+		}
+		if ("SE".equals(count.getBusinessType())) {
+			lambdaQueryWrapper.ge(ObjectUtils.isNotNull(count.getStartDate()), Bills::getActualEtd, count.getStartDate());
+			lambdaQueryWrapper.le(ObjectUtils.isNotNull(count.getEndDate()), Bills::getActualEtd, count.getEndDate());
+		} else {
+			lambdaQueryWrapper.ge(ObjectUtils.isNotNull(count.getStartDate()), Bills::getActualEta, count.getStartDate());
+			lambdaQueryWrapper.le(ObjectUtils.isNotNull(count.getEndDate()), Bills::getActualEta, count.getEndDate());
+		}
+		List<Bills> billsList = billsMapper.selectList(lambdaQueryWrapper);
+		List<VoteAndLineCount> appStatisticsList = new ArrayList<>();
+		if (!billsList.isEmpty()) {
+			List<String> salesman = billsList.stream().filter(e -> "SALES".equals(e.getSrcType()))
+				.map(Bills::getSrcCnName).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+			for (String item : salesman) {
+				VoteAndLineCount appStatistics = new VoteAndLineCount();
+				appStatistics.setSalesman(item);
+				appStatistics.setTeu(billsList.stream().filter(e -> ObjectUtils.isNotNull(e.getOperatorName()) &&
+					e.getOperatorName().equals(item)).map(Bills::getTeu).reduce(0, Integer::sum));
+				appStatisticsList.add(appStatistics);
+			}
+		}
+		return R.data(appStatisticsList);
 	}
 }