Browse Source

1.客户基础资料增加视图判断是否使用
2.财务获取数据分组条件修改
3.所有费用明细提交相关接口增加判断提单号,分单号是否为空
4.业务利润海运费统计不转换人民币
5.成本中心按照当日汇率复制
6.营业费用模块-增加请核接口,撤销请核接口,确认付费接口,撤销付费接口
7.客户订舱增加驳回接口

纪新园 6 months ago
parent
commit
b104d8fa00
28 changed files with 1369 additions and 246 deletions
  1. 34 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/dto/CorpsSumDTO.java
  2. 6 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/entity/BCorps.java
  3. 43 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/entity/CorpsSum.java
  4. 36 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/vo/CorpsSumVO.java
  5. 5 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/business/sea/entity/Bills.java
  6. 167 129
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/finance/operatingExpenses/entity/OperatingExpenses.java
  7. 94 89
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/finance/operatingExpenses/entity/OperatingExpensesItem.java
  8. 6 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/FinanceProfitDtoList.java
  9. 126 0
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/controller/CorpsSumController.java
  10. 42 0
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsSumMapper.java
  11. 16 0
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsSumMapper.xml
  12. 41 0
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/service/ICorpsSumService.java
  13. 8 0
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/service/impl/BCorpsServiceImpl.java
  14. 41 0
      blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/service/impl/CorpsSumServiceImpl.java
  15. 23 3
      blade-service/blade-los/src/main/java/org/springblade/los/box/service/impl/ExpenseApplicationServiceImpl.java
  16. 74 3
      blade-service/blade-los/src/main/java/org/springblade/los/box/service/impl/RouteCostServiceImpl.java
  17. 12 0
      blade-service/blade-los/src/main/java/org/springblade/los/business/sea/controller/BookingCabinController.java
  18. 1 1
      blade-service/blade-los/src/main/java/org/springblade/los/business/sea/mapper/BillsMapper.xml
  19. 2 0
      blade-service/blade-los/src/main/java/org/springblade/los/business/sea/service/IBillsService.java
  20. 55 0
      blade-service/blade-los/src/main/java/org/springblade/los/business/sea/service/impl/BillsServiceImpl.java
  21. 2 0
      blade-service/blade-los/src/main/java/org/springblade/los/check/controller/AuditProecessController.java
  22. 2 0
      blade-service/blade-los/src/main/java/org/springblade/los/check/service/IAuditProecessService.java
  23. 175 0
      blade-service/blade-los/src/main/java/org/springblade/los/check/service/impl/AuditProecessServiceImpl.java
  24. 75 12
      blade-service/blade-los/src/main/java/org/springblade/los/finance/operatingExpenses/controller/OperatingExpensesController.java
  25. 12 0
      blade-service/blade-los/src/main/java/org/springblade/los/finance/operatingExpenses/service/IOperatingExpensesService.java
  26. 259 3
      blade-service/blade-los/src/main/java/org/springblade/los/finance/operatingExpenses/service/impl/OperatingExpensesServiceImpl.java
  27. 6 6
      blade-service/blade-los/src/main/java/org/springblade/los/statisticAnalysis/service/impl/StatisticAnalysisServiceImpl.java
  28. 6 0
      blade-service/blade-los/src/main/java/org/springblade/los/view/mapper/FinanceProfitMapper.xml

+ 34 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/dto/CorpsSumDTO.java

@@ -0,0 +1,34 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.los.basic.corps.dto;
+
+import org.springblade.los.basic.corps.entity.CorpsSum;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * VIEW数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2025-08-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class CorpsSumDTO extends CorpsSum {
+	private static final long serialVersionUID = 1L;
+
+}

+ 6 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/entity/BCorps.java

@@ -657,5 +657,11 @@ public class BCorps implements Serializable {
 	@TableField(exist = false)
 	private String ids;
 
+	/**
+	 * 客户是否使用过
+	 */
+	@TableField(exist = false)
+	private long count;
+
 
 }

+ 43 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/entity/CorpsSum.java

@@ -0,0 +1,43 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.los.basic.corps.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * VIEW实体类
+ *
+ * @author BladeX
+ * @since 2025-08-29
+ */
+@Data
+@TableName("los_corps_sum")
+@ApiModel(value = "CorpsSum对象", description = "VIEW")
+public class CorpsSum implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private Long corpId;
+	private Long sum;
+
+
+}

+ 36 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/basic/corps/vo/CorpsSumVO.java

@@ -0,0 +1,36 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.los.basic.corps.vo;
+
+import org.springblade.los.basic.corps.entity.CorpsSum;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import io.swagger.annotations.ApiModel;
+
+/**
+ * VIEW视图实体类
+ *
+ * @author BladeX
+ * @since 2025-08-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "CorpsSumVO对象", description = "VIEW")
+public class CorpsSumVO extends CorpsSum {
+	private static final long serialVersionUID = 1L;
+
+}

+ 5 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/business/sea/entity/Bills.java

@@ -1641,6 +1641,11 @@ public class Bills implements Serializable {
 	 */
 	@ApiModelProperty(value = "是否提取过成本")
 	private String whetherExtractCost;
+	/**
+	 * 订舱驳回原因
+	 */
+	@ApiModelProperty(value = "订舱驳回原因")
+	private String reason;
 
 	/**
 	 * 到港日期

+ 167 - 129
blade-service-api/blade-los-api/src/main/java/org/springblade/los/finance/operatingExpenses/entity/OperatingExpenses.java

@@ -16,14 +16,18 @@
  */
 package org.springblade.los.finance.operatingExpenses.entity;
 
-import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.los.business.files.entity.FilesCenter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
 
 /**
  * 营业费用实体类
@@ -40,130 +44,164 @@ public class OperatingExpenses implements Serializable {
 
 	private Long id;
 	/**
-	* 创建人 Id
-	*/
-		@ApiModelProperty(value = "创建人 Id")
-		private Long createUser;
-	/**
-	* 创建人
-	*/
-		@ApiModelProperty(value = "创建人")
-		private String createUserName;
-	/**
-	* 创建时间
-	*/
-		@ApiModelProperty(value = "创建时间")
-		private LocalDateTime createTime;
-	/**
-	* 修改人 Id
-	*/
-		@ApiModelProperty(value = "修改人 Id")
-		private Long updateUser;
-	/**
-	* 修改人
-	*/
-		@ApiModelProperty(value = "修改人")
-		private String updateUserName;
-	/**
-	* 修改时间
-	*/
-		@ApiModelProperty(value = "修改时间")
-		private LocalDateTime updateTime;
-	/**
-	* 版本
-	*/
-		@ApiModelProperty(value = "版本")
-		private String version;
-	/**
-	* 审核状态
-	*/
-		@ApiModelProperty(value = "审核状态")
-		private String status;
-	/**
-	* 是否已删除(0 否 1是)
-	*/
-		@ApiModelProperty(value = "是否已删除(0 否 1是)")
-		private Integer isDeleted;
-	/**
-	* 备注
-	*/
-		@ApiModelProperty(value = "备注")
-		private String remarks;
-	/**
-	* 分公司
-	*/
-		@ApiModelProperty(value = "分公司")
-		private String branchName;
-	/**
-	* 分公司 Id
-	*/
-		@ApiModelProperty(value = "分公司 Id")
-		private String branchId;
-	/**
-	* 申请人
-	*/
-		@ApiModelProperty(value = "申请人")
-		private Long applicantId;
-	/**
-	* 申请人
-	*/
-		@ApiModelProperty(value = "申请人")
-		private String applicantName;
-	/**
-	* 申请日期
-	*/
-		@ApiModelProperty(value = "申请日期")
-		private LocalDateTime applicantDate;
-	/**
-	* 金额
-	*/
-		@ApiModelProperty(value = "金额")
-		private BigDecimal amount;
-	/**
-	* 银行户头
-	*/
-		@ApiModelProperty(value = "银行户头")
-		private String bankAccount;
-	/**
-	* 账号
-	*/
-		@ApiModelProperty(value = "账号")
-		private String account;
-	/**
-	* 开户行
-	*/
-		@ApiModelProperty(value = "开户行")
-		private String bankOfDeposit;
-	/**
-	* 单据编号
-	*/
-		@ApiModelProperty(value = "单据编号")
-		private String billNo;
-	/**
-	* 支付方式
-	*/
-		@ApiModelProperty(value = "支付方式")
-		private String paymentMethod;
-	/**
-	* 结算状态
-	*/
-		@ApiModelProperty(value = "结算状态")
-		private String settlementStatus;
-	/**
-	* 结算日期
-	*/
-		@ApiModelProperty(value = "结算日期")
-		private LocalDateTime settlementDate;
-	/**
-	* 结算人
-	*/
-		@ApiModelProperty(value = "结算人")
-		private Long settlementPersonId;
-	/**
-	* 结算人
-	*/
-		@ApiModelProperty(value = "结算人")
-		private String settlementPersonName;
+	 * 创建人 Id
+	 */
+	@ApiModelProperty(value = "创建人 Id")
+	private Long createUser;
+	/**
+	 * 创建人
+	 */
+	@ApiModelProperty(value = "创建人")
+	private String createUserName;
+	/**
+	 * 创建时间
+	 */
+	@ApiModelProperty(value = "创建时间")
+	private Date createTime;
+	/**
+	 * 修改人 Id
+	 */
+	@ApiModelProperty(value = "修改人 Id")
+	private Long updateUser;
+	/**
+	 * 修改人
+	 */
+	@ApiModelProperty(value = "修改人")
+	private String updateUserName;
+	/**
+	 * 修改时间
+	 */
+	@ApiModelProperty(value = "修改时间")
+	private Date updateTime;
+	/**
+	 * 版本
+	 */
+	@ApiModelProperty(value = "版本")
+	private String version;
+	/**
+	 * 审核状态
+	 */
+	@ApiModelProperty(value = "审核状态")
+	private String status;
+	/**
+	 * 是否已删除(0 否 1是)
+	 */
+	@ApiModelProperty(value = "是否已删除(0 否 1是)")
+	private Integer isDeleted;
+	/**
+	 * 备注
+	 */
+	@ApiModelProperty(value = "备注")
+	private String remarks;
+	/**
+	 * 分公司
+	 */
+	@ApiModelProperty(value = "分公司")
+	private String branchName;
+	/**
+	 * 分公司 Id
+	 */
+	@ApiModelProperty(value = "分公司 Id")
+	private String branchId;
+	/**
+	 * 申请人
+	 */
+	@ApiModelProperty(value = "申请人")
+	private Long applicantId;
+	/**
+	 * 申请人
+	 */
+	@ApiModelProperty(value = "申请人")
+	private String applicantName;
+	/**
+	 * 申请日期
+	 */
+	@ApiModelProperty(value = "申请日期")
+	private Date applicantDate;
+	/**
+	 * 申请日期
+	 */
+	@TableField(exist = false)
+	private List<String> applicantDateList;
+	/**
+	 * 金额
+	 */
+	@ApiModelProperty(value = "金额")
+	private BigDecimal amount;
+	/**
+	 * 银行户头
+	 */
+	@ApiModelProperty(value = "银行户头")
+	private String bankAccount;
+	/**
+	 * 账号
+	 */
+	@ApiModelProperty(value = "账号")
+	private String account;
+	/**
+	 * 开户行
+	 */
+	@ApiModelProperty(value = "开户行")
+	private String bankOfDeposit;
+	/**
+	 * 单据编号
+	 */
+	@ApiModelProperty(value = "单据编号")
+	private String billNo;
+	/**
+	 * 支付方式
+	 */
+	@ApiModelProperty(value = "支付方式")
+	private String paymentMethod;
+	/**
+	 * 结算状态
+	 */
+	@ApiModelProperty(value = "结算状态")
+	private String settlementStatus;
+	/**
+	 * 结算日期
+	 */
+	@ApiModelProperty(value = "结算日期")
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private Date settlementDate;
+	/**
+	 * 结算日期
+	 */
+	@TableField(exist = false)
+	private List<String> settlementDateList;
+	/**
+	 * 结算人
+	 */
+	@ApiModelProperty(value = "结算人")
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private Long settlementPersonId;
+	/**
+	 * 结算人
+	 */
+	@ApiModelProperty(value = "结算人")
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String settlementPersonName;
+
+	/**
+	 * 租户
+	 */
+	@ApiModelProperty(value = "租户")
+	private String tenantId;
+
+	@TableField(exist = false)
+	private List<OperatingExpensesItem> operatingExpensesItemList;
+	@TableField(exist = false)
+	private List<FilesCenter> filesCenterList;
+
+	//跳转对应页面的路由
+	@TableField(exist = false)
+	private String url;
+	//页面枚举
+	@TableField(exist = false)
+	private String pageStatus;
+	//页面名字
+	@TableField(exist = false)
+	private String pageLabel;
 
 
 }

