⚡ A801-1 全票池发票查询改为 pageNo/pageSize 透传分页

- IBfiService.queryInvoicePool 改为单页查询返回 BfiPageVO,BfiServiceImpl 移除 queryAllPages 全量翻页
- 正式结算单认领查询透传 current/size,多取 1 条探测 hasMore 并合成 total,前端 R<IPage> 契约不变
- 移除内存作废过滤(rim 无对应查询条件,透传分页下会产生页内空洞)
- 同步更新 BfiUtil 技术文档 A801-1 说明与使用方清单
This commit is contained in:
刘泉佳
2026-09-20 21:08:42 +08:00
parent f9433cbc78
commit 7ec3b2adbc
5 changed files with 47 additions and 40 deletions
@@ -25,6 +25,7 @@ import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDTO;
import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDataDTO; import org.springblade.thirdparty.bfi.pojo.dto.BfiInvoicePoolQueryDataDTO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolItemVO; import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolItemVO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO; import org.springblade.thirdparty.bfi.pojo.vo.BfiInvoicePoolVO;
import org.springblade.thirdparty.bfi.pojo.vo.BfiPageVO;
import org.springblade.thirdparty.bfi.service.IBfiService; import org.springblade.thirdparty.bfi.service.IBfiService;
import org.springblade.transport.mapper.FormalSettlementDetailMapper; import org.springblade.transport.mapper.FormalSettlementDetailMapper;
import org.springblade.transport.mapper.FormalSettlementDetailFeeMapper; import org.springblade.transport.mapper.FormalSettlementDetailFeeMapper;
@@ -1387,16 +1388,19 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
@Override @Override
public IPage<FormalSettlementInvoicePoolVO> invoicePoolQuery(FormalSettlementInvoicePoolQueryDTO query) { public IPage<FormalSettlementInvoicePoolVO> invoicePoolQuery(FormalSettlementInvoicePoolQueryDTO query) {
long pageNo = Math.max(query.getCurrent() == null ? 1 : query.getCurrent(), 1); 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); // 上限 499:预留 1 条给 hasMore 探测,单次远程请求不超过 rim 契约 pageSize 上限 500
long pageSize = Math.min(Math.max(query.getSize() == null ? 10 : query.getSize(), 1), 499);
String invoiceNo = query.getInvoiceNo(); String invoiceNo = query.getInvoiceNo();
String invoiceDateStart = query.getInvoiceDateStart(); String invoiceDateStart = query.getInvoiceDateStart();
String invoiceDateEnd = query.getInvoiceDateEnd(); String invoiceDateEnd = query.getInvoiceDateEnd();
String salerTaxNo = query.getSalerTaxNo(); String salerTaxNo = query.getSalerTaxNo();
String buyerTaxNo = query.getBuyerTaxNo(); String buyerTaxNo = query.getBuyerTaxNo();
String expenseStatus = query.getExpenseStatus(); String expenseStatus = query.getExpenseStatus();
// A801-1 不返回总数:单次按最大页大小全量翻页拉取后,在内存中做精确分页 // A801-1 rim 契约不支持全量且不返回总数:透传 pageNo/pageSize 单页查询,
// 多取 1 条探测是否还有下一页,total 合成为当前已知的最小精确值供前端分页器翻页
BfiInvoicePoolQueryDataDTO data = new BfiInvoicePoolQueryDataDTO(); BfiInvoicePoolQueryDataDTO data = new BfiInvoicePoolQueryDataDTO();
data.setPageSize((int) pageSize); data.setPageNo((int) pageNo);
data.setPageSize((int) pageSize + 1);
if (StringUtil.isNotBlank(invoiceNo)) { if (StringUtil.isNotBlank(invoiceNo)) {
data.setInvoiceNo(invoiceNo.trim()); data.setInvoiceNo(invoiceNo.trim());
} }
@@ -1417,20 +1421,19 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
} }
BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO(); BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO();
param.setQueryParam(data); param.setQueryParam(data);
List<BfiInvoicePoolVO> poolInvoices = bfiService.queryInvoicePool(param); BfiPageVO<BfiInvoicePoolVO> poolPage = bfiService.queryInvoicePool(param);
List<FormalSettlementInvoicePoolVO> invoices = poolInvoices.stream() List<FormalSettlementInvoicePoolVO> invoices = poolPage.getRows() == null ? List.of()
.filter(poolInvoice -> !"1".equals(poolInvoice.getDelete())) : poolPage.getRows().stream()
.map(this::toInvoicePoolVO) .map(this::toInvoicePoolVO)
.toList(); .toList();
log.info("正式结算单认领查询 全票池原始 {} 条,过滤作废后 {} 条,返回第 {} 页 {} 条/页", // 多取的 1 条仅用于 hasMore 判断,不返回给前端
poolInvoices.size(), invoices.size(), pageNo, pageSize); boolean hasMore = invoices.size() > pageSize;
// 内存精确分页:total 为过滤后精确总数,请求页超出范围时返回空records List<FormalSettlementInvoicePoolVO> records = hasMore ? invoices.subList(0, (int) pageSize) : invoices;
int from = (int) ((pageNo - 1) * pageSize); long total = hasMore ? pageNo * pageSize + 1 : (pageNo - 1) * pageSize + records.size();
int to = (int) Math.min(from + pageSize, invoices.size()); log.info("正式结算单认领查询 全票池第 {} 页 {} 条/页,返回 {} 条,hasMore:{}", pageNo, pageSize, records.size(), hasMore);
List<FormalSettlementInvoicePoolVO> records = from >= invoices.size() ? List.of() : invoices.subList(from, to);
Page<FormalSettlementInvoicePoolVO> page = new Page<>(pageNo, pageSize); Page<FormalSettlementInvoicePoolVO> page = new Page<>(pageNo, pageSize);
page.setRecords(records); page.setRecords(records);
page.setTotal(invoices.size()); page.setTotal(total);
return page; return page;
} }
@@ -278,12 +278,12 @@ public interface IBfiService {
BfiBillSaveResultVO pushClaimResult(BfiClaimPushDTO param); BfiBillSaveResultVO pushClaimResult(BfiClaimPushDTO param);
/** /**
* A801-1 查询全票池发票数据(自动翻页汇总全量) * A801-1 查询全票池发票数据(单页查询)
* *
* @param param 查询参数,messageType/messageId 由服务端填充;data.pageSize 必填,作为单页大小与翻页终止依据 * @param param 查询参数,messageType/messageId 由服务端填充;queryParam.pageNo/pageSize 必填
* @return 票池发票数据全量列表 * @return 当前页票池发票数据,rim 契约不返回总数与末页标识
*/ */
List<BfiInvoicePoolVO> queryInvoicePool(BfiInvoicePoolQueryDTO param); BfiPageVO<BfiInvoicePoolVO> queryInvoicePool(BfiInvoicePoolQueryDTO param);
/** /**
* A801-2 进项发票下载(文件下载) * A801-2 进项发票下载(文件下载)
@@ -484,30 +484,28 @@ public class BfiServiceImpl implements IBfiService {
} }
@Override @Override
public List<BfiInvoicePoolVO> queryInvoicePool(BfiInvoicePoolQueryDTO param) { public BfiPageVO<BfiInvoicePoolVO> queryInvoicePool(BfiInvoicePoolQueryDTO param) {
if (param == null || param.getQueryParam() == null) { if (param == null || param.getQueryParam() == null) {
throw new BfiException("查询BFI全票池发票失败,查询参数不能为空"); throw new BfiException("查询BFI全票池发票失败,查询参数不能为空");
} }
param.setMessageType(BfiConstant.MESSAGE_TYPE_INVOICE_QUERY);
// A801-1 rim 契约仅返回当前页数据且无总数,统一通过通用翻页工具取全量,由调用方自行分页
BfiInvoicePoolQueryDataDTO data = param.getQueryParam(); BfiInvoicePoolQueryDataDTO data = param.getQueryParam();
if (data.getPageNo() == null || data.getPageSize() == null) {
throw new BfiException("查询BFI全票池发票失败,pageNo与pageSize不能为空");
}
param.setMessageType(BfiConstant.MESSAGE_TYPE_INVOICE_QUERY);
// rim 契约要求每次请求携带唯一 messageId
param.setMessageId(UUID.randomUUID().toString());
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
log.info("调用BFI接口 全票池发票查询开始 pageSize:{}", data.getPageSize()); log.info("调用BFI接口 全票池发票查询开始 pageNo:{},pageSize:{}", data.getPageNo(), data.getPageSize());
List<BfiInvoicePoolVO> invoices = BfiUtil.queryAllPages(pageNo -> { BfiResultVO<List<BfiInvoicePoolVO>> result = commonRimCall("全票池发票查询",
// 翻页工具逐页注入页码;rim 契约要求每次请求携带唯一 messageId () -> client.invoicePoolQuery(getAccessToken(), param));
data.setPageNo(pageNo); List<BfiInvoicePoolVO> rows = result.getData() != null ? result.getData() : List.of();
param.setMessageId(UUID.randomUUID().toString()); BfiPageVO<BfiInvoicePoolVO> page = new BfiPageVO<>();
BfiResultVO<List<BfiInvoicePoolVO>> result = commonRimCall("全票池发票查询", page.setPageNo(data.getPageNo());
() -> client.invoicePoolQuery(getAccessToken(), param)); page.setPageSize(data.getPageSize());
List<BfiInvoicePoolVO> rows = result.getData() != null ? result.getData() : List.of(); page.setRows(rows);
// rim 契约无 lastPage,包装为 BfiPageVO 借助"数据不满一页即末页"规则终止翻页 log.info("调用BFI接口 全票池发票查询结束 耗时:{}ms,本页 {} 条", System.currentTimeMillis() - start, rows.size());
BfiPageVO<BfiInvoicePoolVO> page = new BfiPageVO<>(); return page;
page.setRows(rows);
page.setPageSize(data.getPageSize());
return page;
});
log.info("调用BFI接口 全票池发票查询结束 耗时:{}ms,全量 {} 条", System.currentTimeMillis() - start, invoices.size());
return invoices;
} }
@Override @Override
@@ -520,6 +520,9 @@ class BfiServiceImplTest {
@Test @Test
void queryInvoicePoolShouldValidateQueryParam() { void queryInvoicePoolShouldValidateQueryParam() {
assertThrows(BfiException.class, () -> service.queryInvoicePool(new BfiInvoicePoolQueryDTO())); assertThrows(BfiException.class, () -> service.queryInvoicePool(new BfiInvoicePoolQueryDTO()));
BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO();
param.setQueryParam(new BfiInvoicePoolQueryDataDTO());
assertThrows(BfiException.class, () -> service.queryInvoicePool(param));
verifyNoInteractions(client); verifyNoInteractions(client);
} }
@@ -531,11 +534,14 @@ class BfiServiceImplTest {
.thenReturn(success(List.of(invoice))); .thenReturn(success(List.of(invoice)));
BfiInvoicePoolQueryDataDTO data = new BfiInvoicePoolQueryDataDTO(); BfiInvoicePoolQueryDataDTO data = new BfiInvoicePoolQueryDataDTO();
data.setInvoiceNo("25532000000044538098"); data.setInvoiceNo("25532000000044538098");
data.setPageNo(1);
data.setPageSize(500); data.setPageSize(500);
BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO(); BfiInvoicePoolQueryDTO param = new BfiInvoicePoolQueryDTO();
param.setQueryParam(data); param.setQueryParam(data);
List<BfiInvoicePoolVO> rows = service.queryInvoicePool(param); BfiPageVO<BfiInvoicePoolVO> page = service.queryInvoicePool(param);
assertEquals(1, rows.size()); assertEquals(1, page.getRows().size());
assertEquals(1, page.getPageNo());
assertEquals(500, page.getPageSize());
} }
@Test @Test
@@ -31,7 +31,7 @@
| A301-1 | 收款单查询 | `queryRecBill` | `BfiPageVO<BfiRecBillVO>` | | A301-1 | 收款单查询 | `queryRecBill` | `BfiPageVO<BfiRecBillVO>` |
| A301-2 | 收款认领公告查询 | `queryClaimAnnounce` | `BfiPageVO<BfiClaimAnnounceVO>` | | A301-2 | 收款认领公告查询 | `queryClaimAnnounce` | `BfiPageVO<BfiClaimAnnounceVO>` |
不适用:`queryInvoicePool`(A801-1,直接返回 List)、`queryExchangeRate`(A801-4,单页调用由 `BfiServiceImpl` 内部处理)。 不适用:`queryInvoicePool`(A801-1,rim 契约限制不能全量查询,已改为 pageNo/pageSize 单页透传,由 `BfiServiceImpl` 直接单次调用)、`queryExchangeRate`(A801-4,单页调用由 `BfiServiceImpl` 内部处理)。
## 3. API 定义 ## 3. API 定义
@@ -98,4 +98,4 @@ lambda 内通过闭包复用同一参数对象,仅需覆盖 `pageNo`;请求
| 内容 | 位置 | | 内容 | 位置 |
| --- | --- | | --- | --- |
| 工具类 | `blade-third-party-api/blade-bfi-api/src/main/java/org/springblade/thirdparty/bfi/util/BfiUtil.java` | | 工具类 | `blade-third-party-api/blade-bfi-api/src/main/java/org/springblade/thirdparty/bfi/util/BfiUtil.java` |
| 当前唯一使用方 | `blade-service/blade-transport/.../service/impl/PaymentApplicationServiceImpl.java`(queryPayApplyPages / queryPayBillPages) | | 使用方 | `blade-service/blade-transport/.../service/impl/PaymentApplicationServiceImpl.java`(付款结果回写)、`KingdeeApBillSyncSupport.java`(应付单同步)、`CustomerArchiveServiceImpl.java`(客户档案同步) |