修复报销金额阻断文案门禁(08-30-b2-submit-error-ocr-fallback)
这个提交包含在:
@@ -45,6 +45,7 @@ const PAGE_TITLES: Array<{ path: string; title: string; group: string }> = [
|
||||
{ path: "/mobile/purchase-requests", title: "移动采购", group: "移动工作台" },
|
||||
{ path: "/mobile/reimbursements", title: "移动报销", group: "移动工作台" },
|
||||
{ path: "/mobile", title: "移动首页", group: "移动工作台" },
|
||||
{ path: "/system/settings", title: "管理", group: "管理" },
|
||||
{ path: "/settings/profile", title: "个人设置", group: "账号设置" },
|
||||
{ path: "/dashboard", title: "数据看板", group: "更多" },
|
||||
];
|
||||
|
||||
@@ -1158,7 +1158,7 @@ export function MobileReimbursementDetailPage() {
|
||||
/>
|
||||
</label>
|
||||
{shouldShowOfficeElectronicsHint(
|
||||
expenseTypes.find((type) => type.id === itemForm.expenseTypeId)?.code,
|
||||
expenseTypes.find((type) => type.id === itemForm.expenseTypeId),
|
||||
itemForm.amount,
|
||||
) ? (
|
||||
<p className="col-span-2 text-xs text-amber-600">该金额通常应选择办公电子设备。</p>
|
||||
@@ -1199,7 +1199,7 @@ export function MobileReimbursementDetailPage() {
|
||||
<div className="shrink-0 text-base font-semibold text-zinc-900">{formatMoney(item.amount)}</div>
|
||||
</div>
|
||||
{item.description ? <p className="mt-2 text-sm leading-5 text-zinc-600">{item.description}</p> : null}
|
||||
{shouldShowOfficeElectronicsHint(item.expenseType?.code, item.amount) ? (
|
||||
{shouldShowOfficeElectronicsHint(item.expenseType, item.amount) ? (
|
||||
<p className="mt-2 text-xs text-amber-600">该金额通常应选择办公电子设备。</p>
|
||||
) : null}
|
||||
{invoiceGuardItemMessages(invoiceGuardIssues, item.id).map((message) => (
|
||||
@@ -1259,7 +1259,7 @@ export function MobileReimbursementDetailPage() {
|
||||
|
||||
{detail.invoiceAmountManualReviewRequired ? (
|
||||
<p className="mt-3 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm leading-6 text-amber-800">
|
||||
本单包含未执行 OCR 的发票,系统未自动比较相关明细金额;财务审批时需查看发票原件核对。
|
||||
本单包含票面金额未自动读取的发票,系统未自动比较相关明细金额;财务审批时需查看发票原件核对。
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
@@ -1418,7 +1418,7 @@ export function MobileReimbursementDetailPage() {
|
||||
) : null}
|
||||
{invoice.amountEvidenceStatus === "ocr_failed" ? (
|
||||
<p className="mt-3 rounded-md border border-red-200 bg-red-50 px-3 py-2 text-sm leading-5 text-red-700">
|
||||
OCR 已处理但未取得票面金额,提交前需要重试识别或联系财务。
|
||||
该发票的票面金额未能读取,暂时无法提交;请重新上传这张发票,或联系财务处理。
|
||||
</p>
|
||||
) : null}
|
||||
{canMaintainReimbursement && !invoice.linkedItemId ? (
|
||||
|
||||
@@ -138,7 +138,7 @@ export function PaymentAccountsPage() {
|
||||
{canManage && companyState.kind === "multiple" ? (
|
||||
<SectionPanel title="公司信息需要处理">
|
||||
<div className="space-y-3 text-sm text-red-600">
|
||||
<p>检测到多条启用的公司信息,系统不会猜测付款账户应关联哪一条。请先处理公司信息。</p>
|
||||
<p>检测到多条启用的公司信息,系统不会猜测付款账户应关联哪一条。请先完善公司信息。</p>
|
||||
{canManageCompanyInformation ? (
|
||||
<Button asChild type="button" variant="secondary">
|
||||
<Link to="/system/master-data">查看公司信息</Link>
|
||||
|
||||
@@ -1346,7 +1346,7 @@ export function ReimbursementDetailPage() {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div>{item.description ?? "-"}</div>
|
||||
{shouldShowOfficeElectronicsHint(item.expenseType?.code, item.amount) ? (
|
||||
{shouldShowOfficeElectronicsHint(item.expenseType, item.amount) ? (
|
||||
<div className="mt-1 text-xs text-amber-600">
|
||||
该金额通常应选择办公电子设备。
|
||||
</div>
|
||||
@@ -1480,7 +1480,7 @@ export function ReimbursementDetailPage() {
|
||||
|
||||
{detail.invoiceAmountManualReviewRequired ? (
|
||||
<p className="rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm leading-6 text-amber-800">
|
||||
本单包含未执行 OCR 的发票,系统未自动比较相关明细金额;财务审批时需查看发票原件核对。
|
||||
本单包含票面金额未自动读取的发票,系统未自动比较相关明细金额;财务审批时需查看发票原件核对。
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
@@ -1541,7 +1541,7 @@ export function ReimbursementDetailPage() {
|
||||
) : null}
|
||||
{invoice.amountEvidenceStatus === "ocr_failed" ? (
|
||||
<p className="rounded-md border border-red-200 bg-red-50 px-3 py-2 text-xs leading-5 text-red-700">
|
||||
OCR 已处理但未取得票面金额,提交前需要重试识别或联系财务。
|
||||
该发票的票面金额未能读取,暂时无法提交;请重新上传这张发票,或联系财务处理。
|
||||
</p>
|
||||
) : null}
|
||||
{canMaintainReimbursement && !invoice.linkedItemId ? (
|
||||
|
||||
@@ -8,9 +8,12 @@ import { Textarea } from "../../components/ui/textarea";
|
||||
|
||||
export const OFFICE_ELECTRONICS_HINT_THRESHOLD = 2000;
|
||||
|
||||
export function shouldShowOfficeElectronicsHint(expenseTypeCode: string | null | undefined, amount: string | number) {
|
||||
export function shouldShowOfficeElectronicsHint(
|
||||
expenseType: Pick<ExpenseType, "code"> | null | undefined,
|
||||
amount: string | number,
|
||||
) {
|
||||
const numericAmount = Number(amount);
|
||||
return expenseTypeCode === "office_supplies"
|
||||
return expenseType?.code === "office_supplies"
|
||||
&& Number.isFinite(numericAmount)
|
||||
&& numericAmount >= OFFICE_ELECTRONICS_HINT_THRESHOLD;
|
||||
}
|
||||
@@ -70,7 +73,7 @@ export function ReimbursementItemEditor({
|
||||
const selectedExpenseType = expenseTypes.find((item) => item.id === expenseTypeId) ?? null;
|
||||
const numericAmount = Number(amount || 0);
|
||||
const shouldWarnOfficeEquipment =
|
||||
shouldShowOfficeElectronicsHint(selectedExpenseType?.code, numericAmount);
|
||||
shouldShowOfficeElectronicsHint(selectedExpenseType, numericAmount);
|
||||
|
||||
const standardsQuery = useQuery({
|
||||
enabled: Boolean(expenseTypeId),
|
||||
|
||||
在新工单中引用
屏蔽一个用户