From 9a35d408dc134247753839547b59033e92a5d78e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com> Date: Sun, 20 Sep 2026 19:41:19 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=AD=A3=E5=BC=8F=E7=BB=93?= =?UTF-8?q?=E7=AE=97=E5=8D=95=E6=96=B0=E5=A2=9E=E5=85=A8=E7=A5=A8=E6=B1=A0?= =?UTF-8?q?=E5=8F=91=E7=A5=A8=E8=AE=A4=E9=A2=86=E6=9F=A5=E8=AF=A2=E7=AB=AF?= =?UTF-8?q?=E7=82=B9=EF=BC=88=E5=A4=9A=E6=9D=A1=E4=BB=B6+=E5=86=85?= =?UTF-8?q?=E5=AD=98=E7=B2=BE=E7=A1=AE=E5=88=86=E9=A1=B5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FormalSettlementInvoicePoolQueryDTO.java | 74 ++++++++++++ .../vo/FormalSettlementInvoicePoolVO.java | 87 +++++++++++++++ .../FormalSettlementController.java | 9 ++ .../service/IFormalSettlementService.java | 3 + .../impl/FormalSettlementServiceImpl.java | 105 ++++++++++++++++++ 5 files changed, 278 insertions(+) create mode 100644 blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/FormalSettlementInvoicePoolQueryDTO.java create mode 100644 blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/FormalSettlementInvoicePoolVO.java diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/FormalSettlementInvoicePoolQueryDTO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/FormalSettlementInvoicePoolQueryDTO.java new file mode 100644 index 00000000..2fd0a090 --- /dev/null +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/FormalSettlementInvoicePoolQueryDTO.java @@ -0,0 +1,74 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * 1. This software is for development use only under a valid license + * from BladeX. + *

+ * 2. Redistribution of this software's source code to any third party + * without a commercial license is strictly prohibited. + *

+ * 3. Licensees may copyright their own code but cannot use segments + * from this software for such purposes. Copyright of this software + * remains with BladeX. + *

+ * Using this software signifies agreement to this License, and the software + * must not be used for illegal purposes. + *

+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is + * not liable for any claims arising from secondary or illegal development. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +package org.springblade.transport.pojo.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 正式结算单认领查询 全票池发票查询条件 + * + * @author Chill + */ +@Data +public class FormalSettlementInvoicePoolQueryDTO implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + /** + * 页码,默认 1 + */ + private Long current = 1L; + /** + * 每页条数,默认 10,最大 500 + */ + private Long size = 10L; + /** + * 发票号码 + */ + private String invoiceNo; + /** + * 开票日期起 yyyy-MM-dd + */ + private String invoiceDateStart; + /** + * 开票日期止 yyyy-MM-dd + */ + private String invoiceDateEnd; + /** + * 销方税号 + */ + private String salerTaxNo; + /** + * 购方税号 + */ + private String buyerTaxNo; + /** + * 单据使用状态,多个用英文逗号分隔[1未用,30在用,60已用,65已入账] + */ + private String expenseStatus; +} diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/FormalSettlementInvoicePoolVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/FormalSettlementInvoicePoolVO.java new file mode 100644 index 00000000..2b1d3566 --- /dev/null +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/FormalSettlementInvoicePoolVO.java @@ -0,0 +1,87 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * 1. This software is for development use only under a valid license + * from BladeX. + *

+ * 2. Redistribution of this software's source code to any third party + * without a commercial license is strictly prohibited. + *

+ * 3. Licensees may copyright their own code but cannot use segments + * from this software for such purposes. Copyright of this software + * remains with BladeX. + *

+ * Using this software signifies agreement to this License, and the software + * must not be used for illegal purposes. + *

