♻️ syncKingdeeInvoiceResult优化N+1问题,使用批量查询和批量插入/更新
This commit is contained in:
+40
-7
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springblade.transport.service.impl;
|
package org.springblade.transport.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.toolkit.Db;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
@@ -790,6 +791,12 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log.info("金蝶开票结果回写批次查询成功:serialNo=[{}],返回单据数={}", batchSerialNos, result.getData().size());
|
log.info("金蝶开票结果回写批次查询成功:serialNo=[{}],返回单据数={}", batchSerialNos, result.getData().size());
|
||||||
|
// 批量查询当前批次已存在的发票号码(避免 N+1)
|
||||||
|
Set<String> existingInvoiceNos = batchQueryExistingInvoiceNos(batch);
|
||||||
|
log.debug("金蝶开票结果回写:批次已存在发票号码数={}", existingInvoiceNos.size());
|
||||||
|
// 收集待插入的发票记录和待更新的开票申请
|
||||||
|
List<InvoiceApplicationInvoice> toInsertInvoices = new ArrayList<>();
|
||||||
|
List<InvoiceApplication> toUpdateApplications = new ArrayList<>();
|
||||||
for (BfiInvoiceApplyOpenApiBillVO bill : result.getData()) {
|
for (BfiInvoiceApplyOpenApiBillVO bill : result.getData()) {
|
||||||
String billNo = bill.getBillNo();
|
String billNo = bill.getBillNo();
|
||||||
InvoiceApplication application = applicationBySerialNo.get(billNo);
|
InvoiceApplication application = applicationBySerialNo.get(billNo);
|
||||||
@@ -802,11 +809,8 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
if (Func.isBlank(invoiceNo)) {
|
if (Func.isBlank(invoiceNo)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Long exists = invoiceApplicationInvoiceMapper.selectCount(
|
// 使用批量查询结果判断是否已存在
|
||||||
Wrappers.<InvoiceApplicationInvoice>lambdaQuery()
|
if (existingInvoiceNos.contains(invoiceNo)) {
|
||||||
.eq(InvoiceApplicationInvoice::getInvoiceApplicationId, application.getId())
|
|
||||||
.eq(InvoiceApplicationInvoice::getInvoiceNo, invoiceNo));
|
|
||||||
if (exists != null && exists > 0) {
|
|
||||||
log.debug("金蝶开票结果回写:发票号码[{}]已存在,跳过", invoiceNo);
|
log.debug("金蝶开票结果回写:发票号码[{}]已存在,跳过", invoiceNo);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -817,8 +821,10 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
record.setInvoiceDate(parseInvoiceDateTimestamp(invoice.getInvoiceDate()));
|
record.setInvoiceDate(parseInvoiceDateTimestamp(invoice.getInvoiceDate()));
|
||||||
record.setInvoiceAmount(invoice.getIncludeTaxAmount());
|
record.setInvoiceAmount(invoice.getIncludeTaxAmount());
|
||||||
record.setRawJson(JsonUtil.toJson(invoice));
|
record.setRawJson(JsonUtil.toJson(invoice));
|
||||||
invoiceApplicationInvoiceMapper.insert(record);
|
toInsertInvoices.add(record);
|
||||||
inserted++;
|
inserted++;
|
||||||
|
// 标记为已存在,避免同批次重复插入
|
||||||
|
existingInvoiceNos.add(invoiceNo);
|
||||||
log.info("金蝶开票结果回写:写入发票,申请单号=[{}],单据编号=[{}],发票号码=[{}],含税金额=[{}]",
|
log.info("金蝶开票结果回写:写入发票,申请单号=[{}],单据编号=[{}],发票号码=[{}],含税金额=[{}]",
|
||||||
application.getApplicationNo(), billNo, invoiceNo, invoice.getIncludeTaxAmount());
|
application.getApplicationNo(), billNo, invoiceNo, invoice.getIncludeTaxAmount());
|
||||||
}
|
}
|
||||||
@@ -826,11 +832,21 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
invoiceWritten += inserted;
|
invoiceWritten += inserted;
|
||||||
// 查到发票:开票申请单推进开票完成(终态)
|
// 查到发票:开票申请单推进开票完成(终态)
|
||||||
application.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_INVOICED);
|
application.setKingdeeStatus(KingdeeBfiConstant.KINGDEE_STATUS_INVOICED);
|
||||||
updateById(application);
|
toUpdateApplications.add(application);
|
||||||
invoicedCount++;
|
invoicedCount++;
|
||||||
log.info("金蝶开票结果回写:开票申请[{}]状态推进为invoiced,本次写入发票{}张", application.getApplicationNo(), inserted);
|
log.info("金蝶开票结果回写:开票申请[{}]状态推进为invoiced,本次写入发票{}张", application.getApplicationNo(), inserted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 批量插入发票记录
|
||||||
|
if (!toInsertInvoices.isEmpty()) {
|
||||||
|
Db.saveBatch(toInsertInvoices);
|
||||||
|
log.info("金蝶开票结果回写:批量插入发票记录{}条", toInsertInvoices.size());
|
||||||
|
}
|
||||||
|
// 批量更新开票申请状态
|
||||||
|
if (!toUpdateApplications.isEmpty()) {
|
||||||
|
updateBatchById(toUpdateApplications);
|
||||||
|
log.info("金蝶开票结果回写:批量更新开票申请状态{}笔", toUpdateApplications.size());
|
||||||
|
}
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
failed++;
|
failed++;
|
||||||
log.error("金蝶开票结果回写批次异常:serialNo=[{}]", batchSerialNos, exception);
|
log.error("金蝶开票结果回写批次异常:serialNo=[{}]", batchSerialNos, exception);
|
||||||
@@ -843,6 +859,23 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl<InvoiceApplic
|
|||||||
+ "笔),回写发票" + invoiceWritten + "张(开票完成" + invoicedCount + "笔,失败批次" + failed + "个)";
|
+ "笔),回写发票" + invoiceWritten + "张(开票完成" + invoicedCount + "笔,失败批次" + failed + "个)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量查询当前批次已存在的发票号码
|
||||||
|
*
|
||||||
|
* @param serialNos 单据编号列表
|
||||||
|
* @return 已存在的发票号码集合
|
||||||
|
*/
|
||||||
|
private Set<String> batchQueryExistingInvoiceNos(List<String> serialNos) {
|
||||||
|
List<InvoiceApplicationInvoice> existingList = invoiceApplicationInvoiceMapper.selectList(
|
||||||
|
Wrappers.<InvoiceApplicationInvoice>lambdaQuery()
|
||||||
|
.in(InvoiceApplicationInvoice::getSerialNo, serialNos)
|
||||||
|
.select(InvoiceApplicationInvoice::getInvoiceNo));
|
||||||
|
return existingList.stream()
|
||||||
|
.map(InvoiceApplicationInvoice::getInvoiceNo)
|
||||||
|
.filter(Func::isNotBlank)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
/** 从票易通原文 Map 中按候选键顺序取首个非空文本值 */
|
/** 从票易通原文 Map 中按候选键顺序取首个非空文本值 */
|
||||||
private String firstText(Map<?, ?> map, String... keys) {
|
private String firstText(Map<?, ?> map, String... keys) {
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
|
|||||||
Reference in New Issue
Block a user