Browse Source

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

liyuan 10 months ago
parent
commit
7bf6eb7b3a
20 changed files with 2031 additions and 10 deletions
  1. 34 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/dto/InvoicingDTO.java
  2. 34 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/dto/InvoicingItemDTO.java
  3. 182 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/entity/Invoicing.java
  4. 133 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/entity/InvoicingItem.java
  5. 36 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/vo/InvoicingItemVO.java
  6. 36 0
      blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/vo/InvoicingVO.java
  7. 1 0
      blade-service/blade-los/src/main/java/org/springblade/los/Util/MagicValues.java
  8. 904 3
      blade-service/blade-los/src/main/java/org/springblade/los/basic/reports/service/impl/ReportsServiceImpl.java
  9. 126 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/controller/InvoicingController.java
  10. 126 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/controller/InvoicingItemController.java
  11. 42 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingItemMapper.java
  12. 33 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingItemMapper.xml
  13. 42 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingMapper.java
  14. 39 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingMapper.xml
  15. 41 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/service/IInvoicingItemService.java
  16. 45 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/service/IInvoicingService.java
  17. 6 6
      blade-service/blade-los/src/main/java/org/springblade/los/trade/service/impl/AgentServiceImpl.java
  18. 41 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/service/impl/InvoicingItemServiceImpl.java
  19. 129 0
      blade-service/blade-los/src/main/java/org/springblade/los/trade/service/impl/InvoicingServiceImpl.java
  20. 1 1
      blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java

+ 34 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/dto/InvoicingDTO.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.trade.dto;
+
+import org.springblade.los.trade.entity.Invoicing;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 开票申请表数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class InvoicingDTO extends Invoicing {
+	private static final long serialVersionUID = 1L;
+
+}

+ 34 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/dto/InvoicingItemDTO.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.trade.dto;
+
+import org.springblade.los.trade.entity.InvoicingItem;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 开票申请明细表数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class InvoicingItemDTO extends InvoicingItem {
+	private static final long serialVersionUID = 1L;
+
+}

+ 182 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/entity/Invoicing.java

@@ -0,0 +1,182 @@
+/*
+ *      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.trade.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 开票申请表实体类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Data
+@TableName("trade_invoicing")
+@ApiModel(value = "Invoicing对象", description = "开票申请表")
+public class Invoicing implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private Long id;
+	/**
+	 * 备注
+	 */
+	@ApiModelProperty(value = "备注")
+	private String remarks;
+	/**
+	 * 版本
+	 */
+	@ApiModelProperty(value = "版本")
+	private String version;
+	/**
+	 * 创建人
+	 */
+	@ApiModelProperty(value = "创建人")
+	private Long createUser;
+	/**
+	 * 创建人名称
+	 */
+	@ApiModelProperty(value = "创建人名称")
+	private String createUserName;
+	/**
+	 * 创建时间
+	 */
+	@ApiModelProperty(value = "创建时间")
+	private Date createTime;
+	/**
+	 * 修改人
+	 */
+	@ApiModelProperty(value = "修改人")
+	private Long updateUser;
+	/**
+	 * 修改人名称
+	 */
+	@ApiModelProperty(value = "修改人名称")
+	private String updateUserName;
+	/**
+	 * 修改时间
+	 */
+	@ApiModelProperty(value = "修改时间")
+	private Date updateTime;
+	/**
+	 * 状态(0 正常 1停用)
+	 */
+	@ApiModelProperty(value = "状态(0 正常 1停用)")
+	private String status;
+	/**
+	 * 是否已删除(0 否 1是)
+	 */
+	@ApiModelProperty(value = "是否已删除(0 否 1是)")
+	private Integer isDeleted;
+	/**
+	 * 公司名称
+	 */
+	@ApiModelProperty(value = "公司名称")
+	private String buyCorporateName;
+	/**
+	 * 纳税人识别号
+	 */
+	@ApiModelProperty(value = "纳税人识别号")
+	private String taxpayerIdentification;
+	/**
+	 * 地址、电话
+	 */
+	@ApiModelProperty(value = "地址、电话")
+	private String addressTel;
+	/**
+	 * 开户行
+	 */
+	@ApiModelProperty(value = "开户行")
+	private String openingBank;
+	/**
+	 * 账号
+	 */
+	@ApiModelProperty(value = "账号")
+	private String accountNumber;
+	/**
+	 * 业务主办(通知人)
+	 */
+	@ApiModelProperty(value = "业务主办(通知人)")
+	private Long businessOrganizerId;
+	/**
+	 * 业务主办(通知人)
+	 */
+	@ApiModelProperty(value = "业务主办(通知人)")
+	private String businessOrganizerName;
+	/**
+	 * 开具发票号码
+	 */
+	@ApiModelProperty(value = "开具发票号码")
+	private String invoiceNo;
+	/**
+	 * 合同号
+	 */
+	@ApiModelProperty(value = "合同号")
+	private String contractNumber;
+	/**
+	 * 开具发票金额
+	 */
+	@ApiModelProperty(value = "开具发票金额")
+	private BigDecimal invoiceAmount;
+	/**
+	 * 销售公司
+	 */
+	@ApiModelProperty(value = "销售公司")
+	private Long corporateId;
+	/**
+	 * 销售公司
+	 */
+	@ApiModelProperty(value = "销售公司")
+	private String corporateName;
+	@ApiModelProperty(value = "租户")
+	private String tenantId;
+	/**
+	 * 业务号
+	 */
+	@ApiModelProperty(value = "业务号")
+	private String businessNo;
+	/**
+	 * 业务时间
+	 */
+	@ApiModelProperty(value = "业务时间")
+	private Date businessDate;
+	@TableField(exist = false)
+	private List<InvoicingItem> invoicingItemList;
+	/**
+	 * 编码生成code
+	 */
+	@TableField(exist = false)
+	private String billNoFormat;
+
+	/**
+	 * 业务类型表 code
+	 */
+	@TableField(exist = false)
+	private String businessTypeCode;
+
+
+}

+ 133 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/entity/InvoicingItem.java

@@ -0,0 +1,133 @@
+/*
+ *      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.trade.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 开票申请明细表实体类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Data
+@TableName("trade_invoicing_item")
+@ApiModel(value = "InvoicingItem对象", description = "开票申请明细表")
+public class InvoicingItem implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private Long id;
+	private Long pid;
+	/**
+	 * 备注
+	 */
+	@ApiModelProperty(value = "备注")
+	private String remarks;
+	/**
+	 * 版本
+	 */
+	@ApiModelProperty(value = "版本")
+	private String version;
+	/**
+	 * 创建人
+	 */
+	@ApiModelProperty(value = "创建人")
+	private Long createUser;
+	/**
+	 * 创建人名称
+	 */
+	@ApiModelProperty(value = "创建人名称")
+	private String createUserName;
+	/**
+	 * 创建时间
+	 */
+	@ApiModelProperty(value = "创建时间")
+	private Date createTime;
+	/**
+	 * 修改人
+	 */
+	@ApiModelProperty(value = "修改人")
+	private Long updateUser;
+	/**
+	 * 修改人名称
+	 */
+	@ApiModelProperty(value = "修改人名称")
+	private String updateUserName;
+	/**
+	 * 修改时间
+	 */
+	@ApiModelProperty(value = "修改时间")
+	private Date updateTime;
+	/**
+	 * 状态(0 正常 1停用)
+	 */
+	@ApiModelProperty(value = "状态(0 正常 1停用)")
+	private String status;
+	/**
+	 * 是否已删除(0 否 1是)
+	 */
+	@ApiModelProperty(value = "是否已删除(0 否 1是)")
+	private Integer isDeleted;
+	/**
+	 * 标签品名
+	 */
+	@ApiModelProperty(value = "标签品名")
+	private String labelProductName;
+	/**
+	 * 件数
+	 */
+	@ApiModelProperty(value = "件数")
+	private BigDecimal quantity;
+	/**
+	 * 单价
+	 */
+	@ApiModelProperty(value = "单价")
+	private BigDecimal price;
+	/**
+	 * 金额
+	 */
+	@ApiModelProperty(value = "金额")
+	private BigDecimal amount;
+	/**
+	 * 本次发票金额
+	 */
+	@ApiModelProperty(value = "本次发票金额")
+	private BigDecimal thisAmount;
+	/**
+	 * 已开发票金额
+	 */
+	@ApiModelProperty(value = "已开发票金额")
+	private BigDecimal invoicedAmount;
+	/**
+	 * 规格
+	 */
+	@ApiModelProperty(value = "规格")
+	private String specifications;
+	@ApiModelProperty(value = "租户")
+	private String tenantId;
+
+
+}