+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is + * not liable for any claims arising from secondary or illegal development. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +package org.springblade.transport.pojo.vo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 正式结算单认领查询 全票池发票VO + * + * @author Chill + */ +@Data +public class FormalSettlementInvoicePoolVO implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + /** + * 发票号码 + */ + private String invoiceNo; + /** + * 发票流水号 + */ + private String serialNo; + /** + * 开票日期 + */ + private String invoiceDate; + /** + * 发票类型名称 + */ + private String invoiceTypeName; + /** + * 税率(百分数,如 13);票池明细缺失时为 null + */ + private BigDecimal taxRate; + /** + * 发票金额(含税,取票池价税合计) + */ + private BigDecimal invoiceAmount; + /** + * 可匹配发票金额(含税,本次口径等于价税合计) + */ + private BigDecimal availableInvoiceAmount; + /** + * 认领金额(默认等于可匹配金额,由前端按结算余额分配) + */ + private BigDecimal matchedAmount; + /** + * 开票单位(销方名称) + */ + private String salerName; + /** + * 受票单位(购方名称) + */ + private String buyerName; + /** + * 附件信息JSON,结构 {"source":"piaozone","path":"A801-2下载path","name":"文件名"} + */ + private String attachmentJson; +} diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java index 49535ce5..9a927fed 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java @@ -27,8 +27,10 @@ import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest; import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest; import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest; import org.springblade.transport.pojo.dto.FormalSettlementInvoiceClaimRequest; +import org.springblade.transport.pojo.dto.FormalSettlementInvoicePoolQueryDTO; import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest; import org.springblade.transport.pojo.entity.FormalSettlementDetailFee; +import org.springblade.transport.pojo.vo.FormalSettlementInvoicePoolVO; import org.springblade.transport.pojo.vo.FormalSettlementVO; import org.springblade.transport.excel.FormalSettlementExcel; import org.springblade.transport.pojo.vo.PreSettlementVO; @@ -250,4 +252,11 @@ public class FormalSettlementController extends BladeController { public R>> receiptClaims(@RequestParam Long formalSettlementId) { return R.data(receiptFlowService.settlementClaims(formalSettlementId)); } + + @GetMapping("/invoice-pool") + @ApiOperationSupport(order = 21) + @Operation(summary = "查询发票云全票池发票(认领查询)") + public R> invoicePool(FormalSettlementInvoicePoolQueryDTO query) { + return R.data(formalSettlementService.invoicePoolQuery(query)); + } } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IFormalSettlementService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IFormalSettlementService.java index cd8557b7..8f77c3a4 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IFormalSettlementService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IFormalSettlementService.java @@ -13,6 +13,7 @@ import org.springblade.core.mp.base.BaseService; import org.springblade.transport.pojo.dto.FormalSettlementSaveRequest; import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest; import org.springblade.transport.pojo.entity.FormalSettlement; +import org.springblade.transport.pojo.vo.FormalSettlementInvoicePoolVO; import org.springblade.transport.pojo.vo.FormalSettlementVO; import org.springblade.transport.pojo.vo.PreSettlementVO; import org.springblade.transport.pojo.entity.PreSettlement; @@ -22,6 +23,7 @@ import java.util.List; import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest; import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest; import org.springblade.transport.pojo.dto.FormalSettlementInvoiceClaimRequest; +import org.springblade.transport.pojo.dto.FormalSettlementInvoicePoolQueryDTO; /** * 正式结算单服务 @@ -47,4 +49,5 @@ public interface IFormalSettlementService extends BaseService String applyPayment(FormalSettlementPaymentRequest request); List applyPayments(FormalSettlementBatchPaymentRequest request); void claimInvoices(FormalSettlementInvoiceClaimRequest request); + IPage invoicePoolQuery(FormalSettlementInvoicePoolQueryDTO query); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java index 9a6cdc4c..e5202aad 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java @@ -11,12 +11,21 @@ package org.springblade.transport.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; +import org.springblade.core.tool.utils.StringUtil; +import org.springblade.thirdparty.bfi.constant.BfiConstant; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDTO; +import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDataDTO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolItemVO; +import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO; +import org.springblade.thirdparty.bfi.service.IBfiService; import org.springblade.transport.mapper.FormalSettlementDetailMapper; import org.springblade.transport.mapper.FormalSettlementDetailFeeMapper; import org.springblade.transport.mapper.FormalSettlementChangeRecordMapper; @@ -44,6 +53,7 @@ import org.springblade.transport.pojo.dto.FormalSettlementSaveRequest; import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest; import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest; import org.springblade.transport.pojo.dto.FormalSettlementInvoiceClaimRequest; +import org.springblade.transport.pojo.dto.FormalSettlementInvoicePoolQueryDTO; import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest; import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest; import org.springblade.transport.pojo.entity.FormalSettlement; @@ -69,6 +79,7 @@ import org.springblade.transport.pojo.entity.ReceivablePayableDetail; import org.springblade.transport.pojo.entity.ReceivablePayableCargoFee; import org.springblade.transport.pojo.entity.SettlementAdjustment; import org.springblade.transport.pojo.entity.Waybill; +import org.springblade.transport.pojo.vo.FormalSettlementInvoicePoolVO; import org.springblade.transport.pojo.vo.FormalSettlementVO; import org.springblade.transport.pojo.vo.PreSettlementVO; import org.springblade.transport.pojo.vo.SettlementAdjustmentVO; @@ -97,6 +108,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -108,6 +120,7 @@ import java.util.stream.Collectors; */ @Service @RequiredArgsConstructor +@Slf4j public class FormalSettlementServiceImpl extends BaseServiceImpl implements IFormalSettlementService { @@ -140,6 +153,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl selectPage(IPage page, FormalSettlementVO query) { @@ -1369,4 +1383,95 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl max) throw new ServiceException("内容不能超过" + max + "个字"); return value; } + + @Override + public IPage invoicePoolQuery(FormalSettlementInvoicePoolQueryDTO query) { + long pageNo = Math.max(query.getCurrent() == null ? 1 : query.getCurrent(), 1); + long pageSize = Math.min(Math.max(query.getSize() == null ? 10 : query.getSize(), 1), 500); + String invoiceNo = query.getInvoiceNo(); + String invoiceDateStart = query.getInvoiceDateStart(); + String invoiceDateEnd = query.getInvoiceDateEnd(); + String salerTaxNo = query.getSalerTaxNo(); + String buyerTaxNo = query.getBuyerTaxNo(); + String expenseStatus = query.getExpenseStatus(); + // A801-1 不返回总数:单次按最大页大小全量翻页拉取后,在内存中做精确分页 + BfiInvoicePoolQueryDataDTO data = new BfiInvoicePoolQueryDataDTO(); + data.setPageSize((int) pageSize); + if (StringUtil.isNotBlank(invoiceNo)) { + data.setInvoiceNo(invoiceNo.trim()); + } + if (StringUtil.isNotBlank(invoiceDateStart)) { + data.setInvoiceDateStart(invoiceDateStart.trim()); + } + if (StringUtil.isNotBlank(invoiceDateEnd)) { + data.setInvoiceDateEnd(invoiceDateEnd.trim()); + } + if (StringUtil.isNotBlank(salerTaxNo)) { + data.setSalerTaxNo(salerTaxNo.trim()); + } + if (StringUtil.isNotBlank(buyerTaxNo)) { + data.setBuyerTaxNo(buyerTaxNo.trim()); + } + if (StringUtil.isNotBlank(expenseStatus)) { + data.setExpenseStatus(expenseStatus.trim()); + } + BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO(); + param.setData(data); + List poolInvoices = bfiService.queryInvoicePool(param); + List invoices = poolInvoices.stream() + .filter(poolInvoice -> !"1".equals(poolInvoice.getDelete())) + .map(this::toInvoicePoolVO) + .toList(); + log.info("正式结算单认领查询 全票池原始 {} 条,过滤作废后 {} 条,返回第 {} 页 {} 条/页", + poolInvoices.size(), invoices.size(), pageNo, pageSize); + // 内存精确分页:total 为过滤后精确总数,请求页超出范围时返回空records + int from = (int) ((pageNo - 1) * pageSize); + int to = (int) Math.min(from + pageSize, invoices.size()); + List records = from >= invoices.size() ? List.of() : invoices.subList(from, to); + Page page = new Page<>(pageNo, pageSize); + page.setRecords(records); + page.setTotal(invoices.size()); + return page; + } + + private FormalSettlementInvoicePoolVO toInvoicePoolVO(BfiInvoicePoolVO poolInvoice) { + FormalSettlementInvoicePoolVO vo = new FormalSettlementInvoicePoolVO(); + vo.setInvoiceNo(poolInvoice.getInvoiceNo()); + vo.setSerialNo(poolInvoice.getSerialNo()); + vo.setInvoiceDate(poolInvoice.getInvoiceDate()); + vo.setInvoiceTypeName(BfiConstant.INVOICE_TYPE_NAMES.getOrDefault(poolInvoice.getInvoiceType(), + poolInvoice.getInvoiceType())); + vo.setTaxRate(resolveTaxRate(poolInvoice)); + BigDecimal totalAmount = parseAmount(poolInvoice.getTotalAmount()); + vo.setInvoiceAmount(totalAmount); + vo.setAvailableInvoiceAmount(totalAmount); + vo.setMatchedAmount(totalAmount); + vo.setSalerName(poolInvoice.getSalerName()); + vo.setBuyerName(poolInvoice.getBuyerName()); + Map attachment = new LinkedHashMap<>(); + attachment.put("source", "piaozone"); + attachment.put("path", poolInvoice.getDownloadUrl()); + attachment.put("name", poolInvoice.getInvoiceNo() + ".pdf"); + vo.setAttachmentJson(JsonUtil.toJson(attachment)); + return vo; + } + + /** + * 税率优先取顶层税率的小数值换算为百分数,如 0.13 -> 13;顶层为空时回退取首条明细税率,均无时返回 null + */ + private BigDecimal resolveTaxRate(BfiInvoicePoolVO poolInvoice) { + if (StringUtil.isNotBlank(poolInvoice.getTaxRate())) { + return new BigDecimal(poolInvoice.getTaxRate()).multiply(BigDecimal.valueOf(100)); + } + return Optional.ofNullable(poolInvoice.getItems()).orElse(List.of()).stream() + .map(BfiInvoicePoolItemVO::getTaxRate) + .filter(StringUtil::isNotBlank) + .findFirst() + .map(taxRate -> new BigDecimal(taxRate).multiply(BigDecimal.valueOf(100))) + .orElse(null); + } + + private BigDecimal parseAmount(String value) { + return StringUtil.isBlank(value) ? BigDecimal.ZERO : new BigDecimal(value); + } }