修复报销票据门禁提示与 OCR 降级(08-30-b2-submit-error-ocr-fallback)
这个提交包含在:
@@ -10,6 +10,35 @@ function readStringList(value: unknown): string[] {
|
||||
.filter((item) => item.length > 0);
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return value != null && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function countGuardAmountUnavailableItems(value: unknown): number {
|
||||
return Array.isArray(value)
|
||||
? value.filter((item) => (
|
||||
isRecord(item)
|
||||
&& typeof item.itemId === "string"
|
||||
&& item.itemId.length > 0
|
||||
&& readStringList(item.invoiceIds).length > 0
|
||||
)).length
|
||||
: 0;
|
||||
}
|
||||
|
||||
function countGuardAmountExceededItems(value: unknown): number {
|
||||
return Array.isArray(value)
|
||||
? value.filter((item) => (
|
||||
isRecord(item)
|
||||
&& typeof item.itemId === "string"
|
||||
&& item.itemId.length > 0
|
||||
&& typeof item.declaredAmount === "string"
|
||||
&& item.declaredAmount.length > 0
|
||||
&& typeof item.invoiceTotal === "string"
|
||||
&& item.invoiceTotal.length > 0
|
||||
)).length
|
||||
: 0;
|
||||
}
|
||||
|
||||
const FEATURE_FLAG_DISABLED_MESSAGES: Record<string, string> = {
|
||||
portal_home_v1_disabled: "工作台首页当前未启用,请联系管理员检查环境开关与功能开关配置。",
|
||||
announcements_v1_disabled: "公告模块当前未启用,请联系管理员检查环境开关与功能开关配置。",
|
||||
@@ -131,6 +160,38 @@ export function mapApiErrorMessage(
|
||||
return "所有报销明细金额都必须大于 0,请修改后再提交。";
|
||||
}
|
||||
|
||||
if (details?.items === "invoice_item_guard_failed") {
|
||||
const messages: string[] = [];
|
||||
const rawUnlinkedCount = details.unlinkedInvoiceCount;
|
||||
const unlinkedCount = typeof rawUnlinkedCount === "number"
|
||||
&& Number.isInteger(rawUnlinkedCount)
|
||||
&& rawUnlinkedCount >= 0
|
||||
? rawUnlinkedCount
|
||||
: 0;
|
||||
const missingCount = readStringList(details.missingInvoiceItemIds).length;
|
||||
const unavailableCount = countGuardAmountUnavailableItems(details.amountUnavailableItems);
|
||||
const exceededCount = countGuardAmountExceededItems(details.amountExceededItems);
|
||||
if (unlinkedCount > 0) messages.push(`${unlinkedCount} 张发票未选择报销明细`);
|
||||
if (missingCount > 0) messages.push(`${missingCount} 条需票明细尚未关联发票`);
|
||||
if (unavailableCount > 0) messages.push(`${unavailableCount} 条明细的发票金额未识别`);
|
||||
if (exceededCount > 0) messages.push(`${exceededCount} 条明细的申报金额高于发票合计`);
|
||||
return messages.length
|
||||
? `票据检查未通过:${messages.join(";")}。请按下方提示处理。`
|
||||
: "票据检查未通过,请核对每条明细与发票的关联和金额后重试。";
|
||||
}
|
||||
|
||||
if (details?.invoice === "invalid_unlinked_item_state") {
|
||||
return "这张发票的关联状态已变化,请刷新后重试。";
|
||||
}
|
||||
|
||||
if (details?.reimbursement === "invalid_status_for_invoice_item_link") {
|
||||
return "当前报销单状态已变化,不能再关联发票,请刷新页面。";
|
||||
}
|
||||
|
||||
if (details?.linkedItemId === "item_not_in_reimbursement") {
|
||||
return "所选明细已不存在或不属于本单,请刷新后重新选择。";
|
||||
}
|
||||
|
||||
const passwordErrors = readStringList(details?.password);
|
||||
if (passwordErrors.length) {
|
||||
return `新密码不符合要求:${passwordErrors.join(";")}。`;
|
||||
|
||||
在新工单中引用
屏蔽一个用户