+ 36 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/vo/InvoicingItemVO.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.trade.vo;
+
+import org.springblade.los.trade.entity.InvoicingItem;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import io.swagger.annotations.ApiModel;
+
+/**
+ * 开票申请明细表视图实体类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "InvoicingItemVO对象", description = "开票申请明细表")
+public class InvoicingItemVO extends InvoicingItem {
+	private static final long serialVersionUID = 1L;
+
+}

+ 36 - 0
blade-service-api/blade-los-api/src/main/java/org/springblade/los/trade/vo/InvoicingVO.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.trade.vo;
+
+import org.springblade.los.trade.entity.Invoicing;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import io.swagger.annotations.ApiModel;
+
+/**
+ * 开票申请表视图实体类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "InvoicingVO对象", description = "开票申请表")
+public class InvoicingVO extends Invoicing {
+	private static final long serialVersionUID = 1L;
+
+}

+ 1 - 0
blade-service/blade-los/src/main/java/org/springblade/los/Util/MagicValues.java

@@ -31,6 +31,7 @@ public class MagicValues {
 	public static final String DISPATCH_NOTICE = "派车通知单";
 	public static final String INCOMING_NOTIFICATION = "入货通知";
 	public static final String SALES_REPORT = "销售报告";
+	public static final String SALES_REPORT_AMEND = "销售报告-amend";
 
 	public static final String ORDER_ALLOCATION = "配单";
 

+ 904 - 3
blade-service/blade-los/src/main/java/org/springblade/los/basic/reports/service/impl/ReportsServiceImpl.java

@@ -2794,6 +2794,904 @@ public class ReportsServiceImpl extends ServiceImpl<ReportsMapper, Reports> impl
 			} else {
 				map.put(MagicValues.DATA, null);
 			}
+		} else if (MagicValues.BUSINESS.equals(reportCode) && MagicValues.SALES_REPORT_AMEND.equals(groupCode) && (MagicValues.HYCK.equals(type) || MagicValues.HYJK.equals(type))) {
+			List<Bills> list = new ArrayList<>();
+			Bills bills = billsService.getById(billId);
+			if (bills != null) {
+				R<String> biz = dictBizClient.getOneValue("src_type_los", bills.getSrcType(), AuthUtil.getTenantId());
+				if (biz.isSuccess()) {
+					bills.setSrcType(biz.getData());
+				}
+				// 提取分表
+				SeaBillsDetail seaBillsDetail = seaBillsDetailService.getOne(new LambdaQueryWrapper<SeaBillsDetail>()
+					.eq(SeaBillsDetail::getTenantId, AuthUtil.getTenantId())
+					.eq(SeaBillsDetail::getPid, bills.getId()));
+				if (seaBillsDetail != null) {
+					bills.setInttraToDoorCorpName(seaBillsDetail.getInttraToDoorCorpName());
+					bills.setInttraToDoorCorpAddr(seaBillsDetail.getInttraToDoorCorpAddr());
+					bills.setInttraToDoorCorpContacts(seaBillsDetail.getInttraToDoorCorpContacts());
+					bills.setInttraToDoorCorpTel(seaBillsDetail.getInttraToDoorCorpTel());
+					bills.setInttraDoorToCorpName(seaBillsDetail.getInttraDoorToCorpName());
+					bills.setInttraDoorToCorpAddr(seaBillsDetail.getInttraDoorToCorpAddr());
+					bills.setInttraDoorToCorpContacts(seaBillsDetail.getInttraDoorToCorpContacts());
+					bills.setInttraDoorToCorpTel(seaBillsDetail.getInttraDoorToCorpTel());
+					bills.setHshipperId(seaBillsDetail.getHshipperId());
+					bills.setHshipperCode(seaBillsDetail.getHshipperCode());
+					bills.setHshipperCnName(seaBillsDetail.getHshipperCnName());
+					bills.setHshipperEnName(seaBillsDetail.getHshipperEnName());
+					bills.setHshipperDetails(seaBillsDetail.getHshipperDetails());
+					bills.setHconsigneeId(seaBillsDetail.getHconsigneeId());
+					bills.setHconsigneeCode(seaBillsDetail.getHconsigneeCode());
+					bills.setHconsigneeCnName(seaBillsDetail.getHconsigneeCnName());
+					bills.setHconsigneeEnName(seaBillsDetail.getHconsigneeEnName());
+					bills.setHconsigneeDetails(seaBillsDetail.getHconsigneeDetails());
+					bills.setHnotifyId(seaBillsDetail.getHnotifyId());
+					bills.setHnotifyCode(seaBillsDetail.getHnotifyCode());
+					bills.setHnotifyCnName(seaBillsDetail.getHnotifyCnName());
+					bills.setHnotifyEnName(seaBillsDetail.getHnotifyEnName());
+					bills.setHnotifyDetails(seaBillsDetail.getHnotifyDetails());
+					bills.setHnotify2Id(seaBillsDetail.getHnotify2Id());
+					bills.setHnotify2Code(seaBillsDetail.getHnotify2Code());
+					bills.setHnotify2CnName(seaBillsDetail.getHnotify2CnName());
+					bills.setHnotify2EnName(seaBillsDetail.getHnotify2EnName());
+					bills.setHnotify2Details(seaBillsDetail.getHnotify2Details());
+					bills.setMshipperId(seaBillsDetail.getMshipperId());
+					bills.setMshipperCode(seaBillsDetail.getMshipperCode());
+					bills.setMshipperCnName(seaBillsDetail.getMshipperCnName());
+					bills.setMshipperEnName(seaBillsDetail.getMshipperEnName());
+					bills.setMshipperDetails(seaBillsDetail.getMshipperDetails());
+					bills.setMconsigneeId(seaBillsDetail.getMconsigneeId());
+					bills.setMconsigneeCode(seaBillsDetail.getMconsigneeCode());
+					bills.setMconsigneeCnName(seaBillsDetail.getMconsigneeCnName());
+					bills.setMconsigneeEnName(seaBillsDetail.getMconsigneeEnName());
+					bills.setMconsigneeDetails(seaBillsDetail.getMconsigneeDetails());
+					bills.setMnotifyId(seaBillsDetail.getMnotifyId());
+					bills.setMnotifyCode(seaBillsDetail.getMnotifyCode());
+					bills.setMnotifyCnName(seaBillsDetail.getMnotifyCnName());
+					bills.setMnotifyEnName(seaBillsDetail.getMnotifyEnName());
+					bills.setMnotifyDetails(seaBillsDetail.getMnotifyDetails());
+					bills.setMnotify2Id(seaBillsDetail.getMnotify2Id());
+					bills.setMnotify2Code(seaBillsDetail.getMnotify2Code());
+					bills.setMnotify2CnName(seaBillsDetail.getMnotify2CnName());
+					bills.setMnotify2EnName(seaBillsDetail.getMnotify2EnName());
+					bills.setMnotify2Details(seaBillsDetail.getMnotify2Details());
+					bills.setMforwarderDetails(seaBillsDetail.getMforwarderDetails());
+				}
+				HmmEdi hmmEdi = hmmEdiService.getOne(new LambdaQueryWrapper<HmmEdi>()
+					.eq(HmmEdi::getTenantId, AuthUtil.getTenantId())
+					.eq(HmmEdi::getPid, bills.getId()));
+				bills.setHmmEdi(hmmEdi != null ? hmmEdi : new HmmEdi());
+				// 提取 USD 汇率
+				if (bCurrency != null) {
+					bills.setRate(bCurrency.getExrate());
+				} else {
+					bills.setRate(new BigDecimal(MagicValues.ZERO));
+				}
+				//
+				if (ObjectUtils.isNotNull(bills.getAmountProfitLoc()) && ObjectUtils.isNotNull(bills.getAmountDrLoc())) {
+					if (bills.getAmountProfitLoc().compareTo(new BigDecimal(MagicValues.ZERO)) == 0 ||
+						bills.getAmountDrLoc().compareTo(new BigDecimal(MagicValues.ZERO)) == 0) {
+						bills.setGrossMargin(new BigDecimal(MagicValues.ZERO));
+					} else {
+						bills.setGrossMargin(bills.getAmountProfitLoc().divide(bills.getAmountDrLoc(), 4, RoundingMode.HALF_UP));
+					}
+				} else {
+					bills.setGrossMargin(new BigDecimal(MagicValues.ZERO));
+				}
+
+				if (isDebug) {
+					System.out.println("GrossMargin: " + bills.getGrossMargin().toString());
+				}
+
+				List<FeeCenter> allFeeCenter = new ArrayList<>();
+
+				// 直单或主单
+				if (MagicValues.MM.equals(bills.getBillType()) || MagicValues.DD.equals(bills.getBillType())) {
+					List<Bills> billsList = billsService.list(new LambdaQueryWrapper<Bills>()
+						.eq(Bills::getMasterId, bills.getId())
+						.eq(Bills::getTenantId, AuthUtil.getTenantId())
+						.eq(Bills::getIsDeleted, 0));
+					if (!billsList.isEmpty()) {
+						String mblNo = billsList.stream().map(Bills::getMblno).filter(Objects::nonNull).collect(Collectors.joining(","));
+						if (ObjectUtils.isNotNull(mblNo)) {
+							// 所有分单的费用
+							List<FeeCenter> feeCenterListMh = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+								.apply("find_in_set(mblno,'" + mblNo + "')")
+								.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+								.eq(FeeCenter::getIsDeleted, 0));
+							if (feeCenterListMh.isEmpty()) {
+								throw new RuntimeException("请先维护费用信息");
+							}
+							allFeeCenter.addAll(feeCenterListMh);
+							for (FeeCenter item : feeCenterListMh) {
+								if (ObjectUtils.isNotNull(item.getShortName())) {
+									item.setCorpCnName(item.getShortName());
+								} else {
+									item.setCorpCnName("无");
+								}
+								if (ObjectUtils.isNotNull(item.getBillShortName())) {
+									item.setBillCorpCnName(item.getBillShortName());
+								} else {
+									item.setBillCorpCnName("无");
+								}
+							}
+							for (Bills item : billsList) {
+								List<FeeCenter> feeD = feeCenterListMh.stream().filter(e -> MagicValues.D.equals(e.getDc())).collect(Collectors.toList());
+								item.setFeeCenterListD(feeD);
+								List<FeeCenter> feeC = feeCenterListMh.stream().filter(e -> MagicValues.C.equals(e.getDc())).collect(Collectors.toList());
+								item.setFeeCenterListC(feeC);
+								List<FeeCenter> feeCenterList = feeCenterListMh.stream()
+									.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
+										Comparator.comparing(f -> f.getFeeId() + f.getCorpId() + f.getCurCode() + f.getDc()))), ArrayList::new));
+								List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
+								for (FeeCenter fee : feeCenterList) {
+									FeeCenterReports feeCenterReports = new FeeCenterReports();
+									feeCenterReports.setRemarks(fee.getRemarks());
+									feeCenterReports.setPid(item.getId());
+									feeCenterReports.setFeeCnName(fee.getFeeCnName());
+									feeCenterReports.setDc(fee.getDc());
+									List<FeeCenter> feeCenterListD = feeCenterListMh.stream()
+										.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(item.getMblno()) &&
+											e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+											e.getCorpId().equals(fee.getCorpId()))
+										.collect(Collectors.toList());
+									if (!feeCenterListD.isEmpty()) {
+										feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+										feeCenterReports.setAmountD(feeCenterListD.stream().map(FeeCenter::getAmount)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+										feeCenterReports.setAmountLocD(feeCenterListD.stream().map(FeeCenter::getAmountLoc)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									}
+									List<FeeCenter> feeCenterListUsdD = feeCenterListMh.stream()
+										.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(item.getMblno()) &&
+											e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+											e.getCorpId().equals(fee.getCorpId()))
+										.collect(Collectors.toList());
+									if (!feeCenterListUsdD.isEmpty()) {
+										feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+										feeCenterReports.setAmountUsdD(feeCenterListUsdD.stream().map(FeeCenter::getAmount)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+										feeCenterReports.setAmountLocD(feeCenterListUsdD.stream().map(FeeCenter::getAmountLoc)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									}
+									List<FeeCenter> feeCenterListC = feeCenterListMh.stream()
+										.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(item.getMblno()) &&
+											e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+											e.getCorpId().equals(fee.getCorpId()))
+										.collect(Collectors.toList());
+									if (!feeCenterListC.isEmpty()) {
+										feeCenterReports.setCorpCnName(fee.getCorpCnName());
+										feeCenterReports.setAmountC(feeCenterListC.stream().map(FeeCenter::getAmount)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+										feeCenterReports.setAmountLocC(feeCenterListC.stream().map(FeeCenter::getAmountLoc)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									}
+									List<FeeCenter> feeCenterListUsdC = feeCenterListMh.stream()
+										.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(item.getMblno()) &&
+											e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+											e.getCorpId().equals(fee.getCorpId()))
+										.collect(Collectors.toList());
+									if (!feeCenterListUsdC.isEmpty()) {
+										feeCenterReports.setCorpCnName(fee.getCorpCnName());
+										feeCenterReports.setAmountUsdC(feeCenterListUsdC.stream().map(FeeCenter::getAmount)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+										feeCenterReports.setAmountLocC(feeCenterListUsdC.stream().map(FeeCenter::getAmountLoc)
+											.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									}
+									feeCenterReportList.add(feeCenterReports);
+								}
+								item.setFeeCenterList(feeCenterReportList);
+								list.add(item);
+							}
+						}
+					}
+					// 当前单据的费用信息
+					List<FeeCenter> feeCenterList = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+						.eq(FeeCenter::getMblno, bills.getMblno())
+						.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+						.eq(FeeCenter::getIsDeleted, 0));
+					allFeeCenter.addAll(feeCenterList);
+
+					List<FeeCenter> feeD = feeCenterList.stream().filter(e -> MagicValues.D.equals(e.getDc())).collect(Collectors.toList());
+					bills.setFeeCenterListD(feeD);
+					List<FeeCenter> feeC = feeCenterList.stream().filter(e -> MagicValues.C.equals(e.getDc())).collect(Collectors.toList());
+					bills.setFeeCenterListC(feeC);
+
+					for (FeeCenter item : feeCenterList) {
+						if (ObjectUtils.isNotNull(item.getShortName())) {
+							item.setCorpCnName(item.getShortName());
+						} else {
+							item.setCorpCnName("无");
+						}
+						if (ObjectUtils.isNotNull(item.getBillShortName())) {
+							item.setBillCorpCnName(item.getBillShortName());
+						} else {
+							item.setBillCorpCnName("无");
+						}
+					}
+					if (!feeCenterList.isEmpty()) {
+						List<FeeCenter> feeCenters = feeCenterList.stream()
+							.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
+								Comparator.comparing(f -> f.getFeeId() + f.getCorpId() + f.getCurCode() + f.getDc()))), ArrayList::new));
+						List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
+						for (FeeCenter fee : feeCenters) {
+							FeeCenterReports feeCenterReports = new FeeCenterReports();
+							feeCenterReports.setRemarks(fee.getRemarks());
+							feeCenterReports.setPid(bills.getId());
+							feeCenterReports.setFeeCnName(fee.getFeeCnName());
+							feeCenterReports.setDc(fee.getDc());
+							List<FeeCenter> feeCenterListD = feeCenterList.stream()
+								.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListD.isEmpty()) {
+								feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountD(feeCenterListD.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocD(feeCenterListD.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							List<FeeCenter> feeCenterListUsdD = feeCenterList.stream()
+								.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListUsdD.isEmpty()) {
+								feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountUsdD(feeCenterListUsdD.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocD(feeCenterListUsdD.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							List<FeeCenter> feeCenterListC = feeCenterList.stream()
+								.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListC.isEmpty()) {
+								feeCenterReports.setCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountC(feeCenterListC.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocC(feeCenterListC.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							List<FeeCenter> feeCenterListUsdC = feeCenterList.stream()
+								.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListUsdC.isEmpty()) {
+								feeCenterReports.setCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountUsdC(feeCenterListUsdC.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocC(feeCenterListUsdC.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							feeCenterReportList.add(feeCenterReports);
+						}
+						bills.setFeeCenterList(feeCenterReportList);
+					} else {
+						throw new RuntimeException("请先维护费用");
+					}
+					list.add(0, bills);
+				}
+				else if (MagicValues.MH.equals(bills.getBillType())) {
+					// 分单
+					Bills details = billsService.getOne(new LambdaQueryWrapper<Bills>()
+						.eq(Bills::getId, bills.getMasterId())
+						.eq(Bills::getTenantId, AuthUtil.getTenantId())
+						.eq(Bills::getIsDeleted, 0));
+					if (details != null) {
+						List<FeeCenter> feeCenterList = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+							.eq(FeeCenter::getMblno, bills.getMblno())
+							.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+							.eq(FeeCenter::getIsDeleted, 0));
+						if (feeCenterList.isEmpty()) {
+							throw new RuntimeException("请先维护费用信息");
+						}
+						allFeeCenter.addAll(feeCenterList);
+						List<FeeCenter> feeD = feeCenterList.stream().filter(e -> MagicValues.D.equals(e.getDc())).collect(Collectors.toList());
+						bills.setFeeCenterListD(feeD);
+						List<FeeCenter> feeC = feeCenterList.stream().filter(e -> MagicValues.C.equals(e.getDc())).collect(Collectors.toList());
+						bills.setFeeCenterListC(feeC);
+						if (!feeCenterList.isEmpty()) {
+							for (FeeCenter item : feeCenterList) {
+								if (ObjectUtils.isNotNull(item.getShortName())) {
+									item.setCorpCnName(item.getShortName());
+								} else {
+									item.setCorpCnName("无");
+								}
+								if (ObjectUtils.isNotNull(item.getBillShortName())) {
+									item.setBillCorpCnName(item.getBillShortName());
+								} else {
+									item.setBillCorpCnName("无");
+								}
+							}
+							List<FeeCenter> feeCenters = feeCenterList.stream()
+								.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
+									Comparator.comparing(f -> f.getFeeId() + f.getCorpId() + f.getCurCode() + f.getDc()))), ArrayList::new));
+							List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
+							for (FeeCenter fee : feeCenters) {
+								FeeCenterReports feeCenterReports = new FeeCenterReports();
+								feeCenterReports.setRemarks(fee.getRemarks());
+								feeCenterReports.setPid(bills.getId());
+								feeCenterReports.setFeeCnName(fee.getFeeCnName());
+								feeCenterReports.setDc(fee.getDc());
+								List<FeeCenter> feeCenterListD = feeCenterList.stream()
+									.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+										e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+										e.getCorpId().equals(fee.getCorpId()))
+									.collect(Collectors.toList());
+								if (!feeCenterListD.isEmpty()) {
+									feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+									feeCenterReports.setAmountD(feeCenterListD.stream().map(FeeCenter::getAmount)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									feeCenterReports.setAmountLocD(feeCenterListD.stream().map(FeeCenter::getAmountLoc)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								}
+								List<FeeCenter> feeCenterListUsdD = feeCenterList.stream()
+									.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+										e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+										e.getCorpId().equals(fee.getCorpId()))
+									.collect(Collectors.toList());
+								if (!feeCenterListUsdD.isEmpty()) {
+									feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+									feeCenterReports.setAmountUsdD(feeCenterListUsdD.stream().map(FeeCenter::getAmount)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									feeCenterReports.setAmountLocD(feeCenterListUsdD.stream().map(FeeCenter::getAmountLoc)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								}
+								List<FeeCenter> feeCenterListC = feeCenterList.stream()
+									.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+										e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+										e.getCorpId().equals(fee.getCorpId()))
+									.collect(Collectors.toList());
+								if (!feeCenterListC.isEmpty()) {
+									feeCenterReports.setCorpCnName(fee.getCorpCnName());
+									feeCenterReports.setAmountC(feeCenterListC.stream().map(FeeCenter::getAmount)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									feeCenterReports.setAmountLocC(feeCenterListC.stream().map(FeeCenter::getAmountLoc)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								}
+								List<FeeCenter> feeCenterListUsdC = feeCenterList.stream()
+									.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(bills.getMblno()) &&
+										e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+										e.getCorpId().equals(fee.getCorpId()))
+									.collect(Collectors.toList());
+								if (!feeCenterListUsdC.isEmpty()) {
+									feeCenterReports.setCorpCnName(fee.getCorpCnName());
+									feeCenterReports.setAmountUsdC(feeCenterListUsdC.stream().map(FeeCenter::getAmount)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+									feeCenterReports.setAmountLocC(feeCenterListUsdC.stream().map(FeeCenter::getAmountLoc)
+										.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								}
+								feeCenterReportList.add(feeCenterReports);
+							}
+							bills.setFeeCenterList(feeCenterReportList);
+						}
+						list.add(bills);
+						List<FeeCenter> feeCenterListMh = feeCenterService.list(new LambdaQueryWrapper<FeeCenter>()
+							.eq(FeeCenter::getMblno, details.getMblno())
+							.eq(FeeCenter::getTenantId, AuthUtil.getTenantId())
+							.eq(FeeCenter::getIsDeleted, 0));
+
+						allFeeCenter.addAll(feeCenterListMh);
+
+						List<FeeCenter> feeD2 = feeCenterListMh.stream().filter(e -> MagicValues.D.equals(e.getDc())).collect(Collectors.toList());
+						details.setFeeCenterListD(feeD2);
+						List<FeeCenter> feeC2 = feeCenterListMh.stream().filter(e -> MagicValues.C.equals(e.getDc())).collect(Collectors.toList());
+						details.setFeeCenterListC(feeC2);
+						for (FeeCenter item : feeCenterListMh) {
+							if (ObjectUtils.isNotNull(item.getShortName())) {
+								item.setCorpCnName(item.getShortName());
+							} else {
+								item.setCorpCnName("无");
+							}
+							if (ObjectUtils.isNotNull(item.getBillShortName())) {
+								item.setBillCorpCnName(item.getBillShortName());
+							} else {
+								item.setBillCorpCnName("无");
+							}
+						}
+						List<FeeCenter> feeCenterList1 = feeCenterListMh.stream()
+							.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
+								Comparator.comparing(f -> f.getFeeId() + f.getCorpId() + f.getCurCode() + f.getDc()))), ArrayList::new));
+						List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
+						for (FeeCenter fee : feeCenterList1) {
+							FeeCenterReports feeCenterReports = new FeeCenterReports();
+							feeCenterReports.setRemarks(fee.getRemarks());
+							feeCenterReports.setPid(details.getId());
+							feeCenterReports.setFeeCnName(fee.getFeeCnName());
+							feeCenterReports.setDc(fee.getDc());
+							List<FeeCenter> feeCenterListD = feeCenterListMh.stream()
+								.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(details.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListD.isEmpty()) {
+								feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountD(feeCenterListD.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocD(feeCenterListD.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							List<FeeCenter> feeCenterListUsdD = feeCenterListMh.stream()
+								.filter(e -> MagicValues.D.equals(e.getDc()) && e.getMblno().equals(details.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListUsdD.isEmpty()) {
+								feeCenterReports.setBillCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountUsdD(feeCenterListUsdD.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocD(feeCenterListUsdD.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							List<FeeCenter> feeCenterListC = feeCenterListMh.stream()
+								.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(details.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.CNY.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListC.isEmpty()) {
+								feeCenterReports.setCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountC(feeCenterListC.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocC(feeCenterListC.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							List<FeeCenter> feeCenterListUsdC = feeCenterListMh.stream()
+								.filter(e -> MagicValues.C.equals(e.getDc()) && e.getMblno().equals(details.getMblno()) &&
+									e.getFeeId().equals(fee.getFeeId()) && MagicValues.USD.equals(e.getCurCode()) && fee.getCurCode().equals(e.getCurCode()) &&
+									e.getCorpId().equals(fee.getCorpId()))
+								.collect(Collectors.toList());
+							if (!feeCenterListUsdC.isEmpty()) {
+								feeCenterReports.setCorpCnName(fee.getCorpCnName());
+								feeCenterReports.setAmountUsdC(feeCenterListUsdC.stream().map(FeeCenter::getAmount)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+								feeCenterReports.setAmountLocC(feeCenterListUsdC.stream().map(FeeCenter::getAmountLoc)
+									.filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
+							}
+							feeCenterReportList.add(feeCenterReports);
+						}
+						details.setFeeCenterList(feeCenterReportList);
+						list.add(0, details);
+					}
+				}
+				if (!list.isEmpty()) {
+					for (Bills item : list) {
+						List<FeeCenterReports> feeCenterReports = new ArrayList<>();
+						// 应收
+						List<FeeCenterReports> feeCenterReportsD = item.getFeeCenterList().stream()
+							.filter(e -> MagicValues.D.equals(e.getDc())).collect(Collectors.toList()) == null ? new ArrayList<>() :
+							item.getFeeCenterList().stream().filter(e -> MagicValues.D.equals(e.getDc())).collect(Collectors.toList());
+						// 应付
+						List<FeeCenterReports> feeCenterReportsC = item.getFeeCenterList().stream()
+							.filter(e -> MagicValues.C.equals(e.getDc())).collect(Collectors.toList()) == null ? new ArrayList<>() :
+							item.getFeeCenterList().stream().filter(e -> MagicValues.C.equals(e.getDc())).collect(Collectors.toList());
+						// 排序
+						List<FeeCenterReports> feeCentersD = feeCenterReportsD.stream()
+							.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
+								Comparator.comparing(e -> e.getFeeCnName() + e.getBillCorpCnName()))), ArrayList::new));
+						int countC = 0;
+						// 遍历应收,并与应付对应
+						for (int i = 0; i < feeCentersD.size(); i++) {
+							FeeCenterReports feeCenterReports1 = new FeeCenterReports();
+							feeCenterReports1.setFeeCnName(feeCentersD.get(i).getFeeCnName());
+							feeCenterReports1.setHblno(feeCentersD.get(i).getHblno());
+							feeCenterReports1.setPid(feeCentersD.get(i).getPid());
+							int finalI = i;
+							FeeCenterReports feeCenterC = feeCenterReportsC.stream()
+								.filter(e -> e.getFeeCnName().equals(feeCentersD.get(finalI).getFeeCnName()) && !"1".equals(e.getMark())).findFirst().orElse(null);
+							feeCenterReports1.setBillCorpCnName(feeCentersD.get(i).getBillCorpCnName());
+							feeCenterReports1.setAmountD(feeCentersD.get(i).getAmountD());
+							feeCenterReports1.setAmountLocD(feeCentersD.get(i).getAmountLocD());
+							feeCenterReports1.setAmountUsdD(feeCentersD.get(i).getAmountUsdD());
+							if (feeCenterC != null) {
+								feeCenterC.setMark("1");
+								feeCenterReports1.setCorpCnName(feeCenterC.getCorpCnName());
+								feeCenterReports1.setAmountC(feeCenterC.getAmountC());
+								feeCenterReports1.setAmountLocC(feeCenterC.getAmountLocC());
+								feeCenterReports1.setAmountUsdC(feeCenterC.getAmountUsdC());
+								countC++;
+							}
+							feeCenterReports.add(feeCenterReports1);
+						}
+						// 如果存在未对应的应付,添加应付费用
+						if (countC < feeCenterReportsC.size()) {
+							List<FeeCenterReports> feeCe = feeCenterReportsC.stream()
+								.filter(e -> !"1".equals(e.getMark())).collect(Collectors.toList());
+							for (FeeCenterReports i : feeCe) {
+								FeeCenterReports feeCenterReports1 = new FeeCenterReports();
+								feeCenterReports1.setCorpCnName(i.getCorpCnName());
+								feeCenterReports1.setFeeCnName(i.getFeeCnName());
+								feeCenterReports1.setHblno(i.getHblno());
+								feeCenterReports1.setPid(i.getPid());
+								feeCenterReports1.setAmountC(i.getAmountC());
+								feeCenterReports1.setAmountLocC(i.getAmountLocC());
+								feeCenterReports1.setAmountUsdC(i.getAmountUsdC());
+								feeCenterReports.add(feeCenterReports1);
+							}
+						}
+						if (ObjectUtils.isNotNull(item.getAmountProfitLoc()) && ObjectUtils.isNotNull(item.getAmountDrLoc())) {
+							if (item.getAmountProfitLoc().compareTo(new BigDecimal(MagicValues.ZERO)) == 0 ||
+								item.getAmountDrLoc().compareTo(new BigDecimal(MagicValues.ZERO)) == 0) {
+								item.setGrossMargin(new BigDecimal(MagicValues.ZERO));
+							} else {
+								item.setGrossMargin(item.getAmountProfitLoc().divide(item.getAmountDrLoc(), 4, RoundingMode.HALF_UP));
+							}
+						} else {
+							item.setGrossMargin(new BigDecimal(MagicValues.ZERO));
+						}
+
+						if (isDebug) {
+							System.out.println(item.getId().toString() + ", " + item.getBillNo() + ", GrossMargin: " + bills.getGrossMargin().toString());
+						}
+						// 费用名称
+						// 1722822288795000833	O/F		海运费	145
+						// 1722823384343011329	P/S		P/S		220
+						// 1746015648988901393	HP/S	HP/S	623
+						// 特殊 PS 客户名称
+						// 1425		W0077	W0077
+						// 1561		W0091	W0091
+						// 3415		W0256	W0256
+						// 5110		W0312	W0312
+						// 6363		W0380	W0380
+						// 10120	W0582	W0582
+						// 11794	W0643	W0643
+						// 12247	W0661	W0661
+						// 12431	W0675	W0675
+						// 12731	W0689	W0689
+						String specPScorpIds = ",1425,1561,3415,5110,6363,10120,11794,12247,12431,12731,";
+
+						List<FeeCenter> feeList = Stream.concat(item.getFeeCenterListD().stream(), item.getFeeCenterListC().stream()).collect(Collectors.toList());
+
+						BigDecimal usdOFProfit = new BigDecimal(BigInteger.ZERO);
+						BigDecimal ofInAmtProfit = new BigDecimal(BigInteger.ZERO);
+						Integer ofCNYCount = 0;
+
+						BigDecimal HPSProfit = new BigDecimal(BigInteger.ZERO);
+						BigDecimal specProfit = new BigDecimal(BigInteger.ZERO);
+						BigDecimal specInAmtProfit = new BigDecimal(BigInteger.ZERO);
+
+						BigDecimal psProfit = new BigDecimal(BigInteger.ZERO);
+						BigDecimal psInAmtProfit = new BigDecimal(BigInteger.ZERO);
+
+						// 特殊ps客户 Id
+						Long specPSCorpId = 0L;
+						// 高收退费客户 Id
+						Long hpsCorpId = 0L;
+
+						if (ObjectUtils.isNotNull(feeList)) {
+							for (FeeCenter fee : feeList) {
+								if (specPSCorpId == 0 && ObjectUtils.isNotNull(fee.getCorpId())) {
+									if (specPScorpIds.indexOf("," + fee.getCorpId().toString() + ",") >= 0) {
+										specPSCorpId = fee.getCorpId();
+									}
+								}
+								BigDecimal amt = fee.getAmount();
+								if (MagicValues.C.equals(fee.getDc())) {
+									amt = amt.multiply(new BigDecimal(-1));
+								}
+								if (MagicValues.USD.equals(fee.getCurCode())) {
+									if ("O/F".equals(fee.getFeeCode())) {
+										// 145
+										usdOFProfit = usdOFProfit.add(amt);
+									}
+									if ("P/S".equals(fee.getFeeCode())) {
+										// 220
+										psProfit = psProfit.subtract(amt);
+									}
+									if ("HP/S".equals(fee.getFeeCode())) {
+										if (hpsCorpId == 0 && ObjectUtils.isNotNull(fee.getCorpId())) {
+											hpsCorpId = fee.getCorpId();
+										}
+										// 623
+										HPSProfit = HPSProfit.add(amt);
+										specProfit = specProfit.subtract(amt);
+									}
+								} else {
+									if ("O/F".equals(fee.getFeeCode())) {
+										// 145
+										ofInAmtProfit = ofInAmtProfit.add(amt.divide(new BigDecimal("6.8"), 2, BigDecimal.ROUND_HALF_UP));
+										ofCNYCount += 1;
+									}
+									if ("P/S".equals(fee.getFeeCode())) {
+										// 220
+										psInAmtProfit = psInAmtProfit.add(amt);
+									}
+									if ("HP/S".equals(fee.getFeeCode())) {
+										if (hpsCorpId == 0 && ObjectUtils.isNotNull(fee.getCorpId())) {
+											hpsCorpId = fee.getCorpId();
+										}
+										// 623
+										specInAmtProfit = specInAmtProfit.subtract(amt);
+									}
+								}
+							}
+						}
+
+						// 提取客户 PsRate
+						BCorps bCorps11 = bCorpsService.getById(item.getCorpId());
+						BigDecimal PsRate = new BigDecimal(BigInteger.ZERO);
+						Integer corpIsDC = 0;
+						if (ObjectUtils.isNotNull(bCorps11)) {
+							PsRate = new BigDecimal(bCorps11.getPsRate());
+							if (ObjectUtils.isNotNull(bCorps11.getCorpTypeName()) && bCorps11.getCorpTypeName().indexOf("国内直接客户") >= 0) {
+								corpIsDC = 1;
+							}
+						}
+						BigDecimal specPsRate = new BigDecimal(BigInteger.ZERO);
+						Boolean isPS = false;
+
+						if (specPSCorpId > 0) {
+							BCorps bCorps12 = bCorpsService.getById(specPSCorpId);
+							if (ObjectUtils.isNotNull(bCorps12)) {
+								specPsRate = new BigDecimal(bCorps12.getPsRate());
+							}
+						}
+
+						if (hpsCorpId > 0) {
+							BCorps bCorps13 = bCorpsService.getById(hpsCorpId);
+							if (ObjectUtils.isNotNull(bCorps13)) {
+								Long ownerCorpId = ObjectUtils.isNotNull(bCorps13.getCorpId()) ? bCorps13.getCorpId() : 0L;
+								if (ownerCorpId > 0 && (ownerCorpId.equals(item.getCorpId()) || ownerCorpId.equals(item.getCarrierId()) || ownerCorpId.equals(hpsCorpId))) {
+									isPS = ObjectUtils.isNotNull(bCorps13.getIsPs()) && bCorps13.getIsPs() == 1;
+								}
+							}
+						}
+
+						String ps_text = ofCNYCount > 0 ? "(应收/应付)存在RMB海运费" : "";
+						String ps_remarks = "";
+						String ps_ps = "";
+						String ps_spec = "";
+
+						usdOFProfit = usdOFProfit.setScale(2, RoundingMode.HALF_UP);
+						ofInAmtProfit = ofInAmtProfit.setScale(2, RoundingMode.HALF_UP);
+						psInAmtProfit = psInAmtProfit.setScale(2, RoundingMode.HALF_UP);
+						psProfit = psProfit.setScale(2, RoundingMode.HALF_UP);
+						HPSProfit = HPSProfit.setScale(2, RoundingMode.HALF_UP);
+						PsRate = PsRate.setScale(2, RoundingMode.HALF_UP);
+						specPsRate = specPsRate.setScale(2, RoundingMode.HALF_UP);
+						specProfit = specProfit.setScale(2, RoundingMode.HALF_UP);
+						specInAmtProfit = specInAmtProfit.setScale(2, RoundingMode.HALF_UP);
+						if (psInAmtProfit.compareTo(BigDecimal.ZERO) != 0) {
+							ps_remarks += " PS不能出现 RMB 费用\r\n";
+						}
+
+						if ("CC".equals(item.getMpaymode()) && psProfit.compareTo(BigDecimal.ZERO) != 0) {
+							ps_remarks += " 主单付费方式为CC 不能出现PS\r\n";
+						}
+
+						if (("PP".equals(item.getMpaymode()) && (MagicValues.DD.equals(item.getBillType()) || MagicValues.MM.equals(item.getBillType())))
+							|| ("PP".equals(item.getMpaymode()) && ObjectUtils.isNotNull(item.getHblno()))) {
+							if (specPScorpIds.indexOf("," + specPSCorpId.toString() + ",") >= 0) {
+								if (usdOFProfit.compareTo(BigDecimal.ZERO) != 0) {
+									BigDecimal tt1 = usdOFProfit.add(ofInAmtProfit).add(HPSProfit).setScale(2, BigDecimal.ROUND_HALF_UP);
+									if (tt1.compareTo(BigDecimal.ZERO) != 0) {
+										BigDecimal pt1 = psProfit.divide(tt1, 2, BigDecimal.ROUND_HALF_UP);
+										if (pt1.compareTo(specPsRate) > 0) {
+											BigDecimal psr1 = new BigDecimal(1).subtract(pt1).setScale(2, BigDecimal.ROUND_HALF_UP);
+											ps_remarks += " PS比例高,公司比例: " + psr1.toString() + " 系统比例为:" + specPsRate.toString() + "\r\n";
+											BigDecimal psr2 = new BigDecimal(1).subtract(specPsRate).setScale(2, BigDecimal.ROUND_HALF_UP);
+											ps_ps += "公司比例:" + psr1.toString() + " (" + psr2.toString() + ")\r\n";
+										}
+									}
+								}
+							} else {
+								if (usdOFProfit.compareTo(BigDecimal.ZERO) != 0) {
+									BigDecimal tt1 = usdOFProfit.add(ofInAmtProfit).add(HPSProfit).setScale(2, BigDecimal.ROUND_HALF_UP);
+									if (tt1.compareTo(BigDecimal.ZERO) != 0) {
+										BigDecimal pt1 = psProfit.divide(tt1, 4, BigDecimal.ROUND_HALF_UP);
+										if (pt1.compareTo(PsRate) > 0) {
+											BigDecimal psr1 = new BigDecimal(1).subtract(pt1).setScale(2, BigDecimal.ROUND_HALF_UP);
+											ps_remarks += " PS比例高,公司比例: " + psr1.toString() + " 系统比例为:" + specPsRate.toString() + "\r\n";
+											BigDecimal psr2 = new BigDecimal(1).subtract(PsRate).setScale(2, BigDecimal.ROUND_HALF_UP);
+											ps_ps += "公司比例:" + psr1.toString() + " (" + psr2.toString() + ")\r\n";
+										}
+									}
+								}
+							}
+						} else {
+							if (psProfit.compareTo(BigDecimal.ZERO) != 0) {
+								ps_remarks += "只有预付、直单和主单,或分单和到付才可以输入PS\r\n";
+							}
+						}
+
+						BigDecimal tt2 = specProfit.add(specInAmtProfit).setScale(2, BigDecimal.ROUND_HALF_UP);
+						if (tt2.compareTo(BigDecimal.ZERO) == 1) {
+							if (isPS == true) {
+								ps_spec += "存在高收退费\r\n";
+							} else {
+								ps_remarks += "不应该存在高收退费\r\n";
+								ps_spec += "不应该存在高收退费\r\n";
+							}
+						}
+
+						ps_remarks = ps_remarks.trim();
+						ps_ps = ps_ps.trim();
+						item.setProfitStatus("");
+						item.setProfitRemarks(ps_remarks.trim());
+						item.setProfitSpec(ps_ps.trim() + "\r\n" + ps_spec.trim());
+						item.setText(ps_text);
+						item.setCorpIsDC(corpIsDC);
+						item.setIfDCCorp(corpIsDC == 1 ? "DC" : "");
+
+						//   FOverFeeLimit:=Trim(GetSysConst('SEA_ISSUEBILL_OVERFEE_LIMIT', '100000'));
+						// 判断是否国内直客
+
+						BigDecimal sumUSDDr = new BigDecimal(BigInteger.ZERO);
+						BigDecimal sumCNYDr = new BigDecimal(BigInteger.ZERO);
+						BigDecimal sumLocDr = new BigDecimal(BigInteger.ZERO);
+
+						BigDecimal sumUSDCr = new BigDecimal(BigInteger.ZERO);
+						BigDecimal sumCNYCr = new BigDecimal(BigInteger.ZERO);
+						BigDecimal sumLocCr = new BigDecimal(BigInteger.ZERO);
+
+						BigDecimal sumOFPS = new BigDecimal(BigInteger.ZERO);
+						if (item.equals(bills)) {
+							// 当前单据,计算 ProfitStatus
+							for (FeeCenter fee : allFeeCenter) {
+								if (MagicValues.C.equals(fee.getDc()) && "P/S".equals(fee.getFeeCode())) {
+									// if("USD".equals(fee.getCurCode())){
+									sumOFPS = sumOFPS.add(fee.getAmountLoc()).setScale(2, BigDecimal.ROUND_HALF_UP);
+								}
+
+								if (MagicValues.D.equals(fee.getDc())) {
+									if ("USD".equals(fee.getCurCode())) {
+										sumUSDDr = sumUSDDr.add(fee.getAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
+									} else {
+										sumCNYDr = sumCNYDr.add(fee.getAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
+									}
+									sumLocDr = sumLocDr.add(fee.getAmountLoc()).setScale(2, BigDecimal.ROUND_HALF_UP);
+								}
+
+								if (MagicValues.C.equals(fee.getDc())) {
+									if ("USD".equals(fee.getCurCode())) {
+										sumUSDCr = sumUSDCr.add(fee.getAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
+									} else {
+										sumCNYCr = sumCNYCr.add(fee.getAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
+									}
+									sumLocCr = sumLocCr.add(fee.getAmountLoc()).setScale(2, BigDecimal.ROUND_HALF_UP);
+								}
+							}
+
+
+							BigDecimal sumProfitUSD = sumUSDDr.subtract(sumUSDCr).setScale(2, BigDecimal.ROUND_HALF_UP);
+							BigDecimal sumProfitCNY = sumCNYDr.subtract(sumCNYCr).setScale(2, BigDecimal.ROUND_HALF_UP);
+							BigDecimal sumProfitLoc = sumLocDr.subtract(sumLocCr).setScale(2, BigDecimal.ROUND_HALF_UP);
+
+							BigDecimal profitRate = new BigDecimal(BigInteger.ZERO);
+							if (sumLocDr.compareTo(BigDecimal.ZERO) == 1) {
+								profitRate = sumProfitLoc.divide(sumLocDr, 4, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);
+							}
+
+							String profitStatus = "";
+							if (!ps_ps.isEmpty()) {
+								profitStatus = "U";
+							}
+							if (sumProfitLoc.compareTo(BigDecimal.ZERO) == 0) {
+								profitStatus = "Z";
+							} else if (sumProfitLoc.compareTo(BigDecimal.ZERO) < 0) {
+								profitStatus = "M";
+							} else if (sumLocDr.compareTo(BigDecimal.ZERO) > 0) {
+								if (profitRate.compareTo(new BigDecimal("0.4")) >= 0) {
+									profitStatus = "H";
+								} else if (profitRate.compareTo(new BigDecimal("0.02")) < 0) {
+									profitStatus = "U".equals(profitStatus) ? "D" : "L";
+								}
+							}
+
+							item.setProfitStatus(profitStatus);
+							//[IF([WFPK_ProfitStatus]='Z', 'Profit was zero!',
+							// IF([WFPK_ProfitStatus]='D', 'Profit was unfair and low !',
+							// IF([WFPK_ProfitStatus]='H', 'Profit was high!',
+							// if([WFPK_ProfitStatus]='L','Profit was low!',''))))]
+							//[IF([WFPK_ProfitStatus]='M', 'Profit was minus!',
+							// IF([WFPK_ProfitStatus]='U', 'P/S was unfair!', ''))]
+							switch (profitStatus) {
+								case "Z":
+									item.setProfitStatusText("利润为零");
+									item.setProfitStatusEnText("Profit was zero!");
+									break;
+								case "D":
+									item.setProfitStatusText("利润不成比例且过低");
+									item.setProfitStatusEnText("Profit was unfair and low!");
+									break;
+								case "H":
+									item.setProfitStatusText("利润过高");
+									item.setProfitStatusEnText("Profit was high!");
+									break;
+								case "L":
+									item.setProfitStatusText("利润过低");
+									item.setProfitStatusEnText("Profit was low!");
+									break;
+								case "F":
+									item.setProfitStatusText("利润正常");
+									item.setProfitStatusEnText("");
+									break;
+								case "M":
+									item.setProfitStatusText("利润为负");
+									item.setProfitStatusEnText("Profit was minus!");
+									break;
+								case "U":
+									item.setProfitStatusText("不成比例");
+									item.setProfitStatusEnText("P/S was unfair!");
+									break;
+								default:
+									item.setProfitStatusText("");
+									item.setProfitStatusEnText("");
+							}
+						}
+//						'F':aAuditItem.RefNo2:='正常';
+//						'M':aAuditItem.RefNo2:='为负';
+//						'H':aAuditItem.RefNo2:='过高';
+//						'L':aAuditItem.RefNo2:='过低';
+//						'U':aAuditItem.RefNo2:='不成比例';
+//						'D':aAuditItem.RefNo2:='不成比例且过低';
+
+						String salesReportOverlimit = sysClient.getParamServiceNew(MagicValues.SALESREPORT_OVERLIMIT);
+						BigDecimal ro;
+						if (ObjectUtils.isNotNull(salesReportOverlimit)) {
+							try {
+								ro = new BigDecimal(salesReportOverlimit);
+							} catch (Exception e) {
+								ro = new BigDecimal(BigInteger.ZERO);
+							}
+						} else
+							ro = new BigDecimal(BigInteger.ZERO);
+						item.setOverFeeLimit(ro.setScale(2, BigDecimal.ROUND_HALF_UP));
+
+						/*
+						if (ObjectUtils.isNotNull(profitMargin)) {
+							BigDecimal margin = new BigDecimal(profitMargin).divide(new BigDecimal(MagicValues.HUNDRED), 2, RoundingMode.HALF_UP);
+							if (margin.compareTo(item.getGrossMargin()) > 0) {
+								item.setProfitMargin("Profit was low and unfair(DC)!");
+								BigDecimal amountD = feeCenterReports.stream().filter(e -> e.getFeeCnName().equals("海运费"))
+									.map(FeeCenterReports::getAmountD).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+								BigDecimal amountC = feeCenterReports.stream().filter(e -> e.getFeeCnName().equals("海运费"))
+									.map(FeeCenterReports::getAmountC).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
+								if (new BigDecimal("0.00").compareTo((amountD.add(amountC))) == 0) {
+									item.setText("(应收/应付)存在RMB海运费");
+								}
+								String status = sysClient.getParamServiceNew("is.profit.margin");
+								if ("1".equals(status)) {
+									BigDecimal amountHYD = item.getFeeCenterList().stream()
+										.filter(e -> e.getFeeCnName().equals("海运费") && "D".equals(e.getDc()))
+										.map(FeeCenterReports::getAmountUsdD).reduce(BigDecimal.ZERO, BigDecimal::add);
+									BigDecimal amountHYC = item.getFeeCenterList().stream()
+										.filter(e -> e.getFeeCnName().equals("海运费") && "C".equals(e.getDc()))
+										.map(FeeCenterReports::getAmountUsdC).reduce(BigDecimal.ZERO, BigDecimal::add);
+									BigDecimal amountPSD = item.getFeeCenterList().stream()
+										.filter(e -> e.getFeeCnName().equals("PS") && "D".equals(e.getDc()))
+										.map(FeeCenterReports::getAmountUsdD).reduce(BigDecimal.ZERO, BigDecimal::add);
+									BigDecimal amountPSC = item.getFeeCenterList().stream()
+										.filter(e -> e.getFeeCnName().equals("PS") && "C".equals(e.getDc()))
+										.map(FeeCenterReports::getAmountUsdC).reduce(BigDecimal.ZERO, BigDecimal::add);
+									BCorps bCorps = bCorpsService.getById(item.getCorpId());
+									BigDecimal PSAmount = amountPSC.subtract(amountPSD);
+									BigDecimal HYAmount = amountHYD.subtract(amountHYC);
+									BigDecimal rate = new BigDecimal("0.00");
+									if (PSAmount.compareTo(new BigDecimal("0.00")) != 0 && HYAmount.compareTo(new BigDecimal("0.00")) != 0) {
+										rate = PSAmount.divide(HYAmount, MathContext.DECIMAL32).setScale(2, RoundingMode.HALF_UP);
+										if (new BigDecimal(bCorps.getPsRate()).compareTo(rate) > 0) {
+											item.setSharingRatio("公司实际分成比例:" + rate + "(" + bCorps.getPsRate() + ")");
+										}
+									}
+								}
+							} else {
+								item.setProfitMargin("");
+							}
+						} else {
+							item.setProfitMargin("");
+						}
+						*/
+						item.setFeeCenterList(feeCenterReports);
+						item.setDept(dept);
+					}
+				}
+				map.put(MagicValues.DATA, list);
+			}
 		} else {
 			// 默认取单据数据,包括主表、预配箱、配箱、费用
 			Bills bills = billsService.getById(billId);
@@ -4662,7 +5560,8 @@ public class ReportsServiceImpl extends ServiceImpl<ReportsMapper, Reports> impl
 							/*List<FeeCenter> feeCenters = feeCenterList.stream()
 								.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
 									Comparator.comparing(f -> f.getFeeId() + f.getCorpId() + f.getCurCode() + f.getReportType()))), ArrayList::new));
-							*/List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
+							*/
+							List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
 							for (FeeCenter fee : feeCenterList) {
 								FeeCenterReports feeCenterReports = new FeeCenterReports();
 								feeCenterReports.setRemarks(fee.getRemarks());
@@ -4827,7 +5726,8 @@ public class ReportsServiceImpl extends ServiceImpl<ReportsMapper, Reports> impl
 								/*List<FeeCenter> feeCenters = feeCenterList.stream()
 									.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
 										Comparator.comparing(f -> f.getFeeId() + f.getCorpId() + f.getCurCode() + f.getReportType()))), ArrayList::new));
-								*/List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
+								*/
+								List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
 								for (FeeCenter fee : feeCenterList) {
 									FeeCenterReports feeCenterReports = new FeeCenterReports();
 									feeCenterReports.setRemarks(fee.getRemarks());
@@ -4988,7 +5888,8 @@ public class ReportsServiceImpl extends ServiceImpl<ReportsMapper, Reports> impl
 							/*List<FeeCenter> feeCenterList1 = feeCenterListMh.stream()
 								.collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
 									Comparator.comparing(f -> f.getFeeId() + f.getCorpId() + f.getCurCode() + f.getReportType()))), ArrayList::new));
-							*/List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
+							*/
+							List<FeeCenterReports> feeCenterReportList = new ArrayList<>();
 							for (FeeCenter fee : feeCenterListMh) {
 								FeeCenterReports feeCenterReports = new FeeCenterReports();
 								feeCenterReports.setRemarks(fee.getRemarks());

+ 126 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/controller/InvoicingController.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.trade.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.trade.entity.Invoicing;
+import org.springblade.los.trade.vo.InvoicingVO;
+import org.springblade.los.trade.service.IInvoicingService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ * 开票申请表 控制器
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/invoicing")
+@Api(value = "开票申请表", tags = "开票申请表接口")
+public class InvoicingController extends BladeController {
+
+	private final IInvoicingService invoicingService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入invoicing")
+	public R<Invoicing> detail(Invoicing invoicing) {
+		Invoicing detail = invoicingService.detail(invoicing);
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页 开票申请表
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入invoicing")
+	public R<IPage<Invoicing>> list(Invoicing invoicing, Query query) {
+		IPage<Invoicing> pages = invoicingService.page(Condition.getPage(query), Condition.getQueryWrapper(invoicing));
+		return R.data(pages);
+	}
+
+	/**
+	 * 自定义分页 开票申请表
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "分页", notes = "传入invoicing")
+	public R<IPage<InvoicingVO>> page(InvoicingVO invoicing, Query query) {
+		IPage<InvoicingVO> pages = invoicingService.selectInvoicingPage(Condition.getPage(query), invoicing);
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 开票申请表
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "新增", notes = "传入invoicing")
+	public R save(@Valid @RequestBody Invoicing invoicing) {
+		return R.status(invoicingService.save(invoicing));
+	}
+
+	/**
+	 * 修改 开票申请表
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "修改", notes = "传入invoicing")
+	public R update(@Valid @RequestBody Invoicing invoicing) {
+		return R.status(invoicingService.updateById(invoicing));
+	}
+
+	/**
+	 * 新增或修改 开票申请表
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入invoicing")
+	public R submit(@Valid @RequestBody Invoicing invoicing) {
+		return invoicingService.submit(invoicing);
+	}
+
+
+	/**
+	 * 删除 开票申请表
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(invoicingService.removeByIds(Func.toLongList(ids)));
+	}
+
+
+}

+ 126 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/controller/InvoicingItemController.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.trade.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.trade.entity.InvoicingItem;
+import org.springblade.los.trade.vo.InvoicingItemVO;
+import org.springblade.los.trade.service.IInvoicingItemService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ * 开票申请明细表 控制器
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/invoicingitem")
+@Api(value = "开票申请明细表", tags = "开票申请明细表接口")
+public class InvoicingItemController extends BladeController {
+
+	private final IInvoicingItemService invoicingItemService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入invoicingItem")
+	public R<InvoicingItem> detail(InvoicingItem invoicingItem) {
+		InvoicingItem detail = invoicingItemService.getOne(Condition.getQueryWrapper(invoicingItem));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页 开票申请明细表
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入invoicingItem")
+	public R<IPage<InvoicingItem>> list(InvoicingItem invoicingItem, Query query) {
+		IPage<InvoicingItem> pages = invoicingItemService.page(Condition.getPage(query), Condition.getQueryWrapper(invoicingItem));
+		return R.data(pages);
+	}
+
+	/**
+	 * 自定义分页 开票申请明细表
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "分页", notes = "传入invoicingItem")
+	public R<IPage<InvoicingItemVO>> page(InvoicingItemVO invoicingItem, Query query) {
+		IPage<InvoicingItemVO> pages = invoicingItemService.selectInvoicingItemPage(Condition.getPage(query), invoicingItem);
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 开票申请明细表
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "新增", notes = "传入invoicingItem")
+	public R save(@Valid @RequestBody InvoicingItem invoicingItem) {
+		return R.status(invoicingItemService.save(invoicingItem));
+	}
+
+	/**
+	 * 修改 开票申请明细表
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "修改", notes = "传入invoicingItem")
+	public R update(@Valid @RequestBody InvoicingItem invoicingItem) {
+		return R.status(invoicingItemService.updateById(invoicingItem));
+	}
+
+	/**
+	 * 新增或修改 开票申请明细表
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入invoicingItem")
+	public R submit(@Valid @RequestBody InvoicingItem invoicingItem) {
+		return R.status(invoicingItemService.saveOrUpdate(invoicingItem));
+	}
+
+	
+	/**
+	 * 删除 开票申请明细表
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(invoicingItemService.removeByIds(Func.toLongList(ids)));
+	}
+
+	
+}

+ 42 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingItemMapper.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.trade.mapper;
+
+import org.springblade.los.trade.entity.InvoicingItem;
+import org.springblade.los.trade.vo.InvoicingItemVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ * 开票申请明细表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+public interface InvoicingItemMapper extends BaseMapper<InvoicingItem> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param invoicingItem
+	 * @return
+	 */
+	List<InvoicingItemVO> selectInvoicingItemPage(IPage page, InvoicingItemVO invoicingItem);
+
+}

+ 33 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingItemMapper.xml

@@ -0,0 +1,33 @@
+<?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.trade.mapper.InvoicingItemMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="invoicingItemResultMap" type="org.springblade.los.trade.entity.InvoicingItem">
+        <id column="id" property="id"/>
+        <result column="pid" property="pid"/>
+        <result column="remarks" property="remarks"/>
+        <result column="version" property="version"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_user_name" property="createUserName"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_user_name" property="updateUserName"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="label_product_name" property="labelProductName"/>
+        <result column="quantity" property="quantity"/>
+        <result column="price" property="price"/>
+        <result column="amount" property="amount"/>
+        <result column="specifications" property="specifications"/>
+        <result column="this_amount" property="thisAmount"/>
+        <result column="invoiced_amount" property="invoicedAmount"/>
+    </resultMap>
+
+
+    <select id="selectInvoicingItemPage" resultMap="invoicingItemResultMap">
+        select * from trade_invoicing_item where is_deleted = 0
+    </select>
+
+</mapper>

+ 42 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingMapper.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.trade.mapper;
+
+import org.springblade.los.trade.entity.Invoicing;
+import org.springblade.los.trade.vo.InvoicingVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ * 开票申请表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+public interface InvoicingMapper extends BaseMapper<Invoicing> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param invoicing
+	 * @return
+	 */
+	List<InvoicingVO> selectInvoicingPage(IPage page, InvoicingVO invoicing);
+
+}

+ 39 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/mapper/InvoicingMapper.xml

@@ -0,0 +1,39 @@
+<?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.trade.mapper.InvoicingMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="invoicingResultMap" type="org.springblade.los.trade.entity.Invoicing">
+        <id column="id" property="id"/>
+        <result column="remarks" property="remarks"/>
+        <result column="version" property="version"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_user_name" property="createUserName"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_user_name" property="updateUserName"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="buy_corporate_name" property="buyCorporateName"/>
+        <result column="taxpayer_identification" property="taxpayerIdentification"/>
+        <result column="address_tel" property="addressTel"/>
+        <result column="opening_bank" property="openingBank"/>
+        <result column="account_number" property="accountNumber"/>
+        <result column="business_organizer_id" property="businessOrganizerId"/>
+        <result column="business_organizer_name" property="businessOrganizerName"/>
+        <result column="invoice_no" property="invoiceNo"/>
+        <result column="contract_number" property="contractNumber"/>
+        <result column="invoice_amount" property="invoiceAmount"/>
+        <result column="corporate_id" property="corporateId"/>
+        <result column="corporate_name" property="corporateName"/>
+        <result column="business_no" property="businessNo"/>
+        <result column="business_date" property="businessDate"/>
+    </resultMap>
+
+
+    <select id="selectInvoicingPage" resultMap="invoicingResultMap">
+        select * from trade_invoicing where is_deleted = 0
+    </select>
+
+</mapper>

+ 41 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/service/IInvoicingItemService.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.trade.service;
+
+import org.springblade.los.trade.entity.InvoicingItem;
+import org.springblade.los.trade.vo.InvoicingItemVO;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * 开票申请明细表 服务类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+public interface IInvoicingItemService extends IService<InvoicingItem> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param invoicingItem
+	 * @return
+	 */
+	IPage<InvoicingItemVO> selectInvoicingItemPage(IPage<InvoicingItemVO> page, InvoicingItemVO invoicingItem);
+
+}

+ 45 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/service/IInvoicingService.java

@@ -0,0 +1,45 @@
+/*
+ *      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.trade.service;
+
+import org.springblade.core.tool.api.R;
+import org.springblade.los.trade.entity.Invoicing;
+import org.springblade.los.trade.vo.InvoicingVO;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * 开票申请表 服务类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+public interface IInvoicingService extends IService<Invoicing> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param invoicing
+	 * @return
+	 */
+	IPage<InvoicingVO> selectInvoicingPage(IPage<InvoicingVO> page, InvoicingVO invoicing);
+
+    Invoicing detail(Invoicing invoicing);
+
+	R submit(Invoicing invoicing);
+}

+ 6 - 6
blade-service/blade-los/src/main/java/org/springblade/los/trade/service/impl/AgentServiceImpl.java

@@ -3681,10 +3681,10 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
 				}
 				BigDecimal remainingAmount = feeCenterList.stream().filter(e -> e.getFeeCode().equals("YFK")).map(FeeCenter::getAmount).filter(Objects::nonNull)
 					.reduce(BigDecimal.ZERO, BigDecimal::add);
-				if (new BigDecimal("0.00").compareTo(remainingAmount) < 0) {
-					agentFeeReport.setRemainingAmount(remainingAmount);
+				if (new BigDecimal("0.00").compareTo(remainingAmount) > 0) {
+					agentFeeReport.setRemainingAmount(remainingAmount.abs());
 					agentFeeReport.setBeforeRepairAmount(new BigDecimal("0.00"));
-				} else if (new BigDecimal("0.00").compareTo(remainingAmount) > 0) {
+				} else if (new BigDecimal("0.00").compareTo(remainingAmount) < 0) {
 					agentFeeReport.setRemainingAmount(new BigDecimal("0.00"));
 					agentFeeReport.setBeforeRepairAmount(remainingAmount.abs());
 				} else {
@@ -4007,10 +4007,10 @@ public class AgentServiceImpl extends ServiceImpl<AgentMapper, Agent> implements
 				BigDecimal remainingAmount = feeCenterList.stream().filter(e -> e.getFeeCode().equals("YFK")).map(FeeCenter::getAmount).filter(Objects::nonNull)
 					.reduce(BigDecimal.ZERO, BigDecimal::add);
 				agentFeeReport.setRemainingAmount(remainingAmount);
-				if (new BigDecimal("0.00").compareTo(remainingAmount) < 0) {
-					agentFeeReport.setRemainingAmount(remainingAmount);
+				if (new BigDecimal("0.00").compareTo(remainingAmount) > 0) {
+					agentFeeReport.setRemainingAmount(remainingAmount.abs());
 					agentFeeReport.setBeforeRepairAmount(new BigDecimal("0.00"));
-				} else if (new BigDecimal("0.00").compareTo(remainingAmount) > 0) {
+				} else if (new BigDecimal("0.00").compareTo(remainingAmount) < 0) {
 					agentFeeReport.setRemainingAmount(new BigDecimal("0.00"));
 					agentFeeReport.setBeforeRepairAmount(remainingAmount.abs());
 				} else {

+ 41 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/service/impl/InvoicingItemServiceImpl.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.trade.service.impl;
+
+import org.springblade.los.trade.entity.InvoicingItem;
+import org.springblade.los.trade.vo.InvoicingItemVO;
+import org.springblade.los.trade.mapper.InvoicingItemMapper;
+import org.springblade.los.trade.service.IInvoicingItemService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * 开票申请明细表 服务实现类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Service
+public class InvoicingItemServiceImpl extends ServiceImpl<InvoicingItemMapper, InvoicingItem> implements IInvoicingItemService {
+
+	@Override
+	public IPage<InvoicingItemVO> selectInvoicingItemPage(IPage<InvoicingItemVO> page, InvoicingItemVO invoicingItem) {
+		return page.setRecords(baseMapper.selectInvoicingItemPage(page, invoicingItem));
+	}
+
+}

+ 129 - 0
blade-service/blade-los/src/main/java/org/springblade/los/trade/service/impl/InvoicingServiceImpl.java

@@ -0,0 +1,129 @@
+/*
+ *      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.trade.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+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.trade.entity.Invoicing;
+import org.springblade.los.trade.entity.InvoicingItem;
+import org.springblade.los.trade.mapper.InvoicingMapper;
+import org.springblade.los.trade.service.IInvoicingItemService;
+import org.springblade.los.trade.service.IInvoicingService;
+import org.springblade.los.trade.vo.InvoicingVO;
+import org.springframework.stereotype.Service;
+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;
+
+/**
+ * 开票申请表 服务实现类
+ *
+ * @author BladeX
+ * @since 2025-04-07
+ */
+@Service
+@AllArgsConstructor
+public class InvoicingServiceImpl extends ServiceImpl<InvoicingMapper, Invoicing> implements IInvoicingService {
+
+	private final IInvoicingItemService invoicingItemService;
+	private final IBusinessBillNoService businessBillNoService;
+	private final IBusinessTypeService bBusinessTypeService;
+
+	@Override
+	public IPage<InvoicingVO> selectInvoicingPage(IPage<InvoicingVO> page, InvoicingVO invoicing) {
+		return page.setRecords(baseMapper.selectInvoicingPage(page, invoicing));
+	}
+
+	@Override
+	public Invoicing detail(Invoicing invoicing) {
+		if (invoicing.getId() == null) {
+			throw new RuntimeException("缺少必要参数");
+		}
+		Invoicing detail = baseMapper.selectById(invoicing.getId());
+		List<InvoicingItem> invoicingItemList = invoicingItemService.list(new LambdaQueryWrapper<InvoicingItem>()
+			.eq(InvoicingItem::getTenantId, AuthUtil.getTenantId())
+			.eq(InvoicingItem::getIsDeleted, 0)
+			.eq(InvoicingItem::getPid, detail));
+		detail.setInvoicingItemList(invoicingItemList.isEmpty() ? new ArrayList<>() : invoicingItemList);
+		return detail;
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public R submit(Invoicing invoicing) {
+		if (invoicing.getId() == null) {
+			BusinessType businessType = bBusinessTypeService.getOne(new LambdaQueryWrapper<BusinessType>()
+				.select(BusinessType::getId)
+				.eq(BusinessType::getTenantId, AuthUtil.getTenantId())
+				.eq(BusinessType::getIsDeleted, 0)
+				.eq(BusinessType::getStatus, 0)
+				.eq(BusinessType::getCode, invoicing.getBusinessTypeCode()));
+			if (businessType == null) {
+				throw new RuntimeException("未找到可用业务类型");
+			}
+			BusinessBillNo businessBillNo = new BusinessBillNo();
+			businessBillNo.setBusinessTypeId(businessType.getId());
+			businessBillNo.setCode(invoicing.getBillNoFormat());
+			R clientBillNo = businessBillNoService.getBillNoLos(businessBillNo);
+			if (!clientBillNo.isSuccess()) {
+				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+				return R.fail(500, "生成订单编号失败");
+			}
+			invoicing.setBusinessNo((String) clientBillNo.getData());
+			invoicing.setCreateTime(new Date());
+			invoicing.setCreateUser(AuthUtil.getUserId());
+			invoicing.setCreateUserName(AuthUtil.getUserName());
+		} else {
+			invoicing.setUpdateUser(AuthUtil.getUserId());
+			invoicing.setUpdateTime(new Date());
+			invoicing.setUpdateUserName(AuthUtil.getUserName());
+		}
+		this.saveOrUpdate(invoicing);
+		if (ObjectUtils.isNotNull(invoicing.getInvoicingItemList()) && !invoicing.getInvoicingItemList().isEmpty()) {
+			for (InvoicingItem item : invoicing.getInvoicingItemList()) {
+				if (item.getId() == null) {
+					item.setPid(invoicing.getId());
+					item.setCreateTime(new Date());
+					item.setCreateUser(AuthUtil.getUserId());
+					item.setCreateUserName(AuthUtil.getUserName());
+				} else {
+					item.setUpdateUser(AuthUtil.getUserId());
+					item.setUpdateTime(new Date());
+					item.setUpdateUserName(AuthUtil.getUserName());
+				}
+			}
+			invoicingItemService.saveOrUpdateBatch(invoicing.getInvoicingItemList());
+			invoicing.setInvoiceAmount(invoicing.getInvoicingItemList().stream().map(InvoicingItem::getAmount)
+				.reduce(BigDecimal.ZERO, BigDecimal::add));
+		}
+		return R.data(invoicing);
+	}
+
+}

+ 1 - 1
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java

@@ -184,7 +184,7 @@ public class UserController {
 		if (ObjectUtil.isNotEmpty(userVO.getDeptPid())) {
 			if ("1504336886057963521".equals(userVO.getDeptPid()) || "1567796746975727617".equals(userVO.getDeptPid())
 				|| "1862313560907030530".equals(userVO.getDeptPid())|| "1863853735860514817".equals(userVO.getDeptPid())
-			|| "1905144938132189185".equals(userVO.getDeptPid())) {
+			|| "1905144938132189185".equals(userVO.getDeptPid())|| "1909147036956012546".equals(userVO.getDeptPid())) {
 				userVO.setRoleAlias("分管调度");
 			} else {
 				userVO.setRoleAlias("大件调度");