+ 94 - 89
blade-service-api/blade-los-api/src/main/java/org/springblade/los/finance/operatingExpenses/entity/OperatingExpensesItem.java

@@ -16,14 +16,14 @@
  */
 package org.springblade.los.finance.operatingExpenses.entity;
 
-import java.math.BigDecimal;
 import com.baomidou.mybatisplus.annotation.TableName;
-import java.time.LocalDateTime;
-import java.io.Serializable;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
 
 /**
  * 营业费用明细实体类
@@ -41,90 +41,95 @@ public class OperatingExpensesItem implements Serializable {
 	private Long id;
 	private Long pid;
 	/**
-	* 创建人 Id
-	*/
-		@ApiModelProperty(value = "创建人 Id")
-		private Long createUser;
-	/**
-	* 创建人
-	*/
-		@ApiModelProperty(value = "创建人")
-		private String createUserName;
-	/**
-	* 创建时间
-	*/
-		@ApiModelProperty(value = "创建时间")
-		private LocalDateTime createTime;
-	/**
-	* 修改人 Id
-	*/
-		@ApiModelProperty(value = "修改人 Id")
-		private Long updateUser;
-	/**
-	* 修改人
-	*/
-		@ApiModelProperty(value = "修改人")
-		private String updateUserName;
-	/**
-	* 修改时间
-	*/
-		@ApiModelProperty(value = "修改时间")
-		private LocalDateTime updateTime;
-	/**
-	* 版本
-	*/
-		@ApiModelProperty(value = "版本")
-		private String version;
-	/**
-	* 审核状态
-	*/
-		@ApiModelProperty(value = "审核状态")
-		private String status;
-	/**
-	* 是否已删除(0 否 1是)
-	*/
-		@ApiModelProperty(value = "是否已删除(0 否 1是)")
-		private Integer isDeleted;
-	/**
-	* 备注
-	*/
-		@ApiModelProperty(value = "备注")
-		private String remarks;
-	/**
-	* 分公司
-	*/
-		@ApiModelProperty(value = "分公司")
-		private String branchName;
-	/**
-	* 分公司 Id
-	*/
-		@ApiModelProperty(value = "分公司 Id")
-		private String branchId;
-	/**
-	* 摘要说明
-	*/
-		@ApiModelProperty(value = "摘要说明")
-		private String summaryDescription;
-	/**
-	* 费用归属人
-	*/
-		@ApiModelProperty(value = "费用归属人")
-		private String costOwner;
-	/**
-	* 数量
-	*/
-		@ApiModelProperty(value = "数量")
-		private BigDecimal quantity;
-	/**
-	* 单价
-	*/
-		@ApiModelProperty(value = "单价")
-		private BigDecimal price;
-	/**
-	* 金额
-	*/
-		@ApiModelProperty(value = "金额")
-		private BigDecimal amount;
+	 * 创建人 Id
+	 */
+	@ApiModelProperty(value = "创建人 Id")
+	private Long createUser;
+	/**
+	 * 创建人
+	 */
+	@ApiModelProperty(value = "创建人")
+	private String createUserName;
+	/**
+	 * 创建时间
+	 */
+	@ApiModelProperty(value = "创建时间")
+	private Date createTime;
+	/**
+	 * 修改人 Id
+	 */
+	@ApiModelProperty(value = "修改人 Id")
+	private Long updateUser;
+	/**
+	 * 修改人
+	 */
+	@ApiModelProperty(value = "修改人")
+	private String updateUserName;
+	/**
+	 * 修改时间
+	 */
+	@ApiModelProperty(value = "修改时间")
+	private Date updateTime;
+	/**
+	 * 版本
+	 */
+	@ApiModelProperty(value = "版本")
+	private String version;
+	/**
+	 * 审核状态
+	 */
+	@ApiModelProperty(value = "审核状态")
+	private String status;
+	/**
+	 * 是否已删除(0 否 1是)
+	 */
+	@ApiModelProperty(value = "是否已删除(0 否 1是)")
+	private Integer isDeleted;
+	/**
+	 * 备注
+	 */
+	@ApiModelProperty(value = "备注")
+	private String remarks;
+	/**
+	 * 分公司
+	 */
+	@ApiModelProperty(value = "分公司")
+	private String branchName;
+	/**
+	 * 分公司 Id
+	 */
+	@ApiModelProperty(value = "分公司 Id")
+	private String branchId;
+	/**
+	 * 摘要说明
+	 */
+	@ApiModelProperty(value = "摘要说明")
+	private String summaryDescription;
+	/**
+	 * 费用归属人
+	 */
+	@ApiModelProperty(value = "费用归属人")
+	private String costOwner;
+	/**
+	 * 数量
+	 */
+	@ApiModelProperty(value = "数量")
+	private BigDecimal quantity;
+	/**
+	 * 单价
+	 */
+	@ApiModelProperty(value = "单价")
+	private BigDecimal price;
+	/**
+	 * 金额
+	 */
+	@ApiModelProperty(value = "金额")
+	private BigDecimal amount;
 
+	/**
+	 * 租户
+	 */
+	@ApiModelProperty(value = "租户")
+	private String tenantId;
 
 }

+ 6 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/statisticAnalysis/FinanceProfitDtoList.java

@@ -111,6 +111,12 @@ public class FinanceProfitDtoList {
 	private String voyageNo;
 
 	/**
+	 * 箱属
+	 */
+	@ExcelProperty(value = "箱属")
+	private String boxBelongsTo;
+
+	/**
 	 * 航线 id
 	 */
 	@ExcelIgnore

+ 126 - 0
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/controller/CorpsSumController.java

@@ -0,0 +1,126 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.los.basic.corps.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+import javax.validation.Valid;
+
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.los.basic.corps.entity.CorpsSum;
+import org.springblade.los.basic.corps.vo.CorpsSumVO;
+import org.springblade.los.basic.corps.service.ICorpsSumService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ * VIEW 控制器
+ *
+ * @author BladeX
+ * @since 2025-08-29
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/corpssum")
+@Api(value = "VIEW", tags = "VIEW接口")
+public class CorpsSumController extends BladeController {
+
+	private final ICorpsSumService corpsSumService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入corpsSum")
+	public R<CorpsSum> detail(CorpsSum corpsSum) {
+		CorpsSum detail = corpsSumService.getOne(Condition.getQueryWrapper(corpsSum));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页 VIEW
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入corpsSum")
+	public R<IPage<CorpsSum>> list(CorpsSum corpsSum, Query query) {
+		IPage<CorpsSum> pages = corpsSumService.page(Condition.getPage(query), Condition.getQueryWrapper(corpsSum));
+		return R.data(pages);
+	}
+
+	/**
+	 * 自定义分页 VIEW
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "分页", notes = "传入corpsSum")
+	public R<IPage<CorpsSumVO>> page(CorpsSumVO corpsSum, Query query) {
+		IPage<CorpsSumVO> pages = corpsSumService.selectCorpsSumPage(Condition.getPage(query), corpsSum);
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 VIEW
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "新增", notes = "传入corpsSum")
+	public R save(@Valid @RequestBody CorpsSum corpsSum) {
+		return R.status(corpsSumService.save(corpsSum));
+	}
+
+	/**
+	 * 修改 VIEW
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "修改", notes = "传入corpsSum")
+	public R update(@Valid @RequestBody CorpsSum corpsSum) {
+		return R.status(corpsSumService.updateById(corpsSum));
+	}
+
+	/**
+	 * 新增或修改 VIEW
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入corpsSum")
+	public R submit(@Valid @RequestBody CorpsSum corpsSum) {
+		return R.status(corpsSumService.saveOrUpdate(corpsSum));
+	}
+
+	
+	/**
+	 * 删除 VIEW
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(corpsSumService.removeByIds(Func.toLongList(ids)));
+	}
+
+	
+}

+ 42 - 0
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsSumMapper.java

@@ -0,0 +1,42 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.los.basic.corps.mapper;
+
+import org.springblade.los.basic.corps.entity.CorpsSum;
+import org.springblade.los.basic.corps.vo.CorpsSumVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ * VIEW Mapper 接口
+ *
+ * @author BladeX
+ * @since 2025-08-29
+ */
+public interface CorpsSumMapper extends BaseMapper<CorpsSum> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param corpsSum
+	 * @return
+	 */
+	List<CorpsSumVO> selectCorpsSumPage(IPage page, CorpsSumVO corpsSum);
+
+}

+ 16 - 0
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/mapper/CorpsSumMapper.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.los.basic.corps.mapper.CorpsSumMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="corpsSumResultMap" type="org.springblade.los.basic.corps.entity.CorpsSum">
+        <result column="corp_id" property="corpId"/>
+        <result column="sum" property="sum"/>
+    </resultMap>
+
+
+    <select id="selectCorpsSumPage" resultMap="corpsSumResultMap">
+        select * from los_corps_sum where is_deleted = 0
+    </select>
+
+</mapper>

+ 41 - 0
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/service/ICorpsSumService.java

@@ -0,0 +1,41 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.los.basic.corps.service;
+
+import org.springblade.los.basic.corps.entity.CorpsSum;
+import org.springblade.los.basic.corps.vo.CorpsSumVO;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * VIEW 服务类
+ *
+ * @author BladeX
+ * @since 2025-08-29
+ */
+public interface ICorpsSumService extends IService<CorpsSum> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param corpsSum
+	 * @return
+	 */
+	IPage<CorpsSumVO> selectCorpsSumPage(IPage<CorpsSumVO> page, CorpsSumVO corpsSum);
+
+}

+ 8 - 0
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/service/impl/BCorpsServiceImpl.java

@@ -72,6 +72,8 @@ public class BCorpsServiceImpl extends ServiceImpl<CorpsMapper, BCorps> implemen
 
 	private final ICorpsInvoiceHeaderService corpsInvoiceHeaderService;
 
+	private final ICorpsSumService corpsSumService;
+
 	static final int GB_SP_DIFF = 160;
 	// 存放国标一级汉字不同读音的起始区位码
 	static final int[] secPosValueList = {1601, 1637, 1833, 2078, 2274, 2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635,
@@ -390,6 +392,12 @@ public class BCorpsServiceImpl extends ServiceImpl<CorpsMapper, BCorps> implemen
 			.eq(CorpsInvoiceHeader::getTenantId, AuthUtil.getTenantId())
 			.eq(CorpsInvoiceHeader::getPid, bCorps.getId())
 		));
+		List<CorpsSum> corpsSumList = corpsSumService.list(new LambdaQueryWrapper<CorpsSum>().eq(CorpsSum::getCorpId, detail.getId()));
+		if (!corpsSumList.isEmpty()) {
+			detail.setCount(corpsSumList.stream().map(CorpsSum::getSum).count());
+		}else{
+			detail.setCount(0);
+		}
 		return detail;
 	}
 

+ 41 - 0
blade-service/blade-los/src/main/java/org/springblade/los/basic/corps/service/impl/CorpsSumServiceImpl.java

@@ -0,0 +1,41 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.los.basic.corps.service.impl;
+
+import org.springblade.los.basic.corps.entity.CorpsSum;
+import org.springblade.los.basic.corps.vo.CorpsSumVO;
+import org.springblade.los.basic.corps.mapper.CorpsSumMapper;
+import org.springblade.los.basic.corps.service.ICorpsSumService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * VIEW 服务实现类
+ *
+ * @author BladeX
+ * @since 2025-08-29
+ */
+@Service
+public class CorpsSumServiceImpl extends ServiceImpl<CorpsSumMapper, CorpsSum> implements ICorpsSumService {
+
+	@Override
+	public IPage<CorpsSumVO> selectCorpsSumPage(IPage<CorpsSumVO> page, CorpsSumVO corpsSum) {
+		return page.setRecords(baseMapper.selectCorpsSumPage(page, corpsSum));
+	}
+
+}

+ 23 - 3
blade-service/blade-los/src/main/java/org/springblade/los/box/service/impl/ExpenseApplicationServiceImpl.java

@@ -224,6 +224,16 @@ public class ExpenseApplicationServiceImpl extends ServiceImpl<ExpenseApplicatio
 					throw new RuntimeException("请选择单一非本币币种");
 				}
 				for (FeeCenter item : expenseApplication.getFeeCenterList()) {
+					if ("MH".equals(item.getBillType())) {
+						if (ObjectUtils.isNull(item.getHblno())) {
+							throw new RuntimeException("费用" + item.getFeeCnName() + "分单号为空,请先保存");
+						}
+					}
+					if ("MM,DD".contains(item.getBillType())) {
+						if (ObjectUtils.isNull(item.getMblno())) {
+							throw new RuntimeException("费用" + item.getFeeCnName() + "提单号为空,请先保存");
+						}
+					}
 					item.setUpdateTime(new Date());
 					item.setUpdateUser(AuthUtil.getUserId());
 					item.setUpdateUserName(AuthUtil.getUserName());
@@ -577,6 +587,16 @@ public class ExpenseApplicationServiceImpl extends ServiceImpl<ExpenseApplicatio
 					if (!feeCenters.isEmpty()) {
 						List<FeeCenter> feeCentersNew = new ArrayList<>();
 						for (FeeCenter item : feeCenters) {
+							if ("MH".equals(item.getBillType())) {
+								if (ObjectUtils.isNull(item.getHblno())) {
+									throw new RuntimeException("费用" + item.getFeeCnName() + "分单号为空,请先保存");
+								}
+							}
+							if ("MM,DD".contains(item.getBillType())) {
+								if (ObjectUtils.isNull(item.getMblno())) {
+									throw new RuntimeException("费用" + item.getFeeCnName() + "提单号为空,请先保存");
+								}
+							}
 							item.setUpdateTime(new Date());
 							item.setUpdateUser(AuthUtil.getUserId());
 							item.setUpdateUserName(AuthUtil.getUserName());
@@ -771,9 +791,9 @@ public class ExpenseApplicationServiceImpl extends ServiceImpl<ExpenseApplicatio
 				data.setSrcCnName(item.getSrcCnName());
 				data.setSrcEnName(item.getSrcEnName());
 				data.setSrcType(item.getSrcType());
-				if (!bills.isEmpty()){
-					Bills bills1 = bills.stream().filter(e-> e.getId().equals(item.getPid())).findFirst().orElse(null);
-					if (bills1 != null){
+				if (!bills.isEmpty()) {
+					Bills bills1 = bills.stream().filter(e -> e.getId().equals(item.getPid())).findFirst().orElse(null);
+					if (bills1 != null) {
 						data.setOperatorId(bills1.getOperatorId());
 						data.setOperatorName(bills1.getOperatorName());
 					}

+ 74 - 3
blade-service/blade-los/src/main/java/org/springblade/los/box/service/impl/RouteCostServiceImpl.java

@@ -26,8 +26,10 @@ 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.Util.CurrencyUtils;
 import org.springblade.los.basic.business.entity.BusinessType;
 import org.springblade.los.basic.business.service.IBusinessTypeService;
+import org.springblade.los.basic.cur.entity.BCurExrate;
 import org.springblade.los.billno.entity.BusinessBillNo;
 import org.springblade.los.billno.service.IBusinessBillNoService;
 import org.springblade.los.box.entity.QuotationItem;
@@ -88,6 +90,8 @@ public class RouteCostServiceImpl extends ServiceImpl<RouteCostMapper, RouteCost
 
 	private final ISysClient sysClient;
 
+	private final CurrencyUtils currencyUtils;
+
 	@Override
 	public IPage<RouteCostVO> selectRouteCostPage(IPage<RouteCostVO> page, RouteCostVO routeCost) {
 		return page.setRecords(baseMapper.selectRouteCostPage(page, routeCost));
@@ -278,11 +282,14 @@ public class RouteCostServiceImpl extends ServiceImpl<RouteCostMapper, RouteCost
 		detail.setUpdateUserName(null);
 		detail.setStatus("录入");
 		detail.setBusinessNo(null);
-		List<RouteCostFee> costFeeList = routeCostFeeService.list(new LambdaQueryWrapper<RouteCostFee>()
+		detail.setExrateDate(new Date());
+		String exrateType = currencyUtils.standardCurrency(detail.getBelongingCompanyId() + "");
+		List<BCurExrate> curExrateList = currencyUtils.obtainRate(detail.getExrateDate(), "1", detail.getBelongingCompanyId() + "");
+		List<RouteCostFee> costFeesList = routeCostFeeService.list(new LambdaQueryWrapper<RouteCostFee>()
 			.eq(RouteCostFee::getTenantId, AuthUtil.getTenantId())
 			.eq(RouteCostFee::getIsDeleted, 0)
 			.eq(RouteCostFee::getPid, routeCost.getId()));
-		for (RouteCostFee item : costFeeList) {
+		for (RouteCostFee item : costFeesList) {
 			item.setId(null);
 			item.setPid(null);
 			item.setCreateTime(null);
@@ -291,8 +298,9 @@ public class RouteCostServiceImpl extends ServiceImpl<RouteCostMapper, RouteCost
 			item.setUpdateUser(null);
 			item.setUpdateTime(null);
 			item.setUpdateUserName(null);
+			item.setExrate(currencyUtils.obtainExrate("D", curExrateList, item.getCurCode(), "1"));
 		}
-		detail.setCostFeeList(costFeeList.isEmpty() ? new ArrayList<>() : costFeeList);
+		detail.setCostFeeList(costFeesList.isEmpty() ? new ArrayList<>() : costFeesList);
 		List<RouteCostItem> costItemList = routeCostItemService.list(new LambdaQueryWrapper<RouteCostItem>()
 			.eq(RouteCostItem::getTenantId, AuthUtil.getTenantId())
 			.eq(RouteCostItem::getIsDeleted, 0)
@@ -308,6 +316,69 @@ public class RouteCostServiceImpl extends ServiceImpl<RouteCostMapper, RouteCost
 			item.setUpdateUserName(null);
 		}
 		detail.setCostItemList(costItemList.isEmpty() ? new ArrayList<>() : costItemList);
+		if (ObjectUtils.isNotNull(detail.getCostItemList())) {
+			int days = detail.getNavigateDay() + detail.getExistStationDay();
+			List<RouteCostFee> costFeeList = detail.getCostFeeList();
+			for (RouteCostItem routeCostItem : detail.getCostItemList()) {
+				routeCostItem.setExrate(currencyUtils.obtainExrate("D", curExrateList, routeCostItem.getCurCode(), "1"));
+				//一程POL杂费成本
+				routeCostItem.setPolCost(computationalCost(costFeeList, "POL", routeCostItem.getBoxType(), routeCostItem.getExrate(), "0"));
+				//一程POL杂费收入
+				routeCostItem.setPolIncome(computationalIncome(costFeeList, "POL", routeCostItem.getBoxType(), routeCostItem.getExrate(), "0"));
+				//一程POD杂费成本
+				routeCostItem.setPodCost(computationalCost(costFeeList, "POD", routeCostItem.getBoxType(), routeCostItem.getExrate(), "0"));
+				//一程POD杂费收入
+				routeCostItem.setPodIncome(computationalIncome(costFeeList, "POD", routeCostItem.getBoxType(), routeCostItem.getExrate(), "0"));
+				//一程用箱成本
+				if (0 != days && ObjectUtils.isNotNull(routeCostItem.getBoxCost()) &&
+					routeCostItem.getBoxCost().compareTo(new BigDecimal("0.00")) != 0) {
+					BigDecimal boxCost = new BigDecimal(days).multiply(routeCostItem.getBoxCost());
+					routeCostItem.setUseBoxCost(boxCost);
+				} else {
+					routeCostItem.setUseBoxCost(new BigDecimal("0.00"));
+				}
+				// 一程成本价 = 一程海运费+一程用箱成本+一程pol杂费+一程pod成本+附加费
+				routeCostItem.setCostPrice(routeCostItem.getOceanFreight().add(routeCostItem.getPodCost()).add(routeCostItem.getPolCost())
+					.add(routeCostItem.getUseBoxCost()).add(routeCostItem.getAdditionalFee()));
+				//一程合计利润
+				routeCostItem.setTotalProfit(routeCostItem.getSalesPrice().add(routeCostItem.getPolIncome())
+					.add(routeCostItem.getPodIncome()).subtract(routeCostItem.getCostPrice()));
+				if ("转船".equals(detail.getFlightType()) && "自转".equals(detail.getChangeShipType())) {
+					//二程POL杂费成本
+					routeCostItem.setPolCostTwo(computationalCost(costFeeList, "POL", routeCostItem.getBoxType(), routeCostItem.getExrate(), "1"));
+					//二程POL杂费收入
+					routeCostItem.setPolIncomeTwo(computationalIncome(costFeeList, "POL", routeCostItem.getBoxType(), routeCostItem.getExrate(), "1"));
+					//二程POD杂费成本
+					routeCostItem.setPodCostTwo(computationalCost(costFeeList, "POD", routeCostItem.getBoxType(), routeCostItem.getExrate(), "1"));
+					//二程POD杂费收入
+					routeCostItem.setPodIncomeTwo(computationalIncome(costFeeList, "POD", routeCostItem.getBoxType(), routeCostItem.getExrate(), "1"));
+					// 二程成本价 = 二程海运费+二程pol杂费+二程pod成本
+					routeCostItem.setCostPriceTwo(routeCostItem.getOceanFreightTwo().add(routeCostItem.getPodCostTwo()).add(routeCostItem.getPolCostTwo()));
+					//二程合计利润
+					routeCostItem.setTotalProfitTwo(routeCostItem.getSalesPriceTwo().add(routeCostItem.getPolIncomeTwo())
+						.add(routeCostItem.getPodIncomeTwo()).subtract(routeCostItem.getCostPriceTwo()));
+				}
+				routeCostItem.setTotalProfitTwo(routeCostItem.getTotalProfitTwo() != null ? routeCostItem.getTotalProfitTwo() : new BigDecimal("0.00"));
+				//合计利润
+				routeCostItem.setProfit(routeCostItem.getTotalProfit().add(routeCostItem.getTotalProfitTwo()));
+
+				if (routeCostItem.getId() == null) {
+					routeCostItem.setPid(routeCost.getId());
+					routeCostItem.setCreateTime(new Date());
+					routeCostItem.setCreateUser(AuthUtil.getUserId());
+					routeCostItem.setCreateUserName(AuthUtil.getUserName());
+				} else {
+					routeCostItem.setUpdateUser(AuthUtil.getUserId());
+					routeCostItem.setUpdateTime(new Date());
+					routeCostItem.setUpdateUserName(AuthUtil.getUserName());
+				}
+			}
+			detail.setProfit20(totalProfit(detail.getCostItemList(), "20"));
+			detail.setProfit40(totalProfit(detail.getCostItemList(), "40"));
+			detail.setProfitHc(totalProfit(detail.getCostItemList(), "40HC"));
+			detail.setOtherProfit(totalProfit(detail.getCostItemList(), "other"));
+			detail.setTotalProfit(detail.getProfit20().add(detail.getProfit40()).add(detail.getProfitHc()).add(detail.getOtherProfit()));
+		}
 		return detail;
 	}
 

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

@@ -150,6 +150,9 @@ public class BookingCabinController extends BladeController {
 			} else if (6 == bills.getBillStatus()) {
 				//待审核
 				lambdaQueryWrapper.eq(Bills::getStatus, 0);
+			}else if (7 == bills.getBillStatus()) {
+				//订舱驳回
+				lambdaQueryWrapper.eq(Bills::getIssueStatus, "6");
 			}
 		}
 		IPage<Bills> pages = billsService.page(Condition.getPage(query), lambdaQueryWrapper);
@@ -325,5 +328,14 @@ public class BookingCabinController extends BladeController {
 		return R.data(pages);
 	}
 
+
+	/**
+	 * 客户订舱驳回
+	 */
+	@PostMapping("/rejectBooking")
+	public R rejectBooking(@Valid @RequestBody Bills bills) {
+		return billsService.rejectBooking(bills);
+	}
+
 }
 

+ 1 - 1
blade-service/blade-los/src/main/java/org/springblade/los/business/sea/mapper/BillsMapper.xml

@@ -474,7 +474,7 @@
         <if test="acc.bookingNo != null and acc.bookingNo != ''">
             and acc.booking_no like concat('%', #{acc.bookingNo}, '%')
         </if>
-        GROUP BY acc.bill_no
+        GROUP BY acc.business_bill_id,acc.bill_no
         ORDER BY acc.business_date
     </select>
     <!-- <if test='acc.type != null and acc.type != "" and acc.type == "2"'>

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

@@ -213,4 +213,6 @@ public interface IBillsService extends IService<Bills> {
 	R submitCommonTemplates(Bills bills);
 
 	R refundCabin(Bills bills);
+
+	R rejectBooking(Bills bills);
 }

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

@@ -2061,6 +2061,16 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 				.ne(FeeCenter::getAuditStatus, "4"));
 			if (!feeCenterList.isEmpty()) {
 				for (FeeCenter item : feeCenterList) {
+					if ("MH".equals(item.getBillType())) {
+						if (ObjectUtils.isNull(item.getHblno())) {
+							throw new RuntimeException("费用" + item.getFeeCnName() + "分单号为空,请先保存");
+						}
+					}
+					if ("MM,DD".contains(item.getBillType())) {
+						if (ObjectUtils.isNull(item.getMblno())) {
+							throw new RuntimeException("费用" + item.getFeeCnName() + "提单号为空,请先保存");
+						}
+					}
 					int version = StringUtil.isBlank(item.getVersion()) ? 1 : Integer.parseInt(item.getVersion());
 					item.setVersion(String.valueOf(version + 1));
 					if (!"0".equals(item.getAuditStatus())) {
@@ -4105,6 +4115,16 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 			.in(FeeCenter::getPid, idMList));
 		if (!feeCenterList.isEmpty()) {
 			for (FeeCenter item : feeCenterList) {
+				if ("MH".equals(item.getBillType())) {
+					if (ObjectUtils.isNull(item.getHblno())) {
+						throw new RuntimeException("费用" + item.getFeeCnName() + "分单号为空,请先保存");
+					}
+				}
+				if ("MM,DD".contains(item.getBillType())) {
+					if (ObjectUtils.isNull(item.getMblno())) {
+						throw new RuntimeException("费用" + item.getFeeCnName() + "提单号为空,请先保存");
+					}
+				}
 				int version = StringUtil.isBlank(item.getVersion()) ? 1 : Integer.parseInt(item.getVersion());
 				item.setVersion(String.valueOf(version + 1));
 				if (!"0".equals(item.getAuditStatus())) {
@@ -6042,6 +6062,41 @@ public class BillsServiceImpl extends ServiceImpl<BillsMapper, Bills> implements
 		return R.data(bills);
 	}
 
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R rejectBooking(Bills bills) {
+		bills.setUpdateUserName(AuthUtil.getUserName());
+		bills.setUpdateUser(AuthUtil.getUserId());
+		bills.setUpdateTime(new Date());
+		bills.setIssueStatus("6");
+		baseMapper.updateById(bills);
+		R<User> res = userClient.userInfoById(bills.getCreateUser());
+		if (res.isSuccess() && ObjectUtils.isNotNull(res.getData())) {
+			LocalDateTime now = LocalDateTime.now();
+			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+			String formatted = now.format(formatter);
+			Message sendMessage = new Message();
+			sendMessage.setParameter(bills.getId() + "");
+			sendMessage.setUserName(AuthUtil.getUserName());
+			sendMessage.setUserId(AuthUtil.getUserId());
+			sendMessage.setToUserId(res.getData().getId());
+			sendMessage.setToUserName(res.getData().getName());
+			sendMessage.setMessageType(1);
+			sendMessage.setTenantId(AuthUtil.getTenantId());
+			sendMessage.setCreateUser(AuthUtil.getUserId());
+			sendMessage.setCreateTime(new Date());
+			sendMessage.setUrl("/iosBasicData/businessCenter/customerBooking/index");
+			sendMessage.setPageLabel("客户订舱");
+			sendMessage.setPageStatus("this.$store.getters.domSaleStatus");
+			sendMessage.setMessageBody("订舱单号:" + bills.getBillNo() + " 已驳回,驳回原因:"+bills.getReason()+",驳回时间:" + formatted);
+			R save = messageClient.save(sendMessage);
+			if (!save.isSuccess()) {
+				throw new SecurityException("发送消息失败");
+			}
+		}
+		return R.data(bills);
+	}
+
 	/**
 	 * 删除海运进出口明细表
 	 *

+ 2 - 0
blade-service/blade-los/src/main/java/org/springblade/los/check/controller/AuditProecessController.java

@@ -250,6 +250,8 @@ public class AuditProecessController extends BladeController {
 			auditProecessService.applyUpdateFee(auditProecess);
 		}else if ("BJZX".equals(proecess.getCheckType())) {
 			auditProecessService.checkMktSlot(auditProecess);
+		}else if ("YYFY".equals(proecess.getCheckType())) {
+			auditProecessService.checkOperatingExpenses(auditProecess);
 		}
 		return R.data(auditProecess);
 	}

+ 2 - 0
blade-service/blade-los/src/main/java/org/springblade/los/check/service/IAuditProecessService.java

@@ -72,4 +72,6 @@ public interface IAuditProecessService extends IService<LosAuditProecess> {
 	void applyUpdateFee(LosAuditProecess auditProecess);
 
 	void checkMktSlot(LosAuditProecess auditProecess);
+
+	void checkOperatingExpenses(LosAuditProecess auditProecess);
 }

+ 175 - 0
blade-service/blade-los/src/main/java/org/springblade/los/check/service/impl/AuditProecessServiceImpl.java

@@ -61,6 +61,8 @@ import org.springblade.los.finance.fee.service.IFeeCenterService;
 import org.springblade.los.finance.fee.service.IFinAccBillsService;
 import org.springblade.los.finance.invoices.entity.FinInvoices;
 import org.springblade.los.finance.invoices.mapper.FinInvoicesMapper;
+import org.springblade.los.finance.operatingExpenses.entity.OperatingExpenses;
+import org.springblade.los.finance.operatingExpenses.mapper.OperatingExpensesMapper;
 import org.springblade.los.finance.stl.entity.FinStlBills;
 import org.springblade.los.finance.stl.mapper.FinStlBillsMapper;
 import org.springblade.system.feign.ISysClient;
@@ -115,6 +117,8 @@ public class AuditProecessServiceImpl extends ServiceImpl<AuditProecessMapper, L
 
 	private final MktSlotMapper mktSlotMapper;
 
+	private final OperatingExpensesMapper operatingExpensesMapper;
+
 	private final ISysClient sysClient;
 
 
@@ -271,6 +275,10 @@ public class AuditProecessServiceImpl extends ServiceImpl<AuditProecessMapper, L
 					message.setMessageBody("您有新的客户托书审核待确认,业务单号:" + auditProecessDTO.getBillNo() + ",请审核。"
 						+ "提交人:" + auditProecessDTO.getSendName() + "  " + "提交时间" + simpleDateFormat.format(auditProecessDTO.getSendTime())
 					);
+				}else if ("营业费用请核".equals(auditProecess.getProcessType())) {
+					message.setMessageBody("您有新的营业费用审核待确认,业务单号:" + auditProecessDTO.getBillNo() + ",请审核。"
+						+ "提交人:" + auditProecessDTO.getSendName() + "  " + "提交时间" + simpleDateFormat.format(auditProecessDTO.getSendTime())
+					);
 				}
 
 
@@ -1950,6 +1958,173 @@ public class AuditProecessServiceImpl extends ServiceImpl<AuditProecessMapper, L
 		baseMapper.updateById(auditProecess);
 	}
 
+	@Override
+	public void checkOperatingExpenses(LosAuditProecess auditProecess) {
+		//查看最新操作记录,防止重复提交
+		LosAuditProecess proecessTemp = baseMapper.selectById(auditProecess.getId());
+		if (proecessTemp == null) {
+			throw new SecurityException("未查到此审批记录,禁止操作");
+		}
+		if ("A".equals(proecessTemp.getAuditStatus()) || "B".equals(proecessTemp.getAuditStatus())) {
+			throw new SecurityException("当前记录已经完成审批,禁止重复操作");
+		}
+
+		if (auditProecess.getAuditStatus() == null || !"S".equals(auditProecess.getAuditStatus())) {
+			throw new SecurityException("审批状态非待审,禁止操作");
+		}
+		//信息
+		Message sendMessage = new Message();
+		sendMessage.setParameter(String.valueOf(auditProecess.getBillId()));
+		sendMessage.setUserName(AuthUtil.getUserName());
+		sendMessage.setUserId(AuthUtil.getUserId());
+		sendMessage.setToUserId(auditProecess.getSendUserId());
+		sendMessage.setToUserName(auditProecess.getSendName());
+		sendMessage.setMessageType(1);
+		sendMessage.setTenantId(AuthUtil.getTenantId());
+		sendMessage.setCreateUser(AuthUtil.getUserId());
+		sendMessage.setCreateTime(new Date());
+		sendMessage.setUrl(auditProecess.getUrl());
+		sendMessage.setPageLabel(auditProecess.getPageLabel());
+		sendMessage.setPageStatus(auditProecess.getPageStatus());
+
+		//用户操作 1.通过  2.驳回
+		Integer operate = auditProecess.getOperate();
+		//查看当前审批是否为最后一级
+		String iffinalItem = auditProecess.getIffinalItem();
+		//审批人
+		auditProecess.setAuditUserId(String.valueOf(AuthUtil.getUserId()));
+		//审批时间
+		auditProecess.setAuditOpTime(new Date());
+
+		OperatingExpenses operatingExpenses = operatingExpensesMapper.selectById(proecessTemp.getBillId());
+
+		//不是最后一级
+		if ("F".equals(iffinalItem)) {
+
+			//通过
+			if (operate == 1) {
+				//如果是第一级, 则修改状态为审批中
+				if (auditProecess.getLevelId() == 1) {
+					operatingExpenses.setStatus("2");
+					int count = operatingExpensesMapper.updateById(operatingExpenses);
+					if (count == 0) {
+						throw new SecurityException("审批开始修改审核状态失败");
+					}
+				}
+
+				auditProecess.setAuditStatus("A");
+				//查询下一级,开启待审
+				LambdaQueryWrapper<LosAuditProecess> auditProecessLambdaQueryWrapper = new LambdaQueryWrapper<>();
+				auditProecessLambdaQueryWrapper
+					.eq(LosAuditProecess::getBatchNo, auditProecess.getBatchNo())
+					.eq(LosAuditProecess::getSrcBillId, auditProecess.getSrcBillId())
+					.eq(LosAuditProecess::getIsDelete, 0)
+					.eq(LosAuditProecess::getActId, auditProecess.getActId())
+					.eq(LosAuditProecess::getBillId, auditProecess.getBillId())
+					.eq(LosAuditProecess::getBillNo, auditProecess.getBillNo())
+					.eq(LosAuditProecess::getTenantId, AuthUtil.getTenantId())
+					.eq(LosAuditProecess::getLevelId, auditProecess.getLevelId() + 1);
+				Integer count = baseMapper.selectCount(auditProecessLambdaQueryWrapper);
+				if (count != null && count > 1) {
+					throw new SecurityException("审核失败,获取下一级信息失败");
+				}
+				LosAuditProecess proecess = baseMapper.selectOne(auditProecessLambdaQueryWrapper);
+				if (proecess == null) {
+					throw new SecurityException("审批通过=>获取下一级信息失败");
+				}
+				proecess.setAuditStatus("S");
+				baseMapper.updateById(proecess);
+
+				SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
+
+				//获得订单创建日期
+				String billsDate = null;
+				if (proecessTemp.getBillId() != null) {
+					if (operatingExpenses != null) {
+						billsDate = simpleDateFormat.format(operatingExpenses.getCreateTime());
+					}
+				}
+
+				Message message = new Message();
+				message.setUserName(AuthUtil.getUserName());
+				message.setUserId(AuthUtil.getUserId());
+				message.setParameter(String.valueOf(auditProecess.getBillId()));
+				message.setMessageType(1);
+				message.setTenantId(AuthUtil.getTenantId());
+				message.setMessageBody("您有新的营业费用审核,申请单号:" + proecessTemp.getBillNo() + ","
+					+ "单据日期:" + billsDate + ",请审核。"
+					+ "提交人:" + proecessTemp.getSendName() + "  " + "提交时间" + simpleDateFormat.format(proecessTemp.getSendTime())
+				);
+				message.setUrl(auditProecess.getUrl());
+				message.setPageLabel(auditProecess.getPageLabel());
+				message.setPageStatus(auditProecess.getPageStatus());
+				message.setCreateUser(AuthUtil.getUserId());
+
+				message.setCreateTime(new Date());
+
+				// 消息批量通知下一级
+				sendMsgToGroup(message, proecess.getAuditUserId());
+			}
+			//不通过
+			else if (operate == 2) {
+				auditProecess.setAuditStatus("B");
+				operatingExpenses.setStatus("0");
+				int count = operatingExpensesMapper.updateById(operatingExpenses);
+				if (count == 0) {
+					throw new SecurityException("修改订单数据失败");
+				}
+
+				sendMessage.setMessageBody("您的营业费用审核未通过" + ",业务单号:" + proecessTemp.getBillNo() + ",驳回原因:" + auditProecess.getAuditMsg());
+				R save = messageClient.save(sendMessage);
+				if (!save.isSuccess()) {
+					throw new SecurityException("发送消息失败");
+				}
+			}
+
+		}
+		//是最后一级
+		else if ("T".equals(iffinalItem)) {
+			//通过
+			if (operate == 1) {
+				auditProecess.setAuditStatus("A");
+				operatingExpenses.setStatus("3");
+				int count = operatingExpensesMapper.updateById(operatingExpenses);
+				if (count == 0) {
+					throw new SecurityException("修改订单数据失败");
+				}
+
+				sendMessage.setMessageBody("您的营业费用审核已通过" + ",业务单号:" + proecessTemp.getBillNo() + ",请继续操作");
+				R save = messageClient.save(sendMessage);
+				if (!save.isSuccess()) {
+					throw new SecurityException("发送消息失败");
+				}
+			}
+			//不通过
+			else if (operate == 2) {
+				auditProecess.setAuditStatus("B");
+				operatingExpenses.setStatus("4");
+				int count = operatingExpensesMapper.updateById(operatingExpenses);
+				if (count == 0) {
+					throw new SecurityException("修改订单数据失败");
+				}
+				sendMessage.setMessageBody("您的营业费用审核未通过" + ",业务单号:" + proecessTemp.getBillNo() + ",驳回原因:" + auditProecess.getAuditMsg());
+				R save = messageClient.save(sendMessage);
+				if (!save.isSuccess()) {
+					throw new SecurityException("发送消息失败");
+				}
+			}
+		} else {
+			throw new SecurityException("审批异常,请联系管理员");
+		}
+
+		cleanMsg(proecessTemp.getAuditUserId(), AuthUtil.getUserId(), proecessTemp.getSrcBillId());
+
+		//保存操作记录
+		auditProecess.setAuditMsg(auditProecess.getAuditMsg());
+		auditProecess.setAuditItem(new Date());
+		baseMapper.updateById(auditProecess);
+	}
+
 	private void updateFeeCenter(FeeCenterUpdateRecord feeCenterUpdateRecord, FeeCenter feeCenter) {
 		feeCenterUpdateRecord.setStatus("3");
 		feeCenterUpdateRecord.setUpdateUser(AuthUtil.getUserId());

+ 75 - 12
blade-service/blade-los/src/main/java/org/springblade/los/finance/operatingExpenses/controller/OperatingExpensesController.java

@@ -16,23 +16,28 @@
  */
 package org.springblade.los.finance.operatingExpenses.controller;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
-import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
-import javax.validation.Valid;
-
+import org.springblade.common.annotation.RepeatSubmit;
+import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
-import org.springframework.web.bind.annotation.*;
-import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.los.business.sea.entity.Bills;
 import org.springblade.los.finance.operatingExpenses.entity.OperatingExpenses;
-import org.springblade.los.finance.operatingExpenses.vo.OperatingExpensesVO;
 import org.springblade.los.finance.operatingExpenses.service.IOperatingExpensesService;
-import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.los.finance.operatingExpenses.vo.OperatingExpensesVO;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
 
 /**
  * 营业费用 控制器
@@ -55,7 +60,7 @@ public class OperatingExpensesController extends BladeController {
 	@ApiOperationSupport(order = 1)
 	@ApiOperation(value = "详情", notes = "传入operatingExpenses")
 	public R<OperatingExpenses> detail(OperatingExpenses operatingExpenses) {
-		OperatingExpenses detail = operatingExpensesService.getOne(Condition.getQueryWrapper(operatingExpenses));
+		OperatingExpenses detail = operatingExpensesService.detail(operatingExpenses);
 		return R.data(detail);
 	}
 
@@ -66,7 +71,29 @@ public class OperatingExpensesController extends BladeController {
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "分页", notes = "传入operatingExpenses")
 	public R<IPage<OperatingExpenses>> list(OperatingExpenses operatingExpenses, Query query) {
-		IPage<OperatingExpenses> pages = operatingExpensesService.page(Condition.getPage(query), Condition.getQueryWrapper(operatingExpenses));
+		LambdaQueryWrapper<OperatingExpenses> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+		lambdaQueryWrapper.eq(OperatingExpenses::getTenantId, AuthUtil.getTenantId())
+			.eq(OperatingExpenses::getIsDeleted, 0)
+			.eq(ObjectUtils.isNotNull(operatingExpenses.getApplicantId()), OperatingExpenses::getApplicantId, operatingExpenses.getApplicantId())
+			.eq(ObjectUtils.isNotNull(operatingExpenses.getCreateUser()), OperatingExpenses::getCreateUser, operatingExpenses.getCreateUser())
+			.eq(ObjectUtils.isNotNull(operatingExpenses.getStatus()), OperatingExpenses::getStatus, operatingExpenses.getStatus())
+			.eq(ObjectUtils.isNotNull(operatingExpenses.getSettlementPersonId()), OperatingExpenses::getSettlementPersonId, operatingExpenses.getSettlementPersonId())
+			.eq(ObjectUtils.isNotNull(operatingExpenses.getSettlementStatus()), OperatingExpenses::getSettlementStatus, operatingExpenses.getSettlementStatus())
+			.eq(ObjectUtils.isNotNull(operatingExpenses.getPaymentMethod()), OperatingExpenses::getPaymentMethod, operatingExpenses.getPaymentMethod())
+			.like(ObjectUtils.isNotNull(operatingExpenses.getBillNo()), OperatingExpenses::getBillNo, operatingExpenses.getBillNo())
+			.like(ObjectUtils.isNotNull(operatingExpenses.getBankAccount()), OperatingExpenses::getBankAccount, operatingExpenses.getBankAccount())
+			.like(ObjectUtils.isNotNull(operatingExpenses.getAccount()), OperatingExpenses::getAccount, operatingExpenses.getAccount())
+			.like(ObjectUtils.isNotNull(operatingExpenses.getBankOfDeposit()), OperatingExpenses::getBankOfDeposit, operatingExpenses.getBankOfDeposit())
+		;
+		if (ObjectUtils.isNotNull(operatingExpenses.getApplicantDateList()) && !operatingExpenses.getApplicantDateList().isEmpty()) {
+			lambdaQueryWrapper.ge(OperatingExpenses::getApplicantDate, operatingExpenses.getApplicantDateList().get(0));
+			lambdaQueryWrapper.le(OperatingExpenses::getApplicantDate, operatingExpenses.getApplicantDateList().get(1));
+		}
+		if (ObjectUtils.isNotNull(operatingExpenses.getSettlementDateList()) && !operatingExpenses.getSettlementDateList().isEmpty()) {
+			lambdaQueryWrapper.ge(OperatingExpenses::getSettlementDate, operatingExpenses.getSettlementDateList().get(0));
+			lambdaQueryWrapper.le(OperatingExpenses::getSettlementDate, operatingExpenses.getSettlementDateList().get(1));
+		}
+		IPage<OperatingExpenses> pages = operatingExpensesService.page(Condition.getPage(query), lambdaQueryWrapper);
 		return R.data(pages);
 	}
 
@@ -108,10 +135,10 @@ public class OperatingExpensesController extends BladeController {
 	@ApiOperationSupport(order = 6)
 	@ApiOperation(value = "新增或修改", notes = "传入operatingExpenses")
 	public R submit(@Valid @RequestBody OperatingExpenses operatingExpenses) {
-		return R.status(operatingExpensesService.saveOrUpdate(operatingExpenses));
+		return operatingExpensesService.submit(operatingExpenses);
 	}
 
-	
+
 	/**
 	 * 删除 营业费用
 	 */
@@ -122,5 +149,41 @@ public class OperatingExpensesController extends BladeController {
 		return R.status(operatingExpensesService.removeByIds(Func.toLongList(ids)));
 	}
 
-	
+	/**
+	 * 单据请核
+	 */
+	@PostMapping("/checkOperatingExpenses")
+	@RepeatSubmit
+	public R checkOperatingExpenses(@RequestBody OperatingExpenses operatingExpenses) {
+		return operatingExpensesService.checkOperatingExpenses(operatingExpenses);
+	}
+
+	/**
+	 * 撤销单据请核
+	 */
+	@PostMapping("/revokeCheckOperatingExpenses")
+	@RepeatSubmit
+	public R revokeCheckOperatingExpenses(@RequestBody OperatingExpenses operatingExpenses) {
+		return operatingExpensesService.revokeCheckOperatingExpenses(operatingExpenses);
+	}
+
+	/**
+	 * 确认付费
+	 */
+	@PostMapping("/confirmation")
+	@RepeatSubmit
+	public R confirmation(@RequestBody OperatingExpenses operatingExpenses) {
+		return operatingExpensesService.confirmation(operatingExpenses);
+	}
+
+	/**
+	 * 撤销确认付费
+	 */
+	@PostMapping("/revokeConfirmation")
+	@RepeatSubmit
+	public R revokeConfirmation(@RequestBody OperatingExpenses operatingExpenses) {
+		return operatingExpensesService.revokeConfirmation(operatingExpenses);
+	}
+
+
 }

+ 12 - 0
blade-service/blade-los/src/main/java/org/springblade/los/finance/operatingExpenses/service/IOperatingExpensesService.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.los.finance.operatingExpenses.service;
 
+import org.springblade.core.tool.api.R;
 import org.springblade.los.finance.operatingExpenses.entity.OperatingExpenses;
 import org.springblade.los.finance.operatingExpenses.vo.OperatingExpensesVO;
 import com.baomidou.mybatisplus.extension.service.IService;
@@ -38,4 +39,15 @@ public interface IOperatingExpensesService extends IService<OperatingExpenses> {
 	 */
 	IPage<OperatingExpensesVO> selectOperatingExpensesPage(IPage<OperatingExpensesVO> page, OperatingExpensesVO operatingExpenses);
 
+    OperatingExpenses detail(OperatingExpenses operatingExpenses);
+
+	R submit(OperatingExpenses operatingExpenses);
+
+	R checkOperatingExpenses(OperatingExpenses operatingExpenses);
+
+	R revokeCheckOperatingExpenses(OperatingExpenses operatingExpenses);
+
+	R confirmation(OperatingExpenses operatingExpenses);
+
+	R revokeConfirmation(OperatingExpenses operatingExpenses);
 }

+ 259 - 3
blade-service/blade-los/src/main/java/org/springblade/los/finance/operatingExpenses/service/impl/OperatingExpensesServiceImpl.java

@@ -16,13 +16,41 @@
  */
 package org.springblade.los.finance.operatingExpenses.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+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.los.basic.business.entity.BusinessType;
+import org.springblade.los.basic.business.service.IBusinessTypeService;
+import org.springblade.los.billno.entity.BusinessBillNo;
+import org.springblade.los.billno.service.IBusinessBillNoService;
+import org.springblade.los.business.files.entity.FilesCenter;
+import org.springblade.los.business.files.service.IFilesCenterService;
+import org.springblade.los.check.dto.LosAuditProecessDTO;
+import org.springblade.los.check.entity.LosAuditPathsActs;
+import org.springblade.los.check.entity.LosAuditPathsLevels;
+import org.springblade.los.check.service.IAuditPathsActsService;
+import org.springblade.los.check.service.IAuditPathsLevelsService;
+import org.springblade.los.check.service.IAuditProecessService;
 import org.springblade.los.finance.operatingExpenses.entity.OperatingExpenses;
-import org.springblade.los.finance.operatingExpenses.vo.OperatingExpensesVO;
+import org.springblade.los.finance.operatingExpenses.entity.OperatingExpensesItem;
 import org.springblade.los.finance.operatingExpenses.mapper.OperatingExpensesMapper;
+import org.springblade.los.finance.operatingExpenses.service.IOperatingExpensesItemService;
 import org.springblade.los.finance.operatingExpenses.service.IOperatingExpensesService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.los.finance.operatingExpenses.vo.OperatingExpensesVO;
+import org.springblade.system.feign.ISysClient;
 import org.springframework.stereotype.Service;
-import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 
 /**
  * 营业费用 服务实现类
@@ -31,11 +59,239 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
  * @since 2025-08-28
  */
 @Service
+@AllArgsConstructor
 public class OperatingExpensesServiceImpl extends ServiceImpl<OperatingExpensesMapper, OperatingExpenses> implements IOperatingExpensesService {
 
+	private final IOperatingExpensesItemService operatingExpensesItemService;
+
+	private final IFilesCenterService filesCenterService;
+
+	private final ISysClient sysClient;
+
+	private final IBusinessBillNoService businessBillNoService;
+
+	private final IBusinessTypeService bBusinessTypeService;
+
+	private final IAuditPathsActsService auditPathsActsService;
+
+	private final IAuditPathsLevelsService auditPathsLevelsService;
+
+	private final IAuditProecessService auditProecessService;
+
 	@Override
 	public IPage<OperatingExpensesVO> selectOperatingExpensesPage(IPage<OperatingExpensesVO> page, OperatingExpensesVO operatingExpenses) {
 		return page.setRecords(baseMapper.selectOperatingExpensesPage(page, operatingExpenses));
 	}
 
+	@Override
+	public OperatingExpenses detail(OperatingExpenses operatingExpenses) {
+		if (operatingExpenses.getId() == null) {
+			throw new RuntimeException("缺少必要参数");
+		}
+		OperatingExpenses detail = baseMapper.selectById(operatingExpenses.getId());
+		List<OperatingExpensesItem> operatingExpensesItemList = operatingExpensesItemService.list(new LambdaQueryWrapper<OperatingExpensesItem>()
+			.eq(OperatingExpensesItem::getTenantId, AuthUtil.getTenantId())
+			.eq(OperatingExpensesItem::getIsDeleted, 0)
+			.eq(OperatingExpensesItem::getPid, operatingExpenses.getId()));
+		detail.setOperatingExpensesItemList(operatingExpensesItemList.isEmpty() ? new ArrayList<>() : operatingExpensesItemList);
+		List<FilesCenter> filesCenterList = filesCenterService.list(new LambdaQueryWrapper<FilesCenter>()
+			.eq(FilesCenter::getTenantId, AuthUtil.getTenantId())
+			.eq(FilesCenter::getIsDeleted, 0)
+			.eq(FilesCenter::getPid, operatingExpenses.getId()));
+		detail.setFilesCenterList(filesCenterList.isEmpty() ? new ArrayList<>() : filesCenterList);
+		return detail;
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R submit(OperatingExpenses operatingExpenses) {
+		String branchId;
+		String deptName = "";
+		if (ObjectUtils.isNull(operatingExpenses.getBranchId())) {
+			branchId = AuthUtil.getDeptId();
+		} else {
+			branchId = operatingExpenses.getBranchId();
+		}
+		//获取部门ids对应中文名
+		R<String> res = sysClient.getDeptName(Long.parseLong(branchId));
+		if (res.isSuccess() && ObjectUtils.isNotNull(res.getData())) {
+			deptName = res.getData();
+		}
+		if (operatingExpenses.getId() == null) {
+			BusinessType businessType = bBusinessTypeService.getOne(new LambdaQueryWrapper<BusinessType>()
+				.eq(BusinessType::getTenantId, AuthUtil.getTenantId())
+				.eq(BusinessType::getIsDeleted, 0)
+				.eq(BusinessType::getStatus, 0)
+				.eq(BusinessType::getCode, "YYFY"));
+			if (businessType == null) {
+				throw new RuntimeException("未找到可用业务类型");
+			}
+			BusinessBillNo businessBillNo = new BusinessBillNo();
+			businessBillNo.setBusinessTypeId(businessType.getId());
+			businessBillNo.setCode("YYFY");
+			businessBillNo.setBranchId(branchId);
+			businessBillNo.setDate(operatingExpenses.getApplicantDate());
+			R clientBillNo = businessBillNoService.getBillNoLos(businessBillNo);
+			if (!clientBillNo.isSuccess()) {
+				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+				return R.fail(500, "生成订单编号失败");
+			}
+			operatingExpenses.setBillNo((String) clientBillNo.getData());
+			operatingExpenses.setCreateTime(new Date());
+			operatingExpenses.setCreateUser(AuthUtil.getUserId());
+			operatingExpenses.setCreateUserName(AuthUtil.getUserName());
+			operatingExpenses.setBranchId(branchId);
+			baseMapper.insert(operatingExpenses);
+		} else {
+			operatingExpenses.setUpdateUser(AuthUtil.getUserId());
+			operatingExpenses.setUpdateTime(new Date());
+			operatingExpenses.setUpdateUserName(AuthUtil.getUserName());
+		}
+		if (ObjectUtils.isNotNull(operatingExpenses.getOperatingExpensesItemList())) {
+			BigDecimal amount = new BigDecimal("0.00");
+			for (OperatingExpensesItem item : operatingExpenses.getOperatingExpensesItemList()) {
+				amount = amount.add(item.getAmount());
+				item.setPid(operatingExpenses.getId());
+				if (item.getId() == null) {
+					item.setCreateTime(new Date());
+					item.setCreateUser(AuthUtil.getUserId());
+					item.setCreateUserName(AuthUtil.getUserName());
+					item.setBranchId(branchId);
+					item.setBranchName(deptName);
+				} else {
+					item.setUpdateUser(AuthUtil.getUserId());
+					item.setUpdateTime(new Date());
+					item.setUpdateUserName(AuthUtil.getUserName());
+				}
+			}
+			operatingExpensesItemService.saveOrUpdateBatch(operatingExpenses.getOperatingExpensesItemList());
+			operatingExpenses.setAmount(amount);
+		}
+		this.saveOrUpdate(operatingExpenses);
+		if (ObjectUtils.isNotNull(operatingExpenses.getFilesCenterList())) {
+			for (FilesCenter item : operatingExpenses.getFilesCenterList()) {
+				item.setPid(operatingExpenses.getId());
+				if (item.getId() == null) {
+					item.setCreateTime(new Date());
+					item.setCreateUser(AuthUtil.getUserId());
+					item.setCreateUserName(AuthUtil.getUserName());
+					if (ObjectUtils.isNotNull(AuthUtil.getDeptId())) {
+						item.setCreateDeptName(deptName);
+					}
+				} else {
+					item.setUpdateUser(AuthUtil.getUserId());
+					item.setUpdateTime(new Date());
+					item.setUpdateUserName(AuthUtil.getUserName());
+				}
+			}
+			filesCenterService.saveOrUpdateBatch(operatingExpenses.getFilesCenterList());
+		}
+		return R.data(operatingExpenses);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R checkOperatingExpenses(OperatingExpenses operatingExpenses) {
+		OperatingExpenses declare = baseMapper.selectById(operatingExpenses.getId());
+		Integer actId = 1136;
+		String processType = "营业费用请核";
+		String checkType = "YYFY";
+		//审批数据
+		LosAuditProecessDTO auditProecessDTO = new LosAuditProecessDTO();
+		//获取审批级次
+		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, declare.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, declare.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));
+		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(operatingExpenses.getUrl());
+			auditProecessDTO.setPageStatus(operatingExpenses.getPageStatus());
+			auditProecessDTO.setPageLabel(operatingExpenses.getPageLabel());
+			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.setSalesCompanyId(Long.parseLong(declare.getBranchId()));
+			auditProecessDTO.setSalesCompanyName(declare.getBranchName());
+			auditProecessDTO.setPayAmount(declare.getAmount());
+			R financeProcess = auditProecessService.createFinanceProcess(auditProecessDTO);
+			if (!financeProcess.isSuccess()) {
+				throw new SecurityException("操作失败,请联系管理员");
+			}
+		}
+		declare.setStatus("1");
+		baseMapper.updateById(declare);
+		return R.data(declare);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R revokeCheckOperatingExpenses(OperatingExpenses operatingExpenses) {
+		OperatingExpenses declare = baseMapper.selectById(operatingExpenses.getId());
+		R financeProcess = auditProecessService.deteleByBillId(operatingExpenses.getId());
+		if (!financeProcess.isSuccess()) {
+			throw new SecurityException("操作失败,请联系管理员");
+		}
+		operatingExpenses.setStatus("0");
+		baseMapper.updateById(declare);
+		return R.data(declare);
+	}
+
+	@Override
+	public R confirmation(OperatingExpenses operatingExpenses) {
+		OperatingExpenses declare = baseMapper.selectById(operatingExpenses.getId());
+		operatingExpenses.setSettlementStatus("1");
+		operatingExpenses.setSettlementDate(new Date());
+		operatingExpenses.setSettlementPersonId(AuthUtil.getUserId());
+		operatingExpenses.setSettlementPersonName(AuthUtil.getUserName());
+		baseMapper.updateById(declare);
+		return R.data(declare);
+	}
+
+	@Override
+	public R revokeConfirmation(OperatingExpenses operatingExpenses) {
+		OperatingExpenses declare = baseMapper.selectById(operatingExpenses.getId());
+		operatingExpenses.setSettlementStatus("0");
+		operatingExpenses.setSettlementDate(null);
+		operatingExpenses.setSettlementPersonId(null);
+		operatingExpenses.setSettlementPersonName(null);
+		baseMapper.updateById(declare);
+		return R.data(declare);
+	}
+
 }

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

@@ -179,10 +179,10 @@ public class StatisticAnalysisServiceImpl implements IStatisticAnalysisService {
 							.setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightDr = feeCenterList.stream()
 							.filter(e -> i.getId().equals(e.getPid()) && "HYF".equals(e.getFeeCode()) && "D".equals(e.getDc()))
-							.map(FeeCenter::getAmountLoc).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
+							.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightCr = feeCenterList.stream()
 							.filter(e -> i.getId().equals(e.getPid()) && "HYF".equals(e.getFeeCode()) && "C".equals(e.getDc()))
-							.map(FeeCenter::getAmountLoc).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
+							.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightProfit = oceanFreightDr.subtract(oceanFreightCr);
 						item.setOceanFreightCr(item.getOceanFreightCr().add(oceanFreightCr));
 						item.setOceanFreightDr(item.getOceanFreightDr().add(oceanFreightDr));
@@ -717,10 +717,10 @@ public class StatisticAnalysisServiceImpl implements IStatisticAnalysisService {
 							.setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightDr = feeCenterList.stream()
 							.filter(e -> i.getId().equals(e.getPid()) && "HYF".equals(e.getFeeCode()) && "D".equals(e.getDc()))
-							.map(FeeCenter::getAmountLoc).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
+							.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightCr = feeCenterList.stream()
 							.filter(e -> i.getId().equals(e.getPid()) && "HYF".equals(e.getFeeCode()) && "C".equals(e.getDc()))
-							.map(FeeCenter::getAmountLoc).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
+							.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightProfit = oceanFreightDr.subtract(oceanFreightCr);
 						item.setOceanFreightCr(item.getOceanFreightCr().add(oceanFreightCr));
 						item.setOceanFreightDr(item.getOceanFreightDr().add(oceanFreightDr));
@@ -888,10 +888,10 @@ public class StatisticAnalysisServiceImpl implements IStatisticAnalysisService {
 							.setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightDr = feeCenterList.stream()
 							.filter(e -> i.getId().equals(e.getPid()) && "HYF".equals(e.getFeeCode()) && "D".equals(e.getDc()))
-							.map(FeeCenter::getAmountLoc).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
+							.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightCr = feeCenterList.stream()
 							.filter(e -> i.getId().equals(e.getPid()) && "HYF".equals(e.getFeeCode()) && "C".equals(e.getDc()))
-							.map(FeeCenter::getAmountLoc).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
+							.map(FeeCenter::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
 						BigDecimal oceanFreightProfit = oceanFreightDr.subtract(oceanFreightCr);
 						item.setOceanFreightCr(item.getOceanFreightCr().add(oceanFreightCr));
 						item.setOceanFreightDr(item.getOceanFreightDr().add(oceanFreightDr));

+ 6 - 0
blade-service/blade-los/src/main/java/org/springblade/los/view/mapper/FinanceProfitMapper.xml

@@ -130,6 +130,9 @@
         <if test='data.srcId != null'>
             and seb.src_id = #{data.srcId}
         </if>
+        <if test="data.boxbelongsTo != null and data.boxbelongsTo != ''">
+            and seb.box_belongs_to = #{data.boxbelongsTo}
+        </if>
         <if test='data.examine != null and data.examine != "" and data.examine == "1"'>
             and seb.status = 3
         </if>
@@ -245,6 +248,9 @@
         <if test='data.srcId != null'>
             and seb.src_id = #{data.srcId}
         </if>
+        <if test="data.boxbelongsTo != null and data.boxbelongsTo != ''">
+            and seb.box_belongs_to = #{data.boxbelongsTo}
+        </if>
         <if test='data.examine != null and data.examine != "" and data.examine == "1"'>
             and seb.status = 3
         </if>