支持财务经办与公司代表关联方还款确认(09-17-company-loan-principal-repayment)
公司只有财务和出借收款经理两名办理人,新增限定公司、出借人和借款范围的关联方确认模式。 仅豁免指定公司代表的收款人关联;经办、自审、证据、交易归属、资金占用及 Q6 限制保留。 贯通付款、人工回单、银行对账、补证恢复、晚到补记与追回;电脑和手机显示实际确认身份。 授权版本、付款与对账停用事件及历史决定只增不改,新增迁移 20261009010000_loan_related_approval。 本地合成验证:82 迁移、HTTP 109 组、浏览器 33 组、数据库约束 9 组通过;13 个有效资金守卫变异均捕获。 已有服务端全量 4519 项通过、1 项原有跳过,后续定向 77 项通过;提示收尾另有 908 项合同测试及前端构建通过。 按用户授权提交后对干净候选运行正式 verify-candidate,不沿用旧候选回执。 限制:独立代码复核待完成(inline 模式);真实回单待验。本次仅本地提交,不推送、不部署。 生成关联决定后不能直接降回不理解该模式的旧代码;真实授权、录入、生产核实和付款仍须明确批准。
这个提交包含在:
@@ -28,7 +28,7 @@ function PageFacts({ page }: { page?: ReceiptVerificationPage }) {
|
||||
|
||||
type Props = {
|
||||
actorId: string; batchId: string; attachmentId: string; makerId: string | null;
|
||||
canManage: boolean; canReview: boolean;
|
||||
canManage: boolean; canReview: boolean; relatedParty?: boolean;
|
||||
items: { id: string; label: string }[];
|
||||
onClose: () => void; onChanged: () => void;
|
||||
};
|
||||
@@ -122,7 +122,7 @@ export function PaymentReceiptVerificationDialog(props: Props) {
|
||||
if (editing[pageNumber]) setChanges((current) => ({ ...current, [pageNumber]: {} }));
|
||||
}}>{editing[pageNumber] ? "取消本页更正" : "更正识别"}</Button>
|
||||
{editing[pageNumber] ? <div className="space-y-3">
|
||||
<p className="text-xs text-zinc-500">只填写要更正的字段,其他字段保留原识别值。更正后需要独立复核。</p>
|
||||
<p className="text-xs text-zinc-500">只填写要更正的字段,其他字段保留原识别值。更正后需要{props.relatedParty ? "公司代表确认" : "独立复核"}。</p>
|
||||
{FIELD_NAMES.map((name) => <label key={name} className="block space-y-1 text-sm">
|
||||
<span>第{pageNumber}页更正{name}</span>
|
||||
{name === "单据状态" ? <select className="min-h-11 w-full rounded-md border bg-white px-3"
|
||||
@@ -141,7 +141,7 @@ export function PaymentReceiptVerificationDialog(props: Props) {
|
||||
})}
|
||||
{detail?.proposal ? <p className="whitespace-pre-wrap break-words text-sm">核验说明:{detail.proposal.reason}</p> : null}
|
||||
{detail?.proposal?.status === "pending_review" && !reviewable ?
|
||||
<p role="status" className="text-sm text-zinc-600">等待有资格的独立审批人复核;经办人和报销参与人不能自审。</p> : null}
|
||||
<p role="status" className="text-sm text-zinc-600">{props.relatedParty ? "等待有当前授权的公司代表确认;上传人、录入人和制单人不能自审。" : "等待有资格的独立审批人复核;经办人和报销参与人不能自审。"}</p> : null}
|
||||
{editable || reviewable ? <label className="block space-y-1 text-sm">
|
||||
<span>{reviewable ? "复核说明" : "更正说明(仅关联可留空)"}</span>
|
||||
<Textarea value={reason} maxLength={500} disabled={busy} onChange={(event) => setReason(event.target.value)} />
|
||||
@@ -152,7 +152,7 @@ export function PaymentReceiptVerificationDialog(props: Props) {
|
||||
onClick={() => save.mutate()}>{save.isPending ? "保存中…" : "保存核验"}</Button> : null}
|
||||
{reviewable ? <>
|
||||
<Button variant="secondary" disabled={busy || query.isFetching || !reason.trim()} onClick={() => review.mutate("reject")}>不通过</Button>
|
||||
<Button disabled={busy || query.isFetching || !reason.trim()} onClick={() => review.mutate("approve")}>确认复核</Button>
|
||||
<Button disabled={busy || query.isFetching || !reason.trim()} onClick={() => review.mutate("approve")}>{props.relatedParty ? "公司代表确认" : "确认复核"}</Button>
|
||||
</> : null}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
在新工单中引用
屏蔽一个用户