R111/A3-A6 强化发票查重和状态治理

这个提交包含在:
2026-05-08 10:05:27 +08:00
父节点 77fbfb5eb8
当前提交 0ab0740d1a
共修改 8 个文件,包含 888 行新增和 53 行删除
+12 -31
查看文件
@@ -1,6 +1,7 @@
const cron = require("node-cron");
const { buildMissingRequiredOcrError, runOcrForInvoice } = require("../services/ocr");
const { resolveInvoiceDedupBlocker } = require("../services/invoiceGovernance");
const { readFileBuffer } = require("../services/storage");
const OCR_DUPLICATE_ERROR = "duplicate_invoice_code_number";
@@ -69,35 +70,10 @@ async function claimPendingInvoices(prisma, config, workerId) {
ocr_lock_owner = ${workerId}
FROM candidates
WHERE i.id = candidates.id
RETURNING i.id, i.file_sha256, i.ocr_provider, i.ocr_type, i.storage_path, i.mime_type, i.ocr_attempts
RETURNING i.id, i.owner_employee_id, i.file_sha256, i.ocr_provider, i.ocr_type, i.storage_path, i.mime_type, i.ocr_attempts
`;
}
async function findDuplicateInvoice(prisma, invoiceId, invoiceCode, invoiceNumber) {
if (!invoiceCode || !invoiceNumber) {
return null;
}
return prisma.invoicePool.findFirst({
where: {
id: { not: invoiceId },
invoice_code: invoiceCode,
invoice_number: invoiceNumber,
is_duplicate_override: false,
OR: [
{ status: "bound" },
{
status: "archived",
archived_reason: "used_complete",
},
],
},
select: {
id: true,
},
});
}
async function getOrCreateOcrResult(prisma, config, claimedInvoice, imageBase64) {
const ocrProvider = getEffectiveOcrProvider(config);
const where = {
@@ -303,11 +279,15 @@ async function processClaimedInvoice(prisma, config, claimedInvoice, workerId, l
return { outcome: "failed" };
}
const duplicate = await findDuplicateInvoice(
const duplicate = await resolveInvoiceDedupBlocker(
prisma,
claimedInvoice.id,
normalized.invoiceCode,
normalized.invoiceNumber,
{
excludeInvoiceId: claimedInvoice.id,
fileSha256: claimedInvoice.file_sha256,
invoiceCode: normalized.invoiceCode,
invoiceNumber: normalized.invoiceNumber,
ownerEmployeeId: claimedInvoice.owner_employee_id,
},
);
if (duplicate) {
@@ -315,7 +295,8 @@ async function processClaimedInvoice(prisma, config, claimedInvoice, workerId, l
logger.warn(
{
invoiceId: claimedInvoice.id,
duplicateInvoiceId: duplicate.id,
duplicateInvoiceId: duplicate.conflict.id,
duplicateReason: duplicate.reason,
mimeType: claimedInvoice.mime_type,
transportMode: normalized?.transportMode ?? normalized?.raw?.transportMode ?? null,
},