文件
wangsli和Claude Opus 5.5 c251729267
ci-e2e / e2e (push) Waiting to run
ci-minimal / check-minimal (push) Waiting to run
借款材料区按需显示并前置缺项提示(09-17-company-loan-principal-repayment)
- 材料区只为仍缺的材料提供上传:原件已存显示可查看,在线确认后收起协议框,历史还款依据仅在登记期初小于原本金时出现
- 余额材料改中性文案(公司银行流水或代账明细账),确认字段改为“余额依据说明”,按钮改为“确认借款余额”并前置列出缺项
- 确认弹窗跟随最新列表状态:刷新中、刷新失败、版本变化、已确认或缺项时禁用按钮与提交
- 浏览器测试覆盖显隐、缺项、材料失效、在线确认失效、刷新与弹窗打开后状态变化;同步操作手册
- 只读复核 P2 已修复关闭;不改后端、接口与数据库

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:58:10 +08:00

99 KiB

2026-10-11 G:材料区域最小精简设计(已批准并实施)

沿用 CompanyLoansPage.tsx 的现有材料区域、表单和 tab 切换,保持现有组件样式。本轮只调整信息显示,不迁移到新详情页、不复制 LoanLenderAcknowledgements 的发起流程,也不新建材料管理面板。

  • 材料是否满足只从当前借款 DTO 推导:未归档、审核可用的 incoming 和 accounting_confirmation;有效 lenderAcknowledgement 或审核可用的 agreement;当登记期初未还小于原本金时还需审核可用的 adjustment。金额按现有精确金额处理约定比较,不拿后续 outstanding 代替期初值。
  • 上传控件按 PRD G 的条件显示,既有材料链接保留;协议入口注明二选一。余额材料始终提供原 accounting_confirmation 上传入口,前台“余额依据说明”继续提交 accountingConfirmationRef,不更名数据库或 API。
  • 原 setTab("acknowledgements") / setTab("authorizations") 用于跳转;无有效声明且已关联员工时提示到原栏目查看/办理,未关联员工保留原纸质路径。现有借款 DTO 不足以判断 pending/returned 或授权是否完成,本轮不补聚合查询、不抓取全量分页,以中性导航文案表达。
  • 缺项投影与按钮禁用共用同一判断;上传提交、等待列表刷新及刷新失败期间不使用旧快照启用确认。返回页面或确认栏目后按现有查询约定更新数据;服务端继续负责防止并发版本变化、声明失效和资料缺失的提交。
  • 确认完成后的授权链接仅用于适用既有关联方授权条件的借款;外部出借人继续原独立审批路径。保持借款声明、余额确认、公司代表授权三种不同业务动作,不自动推进任何状态。

界面仅提示财务如何准备银行流水/代账明细和填写出处,不宣称上传即完成余额核对。实施时同步现有操作手册对应段落,注明银行流水作为附件核对,不是新增银行流水导入能力。

2026-10-10 D:浏览器遗留失败排查设计(已批准实施、产品复核及本地补验完成,未提交)

沿当前借款任务 AC46–AC51,先补最小可观察实验,再定位并修复;不预判两项都是测试脚本问题。没有迁移、生产连接或新的业务规则。

最终产品行为:授权出借人列表使用可选 eligible=related_authority,在服务端分页和计数前排除未核实、未关联员工及财务本人;未传参数的原列表保持原行为,无效取值拒绝。授权弹窗每次打开重置出借人页码为 1。追回上传仍先关闭弹窗、再刷新;等待刷新后才关闭的试验已撤回,刷新期间禁用选项列为 P3,未实现。下面保留获批的实验合同,实际完成与证据以 implement 顶部为准。

提交前复核发现第三页诊断原先只验证选项,没有直接在第三页完成授权;追回旧策略诊断原先只记录选项,没有实际提交;资金回滚原例仅测晚到成功。按原 AC46/AC49/AC50 补实际第三页经办/本人确认、原生验证零 POST、精确 POST 的拒绝/pending/200 后刷新门闩,以及独立和关联两模式的追回金额、交易重复、审计失败回滚。补验不修改产品代码。

D0:采证与定向运行

  • 复用 test-company-loan-db.cjs 的隔离数据库、真实 Fastify/鉴权、合成 PDF 和真实浏览器。增加仅测试使用的可选 RUN_ISOLATED_LOAN_BROWSER_DIAGNOSTIC=authorization-pagination|refund 定向入口,严格校验值并要求已有 DB/browser 开关;输出明确标为定向范围,不能冒称完整回归。现有员工专项入口保留。
  • 白名单事件时间线:设备、阶段、相对时间、角色别名、接口路径与必要页码/类别、请求开始/结束/取消、HTTP 状态、requestId、安全 reasonCode、按钮 pending/disabled、已显示页的合成 ID 和证据 ID。禁止 token/cookie、原始请求响应 payload、账号、真实原件及完整本地路径。表单采证仅记录有效性和字段是否存在,不保存账号值。
  • 监听在动作之前安装,退出/失败时统一收拢 Promise、移除监听并清理测试自有资源。截图和限定环节的浏览器 trace 只用合成页面;保留失败证据,控制产物大小。原 r6/r7、full-loan-r1 证据不覆盖不删除。
  • 同步区分浏览器原生验证无 POST、网络 pending/失败、服务端拒绝、提交成功但界面刷新失败;200 不能单独证明流程完成,DOM 关闭也不能单独证明写入成功。

D1:授权翻页实验

受影响入口:company-loan-employee-fixture.cjs / company-loan-employee-browser.cjs,必要时 LoanRelatedAuthorizations.tsx 及 /loan-lenders 查询;保留每页 30 条、姓名/ID 排序与现有授权过滤。

  1. 隔离 fixture 固定建立至少 65 名活跃、身份核实、员工关联且非财务本人的出借人,用稳定的合成姓名排序;通过实际列表 API 校验第二/第三页目标位置。位置不满足即 fixture 失败,不能跳过翻页或依赖其他测试多建的资料。
  2. 电脑/手机执行第一页→第二页→第三页→第二页→第三页,明确断言各页真实选项和目标 ID;选择目标借款、登记授权、本人确认,验证授权关联与审计、零还款创建。旧 open() 没有重置 lenderPage 的行为仅作为待观察条件,不预先增加“每次回第一页”的产品要求。
  3. 使用可控路由门闩而非任意 sleep:首次响应正常/快速、第二页响应延迟、无关同路径的其他页响应先到、5 秒有效期内返回缓存页、关闭重开。缓存场景以选项正确到达为结果,不强制等待不存在的新 GET;需要等待响应时精确识别目标 page/pageSize 与 actor,并继续检查渲染。
  4. 控制实验让页码不变化或返回错误页,证明测试确实抓到停在旧页。还原旧等待方式时从保留版本/差异取证,若不能逐字还原则注明限制;人为注入的等待失败不是原事故根因证据。仅在同条件能复现历史失败并通过单一修复消除后,才归因。

D2:追回到账实验

受影响入口:company-loan-reconciliation-browser.cjs、company-loan-related-browser.cjs、相应 HTTP fixture;必要时 LoanBankReconciliation.tsx、paymentBatches.js / loanBankResults.js。复用既有退款证据类别 incoming_return、相反账户方向、booked 的晚到成功父事件、金额/归属/声明/审计和银行交易唯一保护。

  1. 为每台设备和审批模式各建独立场景,不用一次场景的成功代替另一模式。保留原始独立模式失败链,当前关联模式由不同身份的财务/公司代表分别办理。
  2. 先产生已登记晚到成功和 40 元待追回,再分别上传合成退款证据、追回 15 和 25 元。上传响应绑定本批次 POST;保存返回的 evidenceId,等待该 ID 出现在实际 options,断言选中后才提交;用旧“最后一个 option”策略与延迟刷新作对照,不假定这一竞争就是旧事故原因。
  3. 对每次登记精确观察 /payment-batches/:id/loan-bank-results POST;检查 returned event 的 parent/evidence/金额,再由另一人复核和财务入账。200 后分别等待对应列表刷新与状态显示,读取数据库确认待追回金额、交易占用、冻结原因与原借款/原终态/批次数;不把等待弹窗消失作为 HTTP 请求的替代品。
  4. 小矩阵覆盖:提交时无有效证据、上传完成但列表读取延迟、登记 POST 延迟、200 后刷新延迟、有效可见的拒绝信息,以及实际事务内审计失败回滚。既有 HTTP 反例优先复用;补本次遗漏而非复制整套资金守卫。
  5. 重试按既有请求键/银行交易身份合同检验:相同键同内容幂等,新的声明可按既有取代规则保留历史,但同一交易不能重复入账;部分追回不解除其他原因冻结,不能改成直接消除本金或生成退款付款批次。

修复、验证与兼容边界

采证先定位层次;纯等待/fixture 问题只改测试。已证实的界面或接口缺陷才做对应最小改动,不扩展通用组件、不统一放大超时、不加盲目重试。触及权限、状态消费、资金保护时补只读独立 review;若需要改既定合同或新增迁移,返回方案确认。

最终分别重验强制触发的两项场景(每设备连续 3 轮),再一次完整借款回归及受影响层检查;未改业务代码时无需为测试变化重复前端构建。提交/发布另行授权,测试修复不自动部署。原事故无法复现时可交付采证与稳定分支覆盖,但结论仍为原根因未定,不凭多轮绿灯结案。

2026-10-10 N5-C 出借人在线确认设计

  1. 新增专用声明、借款快照及单次决定三张表,记录固定的公司/出借人/关联员工、财务发起人、请求键、日期、金额、原件 ID/摘要和版本。声明与范围在一个事务内完整成立,数据库约束保障范围一致及历史不可改删;失效只允许从有效到无效,保留原决定。
  2. 快照读取数据库当前值,客户端仅提交借款 ID/版本及出借人身份版本。限定同公司同出借人、身份已核实、有入账原件;首次发起限定尚未确认期初余额,已确认余额仅在有失效在线声明历史时开放重发。重发不修改借款版本、金额、截止日、原余额确认人/时间、状态或代账引用。同一有效范围的待确认/已确认记录不重复发起,返回已存在提示;退回或失效后允许新请求。多笔声明是一组,任一关键源变化使该组失效。
  3. 发起/决定按“出借人 → 排序后的借款 → 声明 → 人员”取锁,重读来源;决定必须为冻结的关联员工本人且不是发起人。新请求及决定均有幂等和审计原子性。数据库在借款条款、入账原件或出借人关联/版本变化时自动失效该组,不以普通 loan.version 增量推定失效,避免确认余额和补代账材料误伤声明。
  4. 新 API 提供财务全量及本人范围内的声明列表、详情、发起、确认/退回;详情只返回冻结明细及原件元数据。原件沿既有下载校验、用途及审计,新增声明范围绑定,不能借此读取整个台账、代账文件、他人原件或当前关联身份已变化的原件。声明请求和原件引用均不写入浏览器长期存储。
  5. 公司借款页增加“出借人确认”,与“公司代表授权”明确分开。普通员工只读/办理自己的声明,不需要经理身份;根据发布前入口调整,普通员工通过站内通知进入,常驻电脑导航/后备导航/手机“我的”仅供财务和公司代表使用。本人的路由及接口权限保持。沿现有组件/样式实现;查询按账号隔离,新写动作及下载支持取消,账号变化中止旧请求,保留同身份令牌恢复。 发起声明事务复用 createNotifications,仅为冻结的关联员工创建一条 loan.lender_acknowledgement_requested 通知,目标类型为 loan_lender_acknowledgement、目标 ID 为声明 ID;通知文本不复制姓名、金额、账号或原件内容。不调用 IM/outbox/企业微信派发,也不加入外部消息支持类型。通知与声明/审计同事务提交,幂等返回不再次通知。电脑和手机通知链接分别指向公司借款页的 lenderAcknowledgementId 参数,按账号隔离加载单条详情并直接打开;不依赖其位于列表第一页。URL 为当前详情的单一来源,非空 ID 优先于发起草稿;切换声明或浏览器返回时清除旧草稿、核对状态及错误,并取消旧请求。失效/他人记录继续沿现有详情服务校验,不凭通知恢复权限或效力。
  6. assertEvidenceComplete 的协议类依据接受有效声明,余额确认与后续还款消费者统一使用;有效性既看决定与失效状态,也重比当前条款、身份和原件。余额确认先读出借人 ID,再按出借人 → 借款取锁、重读并核对关联,使同组另一笔原件或身份变化与材料消费串行;不能仅锁当前借款后消费旧对象。纸质依据继续可用,原件/代账/必要调整证据不放宽。出借人确认不推进余额、授权、付款状态。
  7. 增量迁移预计从 82 到 83,无存量回填或生产操作。回退保留新增历史表,不回删确认记录;旧应用不认识在线替代材料,线上已消费在线依据后不得声称可无影响回退到旧版,应使用兼容修复或先核实纸质依据覆盖。发布与生产迁移仍另行批准。

验证沿现有隔离 PostgreSQL/HTTP/browser runner,新增定向 fixture;真实账号、回单、生产数据和外部服务不用于开发验证。重点验证本人越权、快照不可变、改回旧值不复活、必要材料不放宽、决定/变更并发及审计回滚。完成后启动只读 reviewer;inline 主会话自行实施和检查,不派 implement/check 子代理。

2026-10-09 N5-P 原借入回单识别预填设计(历史规划记录,已实施发布)

P-A 现有能力与方案选择

对应 PRD P1–P6、AC32–AC39。基线为 45737ccb,沿 CompanyLoansPage 登记入口及 CompanyLoan / LoanEvidence 模型实施,不新建凭证中心、银行流水系统或业务草稿表。现有创建后的 confirmation_status=unconfirmed、三类附件余额确认及公司代表授权继续使用。

已检查来源 事实与设计影响
client/src/pages/CompanyLoansPage.tsx:176;server/src/routes/companyLoans.js:262、:314 创建与上传分离;新入口需一个有原件的保存动作,不能由浏览器串行两次写入冒充原子成功。
server/src/services/paymentReceiptDocument.js:101;paymentReceiptDocumentWorker.js:3 已有受限 PDF 文字读取。抽出或复用受限读取层供本地字段提取,旧 inspectReceiptDocument 输出与付款分类语义保持。
server/src/services/paymentReceiptMatching.js:41;paymentReceiptOcr.js:19 付款归一化包含金额/账户/编号,但没有到账日期/双方名称,且字段识别依赖腾讯。新增借入专用白名单解析,复用底层客户端及值解析;不改变旧付款输出与判定。
server/prisma/schema.prisma:3973、:4063 已有经办请求键、同主体/出借人/原引用唯一约束及附件摘要,可实现本期保存和幂等,不计划迁移或新任务队列。
server/src/services/crypto/index.js:103;purchaseAttachmentPolicy.js 复用认证加密及实际字节验证;预填结果只经短期、专用用途的加密上下文往返,不能把完整 OCR 结果塞入可读签名 token。

采用“浏览器暂存所选文件 → 无业务持久化识别 → 核对 → 携同一文件保存”的方案。用户只选一次原件;网络上识别与保存各传一次,换取无需新建临时附件池、清理任务或跨设备草稿。关闭前尚未保存的内容不续存,成功保存的文件仍按原借款附件治理。

P-B 识别合同与最小字段

拟增加 POST /company-loans/incoming-receipt/recognize,严格 multipart 一份 PDF。授权沿财务角色加 loan.manage;涉及员工银行卡比对时追加既有银行卡权限,不授予经理全局借款读取能力。先执行文件扩展名/MIME/实际字节与大小检查,再在事务外执行受限解析:5 MiB、20 页、既有 5 秒/128 MB 工作者上限。损坏、加密不可读或不安全文件不能保存为正常识别附件。

  1. 本地提取页面文本后,按明确字段标签与版面行关系提取,不使用任意数字猜测。金额保持十进制字符串/最小单位,日期用真实日历校验,不以打印时间、导出时间代到账日期;两个同类值矛盾则留空。标识保留字符串及前导零,流水号和凭证号分别取值,稳定排序选唯一引用。多页重复同一交易可合并;不能证明同一笔时拒绝预填,不只处理首页。
  2. 名称、币种、付款/收款账号用于判断候选及冲突;原始文本仅内存处理。给浏览器的字段是最小业务白名单、遮罩账号、source=pdf_text|ocr|manual、逐字段缺项/歧义说明、凭证性质和入账方向提示,不返回完整账号、原文或提供商响应。凭证正式性和成功状态分别表示,识别成功不称为银行验真。
  3. 本地必需字段充分时零云调用;不足时只使用既有已配置银行 OCR,在每份文件的一次受限识别请求内处理必要页,每页最多一次,整请求有总时限,不能随轮询或组件重挂自动重试。复用客户端时读取借入所需日期/名称后立即白名单压缩,不让旧付款归一化丢掉这些字段;不因提供商结果覆盖本地已发现的非最终/失败/多交易限制。OCR关闭或失败保留本地有效字段,并允许财务手工补齐;刷新识别是显式用户动作。
  4. 借入按付款人→个人、收款人→公司判断,不能复用会拒绝贷方的 paymentDocumentReady。公司支出方向是相对于所选公司判断,不能仅见票面“借方”就拒绝个人付款方出具的回单。完整名称/唯一关系可建议匹配已有公司与出借人,歧义不默认选第一条;历史付款账号与员工当前收款账号不同只提示核对,不自动刷新或否定历史关系。确认为其他收款主体、非人民币或明确银行失败/处理中/非最终时,此文件不能经新入口保存为有效借入原件。
  5. 初步识别与选择主体后的校验可共享同一上下文,无需为切换出借人再次调用 OCR。服务端以最小加密上下文保存字段/性质供下一请求核对,绑定用途 loan_incoming_prefill、经办员工、文件 SHA-256、解析版本、签发时间和到期时间(30 分钟),只经请求体传输且 no-store;不放 URL、localStorage 或日志。解密后校验用途/时限/身份,不能借字段加密的完整性省略业务校验。

P-C 确认保存、重复与原件

拟增加 POST /company-loans/from-incoming-receipt,严格 multipart:同一原件、加密预填上下文、请求键、现有登记字段和明确核对声明。人工改正仅允许本金/日期/引用及用户本来就需填写的登记字段;身份只能选择现有出借人,不接受账户替换、confirmed 或银行成功状态。未知结果可人工补填,token中明确矛盾不能被浏览器删字段消除;OCR关闭的人工路径同样需要文件校验和身份绑定。

  • 保存先重验实际原件、摘要、上下文及登记字段,再校验所选出借人/公司和其版本;要求已查看原件、核对借款性质和主体。openingOutstandingPrincipal / balanceAsOf 必填且不由识别预填为已核实事实;仍执行本金上限、日期顺序和非未来截止日。
  • 文件写存储放在短事务外。事务内创建借款、kind=incoming 的受控附件及两项必要审计;对外只在全部成功后返回。失败只删除本次新写对象;重试读取已成功事务并核验相同字段和文件摘要,不重新上传关联。对象存储与 PG 无分布式事务,进程崩溃可留未引用对象:不将其暴露为成功记录,清理失败留脱敏告警与原存储运维处置边界,不新增通用扫盘/删除服务。
  • 沿用 (created_by, request_key) 幂等与 (legal_entity_id, lender_id, origin_reference) 唯一约束;请求等价比较必须包含原件摘要。新保存以出借人行锁串行,同主体/出借人已存在相同 incoming 摘要时返回已有登记提示,不新建。普通原件追加路径也参加同一重复核对,覆盖新保存与旧上传的竞争,既有历史重复不自动合并/删除。
  • 保持“出借人 → 借款 → 编号”方向,与还款创建一致。已有借款原件上传先只读定位出借人,再锁出借人、锁借款并重验归属;不能在已持借款锁后新增出借人锁。新建持出借人锁后只创建新借款/编号,不再锁或修改已有借款,不与付款批次建立反向依赖。实施前用确定性交错验证该顺序,覆盖原件上传与还款创建;发现与既有约束冲突时先修订设计,不靠加长超时。重复摘要仅证明相同文件;不同扫描件且引用不同时,不能宣称已具备全银行交易去重。
  • 成功仍为余额待核实,原件可按既有用途下载接口读取,审计只留来源、摘要、解析版本和修正字段名等必要元数据,不保存明文 OCR 输入或完整账号。协议/余额核对/调整依据沿原入口,识别不推进授权、余额确认、付款或核销。

P-D 页面与兼容

CompanyLoansPage 的登记借入弹窗增加“上传回单预填/手工登记”路径,复用原 Dialog/Input/Button 和现有字段。上传处理中、待核对、需人工补充、文件不适用和保存失败均有就地提示;能纠正的字段可修改,识别结果须明确仍待核对。当前缺少 frontend-design skill,本阶段仅复用既有组件及样式,不做新视觉裁决。

文件只存在当前表单内存,预填结果按身份/文件请求序号隔离;选择新文件显式重置其提取字段,任何迟到返回都不能覆盖新文件或已手改值。识别/保存都传 AbortSignal,卸载/身份变化取消并清理;保持同身份合法401恢复,禁止新身份重放旧写请求。待保存时阻止重复提交,提交结果丢失时以同请求键回读原结果。

银行候选匹配不更改员工资料;缺出借人使用现有登记出借人入口。原手工 JSON 登记及材料上传仍可用,不强制所有历史借款都经过 OCR。新入口仅支持 PDF,原图片附件能力和旧付款回单支持范围保持。

P-E 运行边界与回退

本期不计划数据库迁移,不增加提供商、生产密钥、全局文件预览或长期识别存储。保存结果使用旧模型,可回退新入口及专用接口后继续按原页面管理,不删除已登记借款或原件;回退仍遵守原关联方模式最低兼容版本限制。

本地测试只用合成 PDF/人员和提供商替身。真实云识别、当前银行产品额度与费用边界须在首次获准实样验收时确认;不从发票 OCR 的额度结论推定 BankSlipOCR 可用,也不自动启用服务或修改计费。未知可人工填写是本期明确降级,不以真实材料未调用为由伪报自动识别已验。发布按最终候选门禁和另行部署授权执行。

2026-10-09 N5 员工出借人选择方案(已批准,已本地实现)

本节对应 PRD 的 AC28–AC31。员工资料已存在于 Employee;现有 loan-lenders/identity-options 仅提供身份选择,借款登记尚未复用银行卡。目标是让财务选择现有员工并核对资料,服务端建立或复用借款出借人关系,保持现有贷款、授权和付款快照模型。

  1. 选择与资料来源:在原借款页面增加员工选择流程,复用现有选择框与人员检索样式。返回允许的身份摘要、公司关联、银行与遮罩账号、资料是否完整及来源版本;不向浏览器传完整账号或身份证件。来源为员工主档的当前银行资料,账户名沿现有员工付款规则使用真实姓名。公司关联可作为借款主体默认值,但必须由财务确认借款所属公司,不能把任职公司自动当作债务人。
  2. 服务端关联:新增明确的“从员工关联出借人”动作,只接收员工、借款公司、所见来源版本、核对声明及幂等键。服务端重读员工与银行资料,校验可选身份、公司、银行支持、账号格式/可解密性及资料版本,再沿现有加密方式保存借款侧资料、员工关联和审计。不能通过客户端提供姓名或账号覆盖来源。身份核对由财务此次明确确认完成,不再让同一员工先手填、再另做一次身份绑定。
  3. 敏感权限与维护入口:保留 loan.manage 的财务角色条件,并沿用 employee.bank.read / employee.bank.manage 的现有银行卡读取权限;不借员工选择扩展到完整人员档案、身份证件或银行卡明文查看。资料不全时定位原员工资料维护入口,有维护权限才可修正。姓名、开户行或账号修改不在借款选择弹窗内重复提供。
  4. 重复选择及锁序:同公司同员工存在唯一可用登记时复用;多个历史登记时返回明确冲突,不自动合并借款、账户或授权。新建关联在事务内对来源员工及经办人排序串行,重查重复并保存创建/复用的请求键绑定;刷新已有出借人沿“出借人 → 人员”的顺序锁定,不持人员锁反向锁已有出借人。员工使用 FOR NO KEY UPDATE,保留串行保护并兼容审计外键的 KEY SHARE。旧身份关联路径也参加同一重复检查;发现并发关系变化时结束事务,按正确锁序重新核对或拒绝,不建立错误关系。
  5. 资料变更与历史:预览至保存间来源变化要求重新核对。已有借款资料与员工主档不同,不静默覆盖;显式“使用当前员工资料”动作由服务端读源、比较版本,沿既有在途禁止修改、账户/身份版本与授权失效规则处理并留审计。已审批或已付批次仍消费原冻结快照。后续员工资料维护不直接重写出借人、付款批次、银行事实或本金。
  6. 数据与范围:优先复用 employee_id、出借人版本和既有审计,无需为员工再建一套人员档案。不得为减少手工录入而增加无依据身份、放宽审批排除或恢复 Q6。若实施研究证明必须新增数据库约束或字段,先明确迁移、存量与兼容影响,再扩展本方案;本节不预先授权存量合并、生产迁移或业务录入。

验证包括:资料完整的员工正常关联、缺字段/账号不可用/银行不支持、无银行卡读取权限、客户端伪造、重复及并发选择、预览后资料改变、已有借款资料不一致、在途禁止刷新、员工改号后旧付款快照保持,以及财务/马经理后续授权分工。只用合成数据,不读取真实账户或调用银行/OCR;沿现有测试入口完成针对性验证和只读复核。

界面查询按身份/员工/公司隔离;两个新写动作透传取消信号,随组件卸载或身份变化终止请求,成功回调再次核对身份。不能只隔离回调而让迟到 401 在另一身份下重发原动作;保留同身份的正常令牌刷新。只保护本次入口,不改变共享 HTTP 恢复语义。

2026-10-08 实样发现后的凭证处理方案(N1–N2 已本地实现)

本节对应 PRD 顶部 R4/AC5 补充及 implement 的 N1–N2,用户已明确“开始执行”。沿用已实现的两人关联模式、回单存储、人工核对和核销流程;不重新设计 S1–S8/SR,不把 S002 专项格式兼容纳入必修范围。

实现收敛:本地使用 PDF 文本解析读取票面限制,无法可靠解析的维持未知;新增的结构化凭证依据随既有加密核验/人工提案保存。人工可按正式回单的已记账支出和记账日期确认,不生成虚假的银行状态原文。旧证据通过有权经办显式发起的本地重检生成新版本,保留历史、不调用云 OCR;最终资金动作不默认接受缺少新版依据的旧记录。

本轮采用现有表,无新增迁移。新增 paymentReceiptDocument 服务和受限 PDF 文本工作线程,使用 pdfjs-dist;单文件最多 5 MB、20 页,工作线程限时 5 秒、旧生代内存上限 128 MB。结构化凭证类型为正式回单、非最终回执或未知,原始票面文字不落日志;识别异常维持未知,不能自动核销。

人工依据分“原件明确成功”和“正式回单已记账支出”。后者须填写真实且不晚于当天的记账日期、原件已核对声明及依据说明,保存 transactionStatusRaw=null;新增人工依据必须按该批次模式确认。既有非最终说明、贷方入账、多个回单或失败/处理中矛盾均不能由人工覆盖。自动凭证检查位于核验构建与最终重建,未放入失败/终态事实也使用的低层字段匹配函数。

旧记录显式重检接口为 POST /payment-batches/:id/receipt-attachments/:attachmentId/document-check,要求当前版本、财务权限和经办资格,核对原件实际大小与摘要、未被消费,再在同一事务新增核验版本与审计;旧人工确认不得转移到新版本。历史 OCR 为 0 页时详情仍可打开重检入口,负数、超上限等无效页数继续拒绝。已核销历史不自动重写。实现及验证证据见 implement 顶部;独立代码复核和真实还款闭环不在本轮完成结论内。

凭证性质、字段读取、交易归属分别判断

  1. 凭证性质先区分已确认的最终付款依据、明确非最终依据、尚不确定。银行限制说明、实际记账方向和入账/付款信息属于判断依据;文件名、标题、OCR 请求成功或没有提取到免责声明均不足以判为最终依据。公司贷方借入和借方还本分开处理。
  2. 自动路径只开放经过实际材料核验的格式与字段组合;识别来源必须能覆盖判断凭证性质所需内容。当前 BankSlipOCR 的六类归一化字段不能证明完整覆盖票面说明。可在本地核对 PDF 文字,缺文字/提取异常保持未知;本阶段不以接入新的云服务或实现所有扫描件 OCR 为前提。
  3. 人工路径在原件实际信息足够时使用。沿既有财务录入、马经理关联方确认,补充可追溯的凭证性质及已记账依据,不补造成功状态。明确非最终的回执不能经普通人工决定升级;需要取得对应正式付款证据。没有可用最终证据则保持待核对,不能以“以后会补回单”先核销。
  4. 凭证足以证明付款也不自动证明属于哪个批次。金额、币种、双方账户、付款方向、银行交易身份及既有候选/提交关联继续分别检查;回单编号、客户方流水号和网银指令号分开保存或引用,不靠人工照抄使之相等。编号不足时保持待对账。

依据留存、旧数据和最终消费

  • 在既有证据模型上留存原件摘要/版本、凭证判断及其依据、自动或人工来源、决定上下文;核验结果持久化、人工冷重建和最终核销都必须保留并重验这些信息。不能只在上传时或页面增加提示。
  • 换件、重新识别、作废和候选变化继续使旧依据失效。旧核验记录缺少凭证判断时不能默认通过;已记账记录保持历史不可变,需要核查的问题另行登记,不自动撤销本金核销或重写生产数据。
  • 本轮凭证依据随现有加密核验和人工提案留存,未新增迁移。涉及共享回单服务时回归报销消费者,既有独立性、交易唯一性、失败/受理与资金约束保持。
  • 验收覆盖明确非最终说明、字段中出现成功但票面有限制、无法完整判别、正式凭据没有字面成功状态、借入/支出方向不同、旧结果缺依据、人工重建及最终核销。去除关键凭证检查后,测试必须能区分错误放行或合同退化。

实际材料与完成边界

  • 原四份获授权 PDF 和 OCR 配置读取范围继续有效,无需为相同范围重复授权;先复用既有结果和本地材料,不无目的重跑云端。新增两份正式借入回单目前只做了本地读取;确有必要发送新文件时再明确文件范围。
  • S001/S003 作为非最终凭证反例;S002 维持既有需复核结果,可用于材料性质/人工依据分析,不要求兼容其全部 OCR 字段,也不为它索取保证金退款材料。新增两份借入回单用于本金及格式核对,不能充作还本付款正例。
  • 优先用现有材料验证原件字段与人工处理是否可行;只有一个具体交易的完整归属无法核对时,才列明需要该笔交易的正式支出回单及网银实际提交详情。现有无真实借款还款时,不要求制造付款获取样本;借款全链用合成数据,首笔真实银行闭环在获准实际还款后验收。
  • 正常办理必须有一条经验证可用的自动或人工路径;仅能拦截不代表可启用。首笔前的软件/材料验证与首笔后的实际银行闭环分别记录。异常缺实样保持未验,不提前认定失败释放等已具备真实银行接受性,缺证继续占用。

2026-10-08 财务经办与马经理关联方确认方案(本地实现及合成验证完成,已授权本地提交)

用户已确认马经理有权代表公司批准,并在规划完成后明确“开始实施”。马经理同时为股东和个人出借收款人;技术员工不参与复核、审批、见证,不增加权限或分派待办。公司授权这一业务事实不再待决。本节是本次权限模式变更的执行合同;本地实现及合成验证已完成,具体证据与剩余验收见 implement 顶部。下方历史设计中的独立复核,除 Q6 外按本节明确区分模式;本地改动不等于生产已具备该模式。

RP-A 业务范围与实际分工

  • 默认 independent 模式保留原规则;新增 related_party 模式只用于经登记的本公司、真实个人出借人、其关联员工以及明确列出的已确认借款。马经理的选择依据真实员工与出借人关联,代码不硬编码姓名、不虚建“非员工出借人”隐藏关系。
  • 财务办理资料核对、申请、制单、提交记录和银行证据。马经理在公司授权范围内批准或退回,按钮及记录标明“关联方确认:确认人同时为本笔出借收款人”。这是一项真实的利益关联例外,不称为独立审批,不以两人确认或 OCR 抵消该关联。
  • 付款退回沿原付款决定接口留存 decision=reject、理由、决定人和授权上下文;该申请不能再批准或导出,退回本身不释放占用。财务按未发送取消规则取消原申请,再新建更正申请;原退回记录不可改。数据库禁止将退回决定当成已批准付款。
  • 财务兼任人事行政不影响其经办,但不能自审。同一员工的多账号或多业务角色按同一真实身份处理。经理可以承担本批多个确认环节,不新增第三位审批人;不能承担本批经办、上传或录入等被排除工作。
  • 正常流程为财务核实本金并发起申请→马经理代表公司确认→财务导出并在网银付款→上传回单沿既有 OCR 核对→证据满足后由财务登记核销。完全满足自动核验的回单无需再增加一次人工回单确认;有人工例外或归属歧义才进入对应确认。
  • 借入凭据、历史归还和代账核对仍是本金的事实来源。出借人确认余额、账户或收到钱与代表公司批准是不同声明,分别留痕;本方案不把聊天中提及的金额或资料自动录成真实余额。

RP-B 公司授权、范围与模式

采用借款模块内的小范围授权记录,不改变通用角色平台。财务录入已存在的公司授权事实、依据说明/引用、公司、出借人、指定确认人员工标识及覆盖的借款;马经理本人确认后生效。该登记反映用户已经确认的公司代表权,不再要求技术员工或额外第三人批准。

  1. 授权内容按版本保存,覆盖借款用真实关联关系约束,不能包含其他公司、出借人或未确认借款。财务不能单人激活、扩充范围或把自己设成确认人;新增借款需登记新范围版本并由马经理确认。
  2. 授权确认只是业务授权留痕,不授予新的全局经理/财务权限。每次新决定还要检查当前人员、经理/CEO业务角色及相应现有权限,授权记录不能让离职人员或无权用户通过。
  3. 新建还款时服务端查找有效且覆盖全部分配借款的范围,冻结 approval_mode、授权标识/版本、公司、出借人及指定确认人。界面显示适用模式,不能用客户端参数或调用顺序把无资格的独立单改成关联单;范围缺失或冲突明确拒绝。
  4. 旧独立批次不自动转换,已送审、已导出或已发生银行事实的模式均不能改写。既有草稿若需改用关联模式,只能满足原安全取消条件后重新申请,不能重用旧审批、导出或银行事实;不安全取消的历史批次另行评估。
  5. 授权生命周期区分“允许新付款”与“允许处理历史对账”。停止新付款后不能建单、付款前批准或导出;仍覆盖原借款的对账授权不会因付款范围用完或付款期限届满自动失效。停止对账权限阻止新的人工对账决定及最终释放,不能删除旧事实或旧批准。
  6. 财务或马经理可登记当前版本的停止及理由;已被取代版本不能再停用。恢复或扩大权限采用财务登记、马经理确认的新版本,缩小范围或停止后不得回退使用更早版本。历史内容和生命周期事件保留,不能靠恢复状态让失效材料批准复活。新的对账决定可引用当前覆盖原批次的新授权版本,原批次的付款授权引用与模式不改。

RP-C 决定与经办冲突

独立模式继续要求无利益关联。关联模式只豁免“指定确认人等于出借收款人”这一种冲突;原来各路径的制单、提交、导出、登记、证据上传和人工录入冲突继续生效。参与人检查必须保留冲突原因,不能在算完一组排除员工标识后直接删掉马经理,否则他兼任上传人时也会被错误放行。

服务端在关联批次的经办入口就拒绝指定确认人创建/提交/导出、登记银行提交或上传/录入/提案银行证据,避免只有两人的配置事后找不到确认人。决定入口再次检查全部相关历史经办记录,包括已作废或被取代的回单,不能靠作废清除冲突。公司授权确认、此前正常审批或收款人声明本身不等同于经办参与。

环节 财务职责 马经理职责 保留的最终条件
授权与未还本金 登记授权范围、借入及历史还款依据、与代账核对;只有已确认本金可申请 确认其公司授权登记;需要时另作债权/账户声明 范围、身份、资料及未还本金有效,授权确认不代替余额核实
付款申请与制单 创建、分配、提交、导出、实际网银操作 代表公司作关联方付款确认或退回 当前授权、角色、身份版本、启用状态、金额和收付款快照、容量与冻结门禁
银行提交与清单 逐次登记/撤回提交,确认清单完整 关联方确认完整清单 新登记、撤回、导出均使原清单确认失效;每次提交分别解释
成功或失败回单归属 上传/录入回单,提出证据及排除其他候选的理由 对需人工判断的归属作关联方确认 交易身份、核验/人工录入记录、完整候选及所覆盖指令一致;同金额/账户或两人声明不足
人工回单例外 留存原件并录入 核对原件作关联方确认 状态、字段和原件可读,失败/处理中/矛盾信息不当成成功;证据重建及核销仍重验
严格失败、银行终态、取消 登记逐提交事实及银行证据;条件满足后取消 承担当前需要的失败/终态决定,以关联方确认记录 严格失败口径、指令对应、全部提交与导出覆盖、3天等待期、无未解决成功/处理中事实;最终释放重验
SR补证恢复 对原终态补证、重新送审 对新增事实和恢复轮次作关联方确认 原结论不改;材料变化旧批准失效;不重开付款,最终取消消费最新有效恢复
晚到成功 登记原件与事实,触发冻结,条件满足后补记 确认归属及银行事实 原付款历史快照、唯一交易、逐借款容量;先解决占用冲突,差额列待追回;补记不能导出
误报/重复登记关闭 提出更正依据 关联方确认更正 原记录与更正留存,证据不足不能关闭;不能改变已入账事实或清掉其他冻结原因
部分/全额追回 登记真实到账及材料,执行符合条件的入账 关联方确认到账 实际到账、交易唯一、部分只冲减待追回;全部有效原因关闭才解冻,不做冲抵
Q6人工确认未提交 本模式不可发起 本模式不可确认 原规则需两名额外独立复核人;服务端、最终释放及界面共同限制

材料不足的结果仍为待对账、保持占用或冻结。关联确认不降低证据门槛,也不能保证同金额分期都自动核销。若两位实际办理人中没有当前合格确认人,可继续由有权财务留存事实,不以单人确认恢复资金动作。

RP-D 当前资格、历史效力与并发

动作类型 资格与授权时点 停用后的处理
新申请、付款前批准、导出及重新导出 当前经办/确认资格、付款授权、冻结状态及版本;实际导出前再次检查 停止新付款即拦截,旧“已批准”不能继续导出
新的银行事实、归属、人工回单、恢复或追回决定 当前确认人业务资格及对账授权,绑定本次证据;不要求原付款审批人或出借人恢复旧资格 新决定在对账权限停用后拒绝;有权财务仍可登记新事实,冻结照常产生
确认未付款及最终取消释放 当前操作人、当前对账授权、有效的对应决定、最新材料与全部释放门禁 对账授权停止后不能新释放;付款授权停止本身不阻断有证据的对账释放
已付款核销、已确认银行事实的补记/追回入账 当前记账操作人有权;原付款/事实决定当时有权且证据仍有效,按各自冻结模式和快照重验资金条件 停止新付款、原审批人/出借员工事后离职或主数据停用不抹掉已付事实;不新增付款指令。需要重新人工确认的失效证据仍按新决定的当前资格规则处理

已作出的关联决定不能伪装成独立批准。最终使用历史决定校验其当时记录的模式、授权版本、范围和参与身份,不再通过“历史收款人必须独立”的旧函数;也不能只认一个 approved 状态而不验材料与交易。

沿用既有批次→回单交易/附件→出借人及人员资格的锁序;创建锁出借人→借款且不等待既有批次。授权停用/新版本生效仅锁出借人,不再取得既有批次锁。资金动作在持出借人锁后重验授权,因而与停用串行;不得新引入出借人→既有批次的逆序。当前资格在决定事务内校验,决定/审计/资金更新原子执行。

  • 付款授权停用先于新批准/导出提交:后者拒绝;导出先完成:保留导出事实,后续停用不能让已下载文件在银行失效。
  • 对账授权停用先于新决定或最终释放:拒绝;有效决定先完成:保留该历史决定,最终释放仍重验当前对账授权;已确认的真实付款可按历史证据记账。
  • 材料/候选变化仍按现有机制使旧批准失效。核销/释放只依据事务当时已知事实;之后才出现的新证据进入晚到结果对账,不宣称锁能防止未来事实。
  • 禁止通过前端能力缓存、自动重试、权限恢复或删掉冲突原因绕过上述时点;幂等请求只返回原事务结果,不重复产生付款或释放。

RP-E 数据与完整消费者

本地新增增量迁移 20261009010000_loan_related_approval,仅在隔离合成数据库验证。采用现有还款/事实表加明确模式及授权引用,不建设通用代理审批系统。

数据 实现内容与约束
借款关联授权、覆盖借款与生命周期事件 公司、出借人、确认人员工外键,范围借款外键,版本、依据引用、财务登记/经理确认、两个权限方面的状态事件;内容与已确认事件不可改删,扩大范围必须新版本
LoanRepayment付款上下文 approval_mode = independent / related_party、授权标识/版本、确认人及关联身份快照;创建时冻结,之后不可转换;新关联记录缺少范围或身份不能落库
逐次决定上下文 批次审批与其审计、归属、提交清单、终态事实、SR恢复、银行事件及借款人工回单决定均留存确认模式、授权版本、关联身份、决定人/时点及证据快照;异常的新决定可引用新的合法授权版本,但不覆盖原付款上下文
历史和数据库保护 原记录显式归为独立模式,不补造授权;保留经办人与确认人不同、已复核记录不可改删、交易唯一与资金容量约束;关联字段完整性/外键与模式一致性另加约束,共享报销记录不得标成借款关联模式

快照只保存身份标识、版本、引用与摘要,不复制解密账号或银行原文。待审记录变化仍新建/取代,不回写已作出的决定;驳回也保留当时模式与理由。

源码已确认的改动消费者如下,实施须覆盖入口、读取/重建与最终使用,不能仅修改 activeReviewer 或页面按钮:

位置 需要贯通的职责
companyLoanPayments.js prepareLoanRepayment 创建前候选门禁、eligibleLoanReviewers、activeReviewer、validateLoanPayment、assertApprovedIndependently、归属确认、严格失败、核销与取消;把冲突原因与模式分开
loanBankSubmissions.js / loanBankTerminalFacts.js 清单确认、终态参与人及决定、confirmNotPaid、材料状态与最终释放重验;保留导出/指令逐次覆盖和等待期
loanReleaseRecoveries.js / loanBankResults.js 恢复逐事实/整轮确认、最终消费、晚到/更正/追回决定与记账;冻结关闭仍只能由对应事务完成
paymentReceiptManualReview.js / paymentReceiptManualPersistence.js 人工提案决定、receiptParticipants、assertIndependentReceiptReviewer、loadApprovedManualReceiptEvidence、详情重建及所有复用人工证据的校验;借款分支识别模式,报销/差旅继续原规则
paymentReceiptVerification.js 及交易认领路径 自动核验和最终消费使用正确历史审批上下文,保留唯一交易、字段/状态及候选检查;OCR成功不代替公司批准
loanNotSubmitted.js 与取消消费者 关联模式在发起、决定及最终消费三处拒绝Q6;旧独立Q6双审与材料合同不变
routes/paymentBatches.js / routes/companyLoans.js 服务端候选、动作能力、授权登记、范围受限的经理材料读取与确认;不得为绕过目前财务专用读取检查而授予经理全局财务权限
CompanyLoansPage.tsx、还款详情/对账组件、待办及通知消费者 依据服务端返回的模式和能力展示动作、材料与历史文案;技术员工不进入候选或通知对象,现有独立模式显示不变

RP-F 页面、错误与回单

  • 沿用已有页面、对话框和样式。授权及范围在借款业务内登记;还款详情、确认弹窗、历史决定和待办都显示关联身份。按钮区分财务“提交/登记/核销”与经理“关联方确认/退回”,不出现“独立复核通过”的错误描述。
  • 服务端返回受范围限制的能力和不可用原因;错误码合同区分无有效授权、超范围、经办冲突、证据失效和本模式不支持Q6。未授权人员不通过原因文本获得借款、人员或银行材料详情。经理只获得作出本笔决定所需材料,完整账号/原件仍要求用途、权限和审计。
  • 收款人多角色不能获得本批经办入口;财务多角色不能获得自己的确认按钮,直接调用接口同样拒绝。电脑和手机均完成授权确认、付款及异常流程操作,不以共用组件替代移动端验证。
  • 普通回单继续 BankSlipOCR → normalizeBankSlip → 匹配/必要人工核对。按获准使用的实际文件确认可读字段和状态;合成测试只替换云端返回。无需提前问银行能否识别,也不能补造回单未记载的流水号或把 OCR 视为银行验真。
  • 回单流水号/凭证号与提交指令号的关系从实际回单、网银提交记录核对,不默认相同。现有依赖编号的失败/处理中路径继续严格检查;信息不能对应时保持待对账。银行终态或“无提交”的证明属于异常证据问题;Q6在此模式下关闭,官方无结果材料不再作为普通还款启用前提。

RP-G 实施、验收及启用边界

  1. RP1:数据、授权范围、两类权限生命周期与冻结模式;RP2:所有服务/路由/证据重建/最终消费;RP3:现有电脑手机界面与范围访问;RP4:合成正反例、并发、资金守卫变异、只读复核和最终候选检查。详细清单及验收映射见 implement 顶部。
  2. 改动应一起完成到可办理、可对账再启用,不能仅部署放开收款人审批的中间版本。AC20–AC26已有本轮本地合成证据,AC27数据库部分通过、独立代码复核及固定候选正式门禁待完成;原AC3保留独立模式基线,其余资金要求不降级。
  3. 本地已有A/B/C、S1–S8、SR和电脑/手机界面;本次是在已有流程上调整模式,不重做或声称这些尚未实现。4c37fcee 的门禁只证明旧独立模式,关联模式必须绑定自己的测试结果。完成实现后按项目规则只读复核;inline下无法派审则如实保留待独立复核。
  4. 2026-10-07的获准生产只读核实为OA借款记录0、73迁移已应用;本轮新增后本地82迁移。这只是时点事实。发布前再获准核对存量及实际迁移差集,不能永久复用空存量结论;若出现历史在途独立批次,单独评估且不自动转模式。
  5. 新决定一旦产生,旧代码不理解关联确认的含义,不允许直接降级、删除模式字段或改写历史。需要停止新付款并采用获批兼容修复/回退方案,保留已发生银行事实及其证据。
  6. 本轮已授权本地实施与验证;用户随后明确授权将完整的 39 项改动本地提交,并运行新候选正式门禁。真实授权配置、生产查询、推送、部署及真实付款不在此次执行内。运行时验证、主会话检查、独立复核和真实材料验收分别记录,不沿用旧候选回执证明新模式。

已否定方向(历史说明)

此前讨论过让技术员工获得借款专项复核资格。用户已明确否定,不采用、不实施、不再作为待确认项;现方案不依赖该员工,也不以另建身份或增加通用角色代替他的同意。

2026-10-07 S4–S8 实施细化(沿已批准范围,尚待最终验收)

  • Q6 使用独立的人工声明与复核记录,不混入银行终态事实。三类附件固定分类;查询及对账覆盖首次导出至登记日(公司时区),每个相关导出人均须有文件去向说明。完整空提交清单可以独立复核;撤回登记不能充当“未提交”。混合批次仍逐条验证已提交部分的银行终态。
  • 每次人工声明绑定材料修订、全部导出/提交/核验、付款快照及同额候选。两名不同且当前合格的复核人分别决定。失效声明可以追加取代,原银行终态不改;最终取消重验全部条件、物理文件摘要及双审,数据库另外约束释放配对。
  • 冻结按来源事件逐条记录;只在新申请、付款前复核及导出入口检查。关闭函数仅供对账业务事务调用,没有通用解冻接口。误报须经独立人员凭更正证据确认;仅不确定或证据不足不能关闭。
  • 晚到成功及退款到账以人工核对银行原件的方式登记(不是 OCR 通过)。输入按既有回单归一化规则核对成功状态、双方账号、币种、金额和流水号,原始人工输入加密存储;查询完整输入必须填写用途并记审计。已取消批次可以另存银行证据,但不重开原付款回单、付款项或导出。
  • 归属批准到入账之间再次出现同额候选,最终入账重验会拒绝。可用同一交易的新登记取代未入账的旧批准,再独立复核;取代时保持至少一条冻结。银行交易的唯一认领在最终入账事务中消费,复核仅做冲突检查,避免尚未入账的失效批准占死交易身份。已入账的银行事实不能被重提覆盖。
  • 晚到补记与追回使用独立银行事件、交易认领及逐借款补记表,不创建付款批次。交易认领和原核销/别名空间相互排斥;复核与入账同样校验密钥和交易身份。补记成功之后,新申请可用本金要扣掉补记结清额,数据库容量检查也包含这部分。
  • 未释放的原占用在补记事务中以被银行事实推翻为原因释放,保留原终态和取消信息;其他仅占用的申请须先处理,不能算作已付。已经付掉的部分按差额列待追回;整笔超额时也保留银行全额和零结清记录。追回只接受实际到账并经复核,不用冲抵;部分到账不解冻。
  • 已有待复核或已批准的晚到成功时,旧终态取消入口拒绝,必须走对账补记;数据库延迟约束同样保护这条边界。取代已产生占用冲突的未入账事件时,同事务先转移冲突冻结再关闭旧原因;新事件入账或凭更正证据确认误报时关闭对应派生原因,不能留下不可处理的旧冻结。
  • 已用于误报解冻的更正证据属于已消费的复核依据,服务及数据库均禁止再作废。更正记录、原始银行事件及关闭依据保留,不回写原结论。
  • 终态界面支持一次关联多份同指令处理中回单。复核卡明确展示所选提交、终态类型、证据、了结回单;Q6 展示逐份导出及三类证据的准确绑定,失败归属展示覆盖指令及核验附件。历史作废回单仅可通过实际事实绑定、必填用途的对账读取查看;权限、隔离策略、物理摘要、审计及 no-store 保留,普通作废回单下载仍被拒绝,不恢复其付款效力。
  • S8 沿用既有 React 对话框和样式,未引入新视觉方案。页面集中展示导出、提交、证据、人工声明、补证轮次、银行事件和冻结原因;原制单不得再次导入网银的提示不是技术保证。
  • S0 存量已于 2026-10-07 获准只读核实:OA 借款记录为 0,发布前需重核。合格复核人数、银行编号关系及官方材料、真实回单验收仍未完成;本轮资金与界面代理已完成修复后只读静态复核,运行时结果见 implement。该复核不替代异模型或业务人员验收。本地实现/合成验证不代表可以部署或真实还款。

2026-10-07 补证后恢复方案(SR,第 1 版,用户已批准本地实施)

本方案先完成设计,随后用户明确回复“批准”,授权 SR-A、SR-B 本地实施与验证;SR-C 随 S8,提交、推送与部署未授权。S3 已本地提交 14aee82d;下文历史设计及实施记录保留其原时点。本方案补充 3.2 的释放流程,不把普通补证归入 S6 的晚到成功。

SR1 问题与边界

源码依据:loanBankTerminalFacts.js 的 proposeTerminalFact、confirmNotPaid 只接受 unknown;作废证据会取代关联事实。companyLoanPayments.js 的 cancelLoanRepayment 重验当前证据;guard_loan_repayment_history 禁止回写既有终态及其依据。因此,已确认未付款但未释放时,旧证据失效后即使取得新的有效终态证据,也无法完成重新登记与释放。

适用:批次仍为 reviewed/failed,原银行结论为 confirmed_not_paid 或 confirmed_failed,所有本金分配仍为 reserved。包括补换银行书面证据、同一交易换回单或重新识别、补登遗漏提交、候选批次变化导致归属复核失效。正常 unknown 仍走 S3;原有结论与依据仍有效时沿原取消流程,不要求额外恢复复核。

不适用:已取消释放、已核销、任一分配不再占用、已出现本笔成功事实。成功事实留待 S6;疑似成功或无法识别时可记录补证需求,但不得通过释放复核,继续占用,不把作废当作否定银行事实。处理中回单只能由同一指令的有效终态事实了结。本期不开放 Q6 人工未提交恢复、不降低 S0 存量核实或 S3 证据门槛。真实已付后退款、冲正、退汇仍不等于未付款。

SR2 历史结论与当前释放资格分开

  • 原 bank_result_state、bank_result_ref、审批与分配记录不回写,不把终态改回 unknown;新增恢复记录引用原结论及此前恢复轮次。补证不说明原未付款判断必然错误,页面表述为“原结论保留,释放依据待补充”。
  • 新增恢复轮次(拟表 loan_release_recoveries)与审计事件。每轮不可改的内容包括批次、原结论/依据、前轮、发起人、原因;送审时冻结的清单、事实、证据与候选快照另形成不可改的送审记录。
  • 轮次状态:collecting(补证中)→ proposed(待复核)→ approved/rejected;经办可撤回未批准轮次为 withdrawn。资料变化可使待复核或已批准轮次为 superseded;成功释放为 consumed。受控状态与决定事件同事务写入;不可删除,不可修改既有送审字段、复核意见或把已关闭轮次复活。
  • 每批次至多一轮补证中、待复核或已批准记录。需再次恢复时新建轮次;过期轮次的取代与新轮次创建同事务完成。请求键保证重试不生成重复轮次。
  • 一旦发起过恢复,最终释放只能依据最新一轮有效批准。驳回、撤回、资料变回原样、旧批准仍在数据库中,都不能重新启用原结论的释放权限。批准本身不释放额度,仍由财务执行最终取消。
  • 不生成付款批次或补记付款,不恢复导出、执行付款、已释放占用;本金在补证、送审、复核期间都不变。S5 的出借人冻结原因如已存在,不能被本流程关闭。

SR3 补证、送审与独立复核

  1. 当前持 loan.manage 的财务发起,说明失效原因;服务端验证适用范围并记录原结论。不得用管理员权限跳过。
  2. 在有效恢复轮次中,允许终态批次登记新终态事实;只对该入口放开原 unknown 限制。证据上传、作废、提交清单登记与复核仍沿 S1/S3 的事实规则;失效事实按既有规则取代,不覆盖旧事实。新登记的事实逐条独立复核。
  3. 补登提交后必须重做完整清单复核,并为每次有效提交举证。撤回登记仅是材料纠错,不代表银行撤销;新增再撤回也算清单变化。不能通过撤回真实提交消除已知银行事实。每条导出仍须关联已终止提交,历史汇总继续阻断;没有提交的导出留给 S4。
  4. confirmed_failed 的恢复也升级为 S3 的逐提交终态证据集合,不能重写原失败核验 ID。原证据仍可读且有效时可引用;换回单、重新识别后必须引用新核验记录。失败归属仍按提交及当前全部同额候选独立复核。
  5. 财务送审时,服务端重跑 S3 全部释放条件并冻结完整证据快照,不接受客户端自行宣称“完整”或自报有效版本。
  6. 当前合格的经理/总经理独立复核。排除本轮发起/送审人、所有相关证据上传人、回单人工录入人、终态事实登记人,以及本批次制单、提交、出借员工、导出、银行提交登记与清单确认经办人。取人员关系时包含旧记录、作废与撤回记录,不能借换材料消除经办身份。原审批人可参与,但必须满足当前资格与上述独立性;不因其是原审批人而自动放行。
  7. 批准时重新取当前材料和候选,比较快照并重跑全部条件;驳回或证据不足继续占用。原审批人和出借员工的在职/角色、主数据当前启用状态不重验,按历史审批与原冻结快照核对;当前操作人始终核验当前权限。
  8. 最终取消必须引用这轮批准;核对当前操作人取消权限,再次重验快照、释放条件与分配状态。释放、批次取消、轮次消费和审计一次事务提交,任一步失败全部回滚。已完成的同请求重试返回原结果,不重复释放。

沿用 S3:逐提交覆盖、逐导出关联、提交清单有效、终态证据有效、失败交易唯一性、必要的失败归属、无未解决成功/处理中事实、无历史汇总、距最后导出满内部等待期。对账单、截图、等待期或两个人确认均不能单独放行。未付款的新证据不要求再机械等待 3 天,但仍必须满足最后一次真实导出的等待期。编号对应关系仍待 S0,不靠人工照抄回单号补足银行证明。

SR4 快照失效与并发

送审快照包含:原结论与依据;原付款快照标识;全部导出;全部提交(含撤回)及清单复核记录;逐提交终态事实与复核记录;银行证据 ID、摘要和作废状态;全部付款回单的 ID、摘要、OCR 版本、核验记录、人工录入/复核记录及作废状态;归属批准及全部候选集合;分配 ID/金额/占用状态。证据只要改变,旧批准就不能沿用,即使银行流水号相同。

使用服务端单调递增的材料修订号并保存上述快照;材料新增、作废、重识别、人工录入及材料复核均推进修订号,防止“改完又改回”复活旧批准。恢复轮次自身的送审、批准和消费决定不改变材料修订号,避免批准使自己失效。候选变化同时重查实际集合,不只依赖目标批次自己的修订号。证据送审与批准之后的缺失、失效、存储读取错误或摘要不符,均不得放行。

锁与检查须覆盖所有写入者,而非仅恢复接口:同批次最终释放与证据作废、付款回单上传/核验落库、提交登记/撤回、清单/事实/归属复核串行;同出借人的候选形成与候选检查也串行。沿既有锁相对顺序:批次 → 回单交易 advisory lock(需用时)→ 出借人 → 按 ID 排序借款行,不引入反向加锁。编码前核对所有受影响入口及后台 OCR 写入的实际锁序;多批次场景不在持有出借人锁后反向锁其他批次。

  • 变化先发生:旧送审/批准失效,取消拒绝,本金和占用不变;取代旧轮次后补证重新送审。
  • 最终释放先发生:只消费一次批准并释放一次;之后证据不允许改写已关闭记录。后来银行事实须走独立对账流程,本设计不能证明未来不会出现成功,不声称串行化消除晚到风险。
  • 独立性与权限在送审/批准及最终动作所需环节重查;经办人集合变化使旧送审失效。旧逐事实复核人事后离职本身不抹掉当时有效的批准,新的恢复复核人必须当前合格。

SR5 数据、接口与页面安排(设计约定;实现状态见 implement)

预计新增一个增量迁移:恢复轮次/不可变送审与决定记录、材料修订号、唯一索引及历史保护约束;不得放宽原银行终态或已释放分配的保护。存量不自动补造恢复批准、不自动释放;默认未发起恢复,保留 S3 原门禁。回滚前若已有恢复记录,不能退回只按旧结论释放的代码;停止发布并保留数据,另审兼容方案。

拟接口位于 /payment-batches/:id/loan-release-recoveries:发起、送审、独立复核、撤回、查询。沿现有附件/事实/清单接口补证,最终仍走批次取消接口并传恢复轮次与幂等请求标识。终态材料写入口须验证当前轮次,不提供通用“重开批次”。拟新增原因类别:恢复必需、证据已变化、仍有银行事实未解决、无合格复核人;复用已有原因码优先,新增时同步前后端错误码合同。

S8 还款详情增加“补充释放依据”:并列显示原结论与当前补证/复核/可释放状态、逐提交缺口、失效原因、操作者与证据查看入口。财务与复核人动作分开,服务器仍强制鉴权;详情不能把“批准”显示成“已释放”。PC/手机使用同一组件并实测全流程,敏感字段默认脱敏。界面与对应后端齐备、完成 S0/真实样本/整体验收前不得部署启用。

SR6 验收与后续决策

对应 PRD AC17–AC19,覆盖两种原终态、重复补证、重扫同一流水号、补登第二次提交、多次送审、候选变化、自审/离职、事务回滚、并发交错及禁止重付。关键资金检查做变异测试;必须从真实 HTTP 的上传/核验与复核入口走到取消释放,不能直接调用释放函数代替。只替换云 OCR 响应,使用隔离 PostgreSQL 与合成材料。

批准的核心选择是“原终态不变,新增恢复轮次决定释放资格”;它覆盖 S3 后的补证恢复,不含 S4–S8 的实施。当前代码及验证进展见 implement 顶部;inline 模式不得将主会话自查写成独立复核。

2026-09-17 实施细化

2026-10-06 失败回单归属与银行结果对账方案(第 3 版,待用户审阅,未实施)

第 3 版补充:区分制单导出与银行提交尝试、“从未提交银行”的单独路径(待决)、按原因冻结及误报出口、补记不生成可导出指令。第 2 版根据审阅意见修订:未付款证据须证明指令终止、按付款尝试而非附件数判断、占用与已付分开且超额按差额逐笔计算、晚到成功按冻结快照核对并覆盖“已确认失败未释放”、冻结覆盖后续指令且追回须核实到账。

1. 要解决的问题(现状均已在合成测试或代码中确认)

编号 现状 后果
R1 导出制单或上传回单后状态为 unknown,只有匹配的失败回单能转 confirmed_failed 再取消 未付款或网银导入即失败而无回单时,占用永久不释放,且因在途拦截冻结出借人维护
R2 确认失败要求批次回单总数恰为 1(含作废) 作废一次即永远无法确认失败;同时“附件数”本身也不能代表付款尝试次数
R3 存在同金额候选时确认失败一律拒绝 等额分期任一期真实失败都无法释放
R4 确认失败仍按付款前规则校验出借员工在职 出借员工离职后无法确认失败
R5 confirmed_failed/confirmed_success 为终态,已释放/已结清分配不可改;执行状态要求 confirmed_success 失败结论之后银行晚到成功无处补记;同一本金可能被再次申请并付款

线下对账只能查清银行事实,不能直接解除系统占用。任何释放、补记、追回都必须走下述有依据、有独立复核、有审计的系统流程;不提供“管理员解除占用”,不直接改库。

C(同金额回单归属确认)只防止错误核销,不能防止银行实际重复付款;本方案另设事前冻结(3.5)。

2. 总体原则

  1. 释放占用只能基于“银行对本批次每一次提交都已到达不再执行的终态”的正面证据;“暂时没看到付款”、对账单无支出、等待期届满都不能单独作为依据。唯一例外是 3.2a 的“人工确认未提交”:须满足全部证据与双人复核,记录和页面均标注为人工确认,与“银行确认指令终止”严格区分。
  2. 每条银行事实绑定具体证据及其核验记录,由当前有资格、且不是登记人、导出人、证据上传人、批次创建人、提交人或出借员工的经理/总经理独立复核。
  3. 银行事实登记属付款后环节:按原批次冻结的收付款快照与历史审批身份核对,不要求与出借人当前资料版本一致;只判断当前操作人的权限与独立性。
  4. 历史只增不改:推翻先前结论时新增记录并标记原结论,不回写终态。
  5. 无合格独立复核人时保持占用并显示业务阻塞原因,不降级为单人确认。

3. 方案

3.1 付款尝试与银行事实记录

  • 制单导出记录:每次导出落一条记录(序号、时间、导出人、文件摘要、制单行客户方流水号 批次号-R00n、金额、收付款快照摘要)。重导出沿用同一客户方流水号,所以导出次数不等于向银行提交的次数:下载两次可能只提交一次,下载一次也可能被重复提交。现有 payment_order_export_count 只计数,需落表。
  • 银行提交尝试:由财务登记实际向银行提交的每一次指令(提交时间、渠道、所用导出记录、银行指令号或网银批次号、客户方流水号),并附银行凭据。一次提交关联一条导出记录;一条导出记录可以对应零次、一次或多次提交。登记清单本身也要经独立复核,确认“这就是全部提交”。
  • 银行事实确认:把 loan_receipt_attributions 扩为银行事实确认,新增 kind 与可选 attempt_id:
    • settlement:现有归属确认,含义不变;
    • failure:某次银行提交被拒绝或失败(失败回单),须写明覆盖哪些银行指令,并绑定交易指纹与证据;存在同金额候选时必须有已复核的 failure(R3);
    • terminated:某次银行提交已撤销或拒绝、不再待执行(无回单时的指令终态证据,见 3.2);须写明覆盖的指令,不能以一条指令的终态推定其他提交已结束;
    • not_submitted:导出后从未提交银行(见 3.2a,是否支持待用户决定);
    • late_success:晚到成功,见 3.4。
  • 以上沿用登记、独立复核、失效取代、证据绑定、历史只增不改。

3.2 释放占用的证据门槛(R1、R2)

释放(unknown → 新终态 confirmed_not_paid,或沿用 confirmed_failed 后取消)必须同时满足:

  1. 逐次提交有终态:已复核的银行提交清单中,每一次提交都有已复核、且明确覆盖该指令的 failure 或 terminated 事实;每一条导出记录要么关联了已终止的提交,要么有已复核的 not_submitted 事实(3.2a)。
  2. 终态证据须能唯一定位指令:银行书面回复、网银“指令查询”的官方导出 PDF 等,须载明该尝试的客户方流水号(或银行指令号)及其终态(已拒绝、已撤销、已失败),并表明不再待执行。对账单只能作辅助核对,不能单独证明未付款。截图、口头说明、“网银查不到”一律不接受。
  3. 无未解决的成功或待定事实:作废附件只改变材料使用状态,不抹掉银行事实。曾核验为成功的回单直接阻断释放;曾为待定(处理中、受理)的,须由同一尝试后续的终态证据(失败或撤销)关闭后才不再阻断。
  4. 内部等待期:距最后一次导出满 N 个自然日(建议 3 日)。这只是内部谨慎期,不代表银行时限,也不能替代第 1、2 条。
  5. 独立复核:导出人、证据上传人、登记人不能复核。
  6. 释放后系统禁止该批次再次导出;但 OA 无法让已下载的制单文件在网银中失效,页面仅作提示。此剩余风险由 3.4 晚到成功与 3.5 冻结兜底,不作技术保证表述。

3.2a 只导出、从未提交银行(待用户决定)

这种情况下,银行可能根本没有可出具终态的指令。若本期坚持“银行终态是唯一释放依据”,这类批次将仍然不能释放,R1 只算部分解决。如需支持,规则单列如下,不视为满足银行终态条件:

  • 证据(须全部具备):
    • 网银“指令查询”官方导出 PDF,覆盖首次导出日至登记日,按该客户方流水号及收款账号、金额查询无结果;
    • 同期付款账户对账单,经逐笔核对无对应支出;
    • 导出人书面说明文件去向,以及未提交的原因。
  • 内部等待期满。
  • 双人复核:两名彼此不同、当前有资格的经理或总经理分别独立复核。两人都不能是登记人、导出人、证据上传人、批次创建人、提交人或出借员工。
  • 定性:这是“查无提交”的人工谨慎结论,不是银行保证。数据上记为独立终态 confirmed_not_submitted(区别于银行确认终止的 confirmed_not_paid),页面显示“人工确认未提交”。之后若出现该流水号的成功回单,按 3.4 处理,并另记“未提交结论被推翻”。
  • 实际限制:
    • 需要两名额外的合格复核人,且都不能是登记人、出借人、导出人等相关人员。公司人数少,是否满足尚未核实;人员不足时,这条路径不可用,额度继续占用。
    • 建设银行能否出具“查询无结果”的官方导出 PDF,尚未确认;拿不到时同样继续占用。因此不能宣称“只导出未提交”的所有情况都能解决。

3.3 确认失败的修正(R4)

确认失败改按付款后规则:不要求出借员工当前在职,不要求出借人当前资料版本与提交时一致,改为核对批次冻结快照;当前操作人仍按当前资格与独立性校验。

3.4 晚到成功:补记与差额计算(R5)

触发:已核验的成功回单属于某个已有失败或未付款结论的批次(无论是否已取消释放),并经 late_success 类独立复核确认归属;核对对象是该批次冻结的收付款快照、历史审批身份与交易唯一性认领。

处理步骤:

  1. 推翻原结论:新增事实记录,标记原批次结论“已被银行事实推翻”,并写审计,不回写原终态。
  2. 即时冻结:可信晚到成功一经登记(复核前即生效),冻结该出借人,见 3.5。
  3. 逐笔分配计算:按原批次的原借款分配逐笔处理。对每笔借款 L,设晚到付款分摊到 L 的金额为 a:
    • 其他已付并结清的还款,在 L 上已结清 S;L 的未还本金为 O(已扣除 S)。
    • L 上其他未付款、仅占用的申请属于占用冲突,不是超额。这些申请须先处理:未导出的可取消;已导出或待查证的按 3.2 举证或等待其事实。处理完毕前,L 的补记暂停。
    • 冲突清除后,可补记结清额为 min(a, O),差额 a − min(a, O) 列为对出借人的待追回款。
  4. 补记方式:由于原分配为终态(已释放)或原批次状态受限,补记生成一条关联原批次与该交易的“补记还款”,按上一步计算结果占用并立即结清。若原分配仍为占用(已确认失败但未取消),在同一事务内以“被晚到成功推翻”为原因释放,再由补记还款结清。整个过程受数据库约束“占用加结清不超过未还本金”保护。
    • 数据边界:补记只记录已经发生的银行付款,不生成付款批次、不可导出、不可再次付款。即使整笔都是超额(可结清本金为零),也必须完整记录银行付款金额、交易指纹与待追回金额。
  5. 示例:本金 100 元,晚到成功 80 元。
    • 另一笔新申请占用 70 元、尚未付款:这是占用冲突,暂停该申请的后续付款并处理该占用;处理后补记结清 80 元,剩余本金 20 元。
    • 另一笔已付款并结清 60 元:剩余本金 40 元,补记结清 40 元,另 40 元列为待追回款。

3.5 冻结与解冻

  • 按原因冻结:冻结以“原因记录”为单位,挂在出借人上。每条记录写明原因类型(晚到成功待确认、占用冲突、待追回款)、来源事件、状态(生效或已关闭)以及关闭依据。只要出借人仍有任一生效原因,就处于冻结状态。
  • 冻结时机:可信晚到成功登记时(复核前即生效),或产生占用冲突、待追回款时。
  • 冻结范围:该出借人的新还款申请、其他在途申请的复核与导出(含重新导出)一律拒绝。
  • 不冻结:已发生银行事实的登记、回单上传与核验、事实复核、对账与追回登记。
  • 追回:以银行到账证据(出借人退款入账回单)登记,须独立复核,支持部分追回,逐笔冲减待追回款。本期不支持冲抵后续本金。
  • 原因的出口:
    • 确认为真实晚到成功:完成补记后,占用冲突与待追回款作为新的原因分别处理;晚到原因在补记完成时关闭。
    • 确认为误关联或重复登记(例如回单传错批次、对应的交易已在别处登记):保留原登记记录,经独立复核、附依据后关闭该原因,不补记。
    • 证据仍不确定:原因保持生效,继续冻结。
    • 待追回款:全额实际到账并经复核后关闭;部分追回只冲减金额,不关闭。
  • 解冻:出借人的全部生效原因都已关闭才解冻。不因其中一笔处理完就整体放开;仅“登记了追回结果”也不能关闭原因。

3.6 权限与离职

环节 操作人 复核人
登记付款尝试、失败、终态、晚到成功、追回到账 当前持财务角色和 loan.manage 的人员 当前经理或总经理,且不是登记人、导出人、证据上传人、批次创建人、提交人或出借员工

原审批人、出借员工离职,以及法人或银行停用、出借人资料事后合法变更,都不影响上述环节(均按冻结快照核对)。人员不足时,页面显示具体环节与缺少合格复核人的原因类别。

4. 页面

在还款详情的“银行结果”区,按付款尝试列出每次导出及其事实状态,只显示当前可做的动作:

  • 待查证:登记失败或终态证据(显示内部等待期剩余天数);
  • 全部尝试已终止:取消释放;
  • 已推翻:晚到事件、逐笔补记结果与待追回款;
  • 冻结中:说明原因与解冻条件,提供追回登记入口。

各表单写明证据要求:须能定位具体指令;对账单与时间吻合只能作辅助。

5. 验收(实施时转为 PRD AC)

  1. 只导出未付款:无指令终态证据、也不满足 3.2a 特别复核例外时,等待期满也拒绝;有能定位指令的终态证据并经独立复核后可释放;满足 3.2a 全部证据并经双人复核后,可作为“人工确认未提交”释放,记录与页面显示为人工确认;仅对账单、截图或时间依据被拒;导出人、登记人自审被拒。
  2. 导出与提交分开:多次导出、一次提交,或一次导出、多次提交,都按提交清单逐条举证;一条指令的终态不能证明其他提交已结束;提交清单未经复核即不能释放。若采纳 3.2a:只导出未提交须满足全部证据并经双人复核,否则继续保持占用。
  3. 作废的成功回单持续阻断;作废的待定回单在同一尝试取得终态证据后不再阻断。
  4. 存在同金额候选时,失败经 failure 归属确认后可以释放,否则保持占用。
  5. 离职或出借人资料事后合法变更后,确认失败、终态、晚到成功仍可由当前合格人员完成,并按冻结快照核对。
  6. 晚到成功覆盖四种情况:已释放、已确认失败但未释放、占用冲突(先暂停后补记)、已付冲突(按差额补记加待追回);多借款合并还款逐笔计算;同一笔交易不能用于两次补记或核销。
  7. 冻结按原因管理:覆盖新申请和其他在途申请的复核与导出,但不阻止事实登记;误报的晚到成功经复核关闭原因后不补记;证据不确定时继续冻结;多个原因并存时,只关闭其中一个不会解冻;部分追回不解冻。 8a. 补记不生成可导出指令;整笔超额时补记结清为零,但仍完整记录银行付款与待追回金额。
  8. 全部只增不改、审计完整,不存在单人释放路径;合成全流程测试含确定性并发(终态登记与晚到回单、补记与新申请、冻结与导出),每类关键守卫都有变异测试。

6. 不在本方案内

银行接口直连、对账单自动解析与 OCR、利息、冲抵后续本金、手机端专门优化(沿用共用组件)、生产存量处理(生产是否已有真实还款仍待核实)、部署。

7. 需要用户确认(采纳审阅建议作为默认)

问题 默认
Q1 内部等待期 3 个自然日,仅作内部谨慎期
Q2 证据 按内容判断:须唯一定位指令并证明终态;银行官方导出 PDF 可以;对账单只能辅助
Q3 冻结 冻结新付款与未发出的后续指令,保留事实登记、对账、追回入口
Q4 冲抵 本期只支持实际退款到账
Q5 迁移 由最终数据设计决定(预计包括导出记录、银行提交尝试、事实记录扩展、补记还款、冻结原因、追回记录,以及 confirmed_not_paid、confirmed_not_submitted 两个状态);部署另行批准
Q6 只导出未提交(3.2a) 用户 2026-10-06 确认支持,作为经特别复核的人工例外(全部证据加双人复核);受合格复核人数和银行能否出具查询 PDF 限制,不满足时继续占用

origin_reference作为主体+出借人范围的原借入凭据唯一引用,防止更换幂等键重复登记。期初已还差额必须有adjustment证据。身份与账户分别版本控制,改账户同时撤销身份确认,旧未付快照失效。

新申请持lender→排序loan→日序号锁,只创建本事务尚未可见的新batch;所有既有batch路径先锁batch,核销沿receipt advisory→排序附件→lender/审批身份→排序loan,台账/身份维护不反向锁batch。取消保留旧申请和批次,不原位重提;一申请恰好一个保留批次。下载制单或上传回单转unknown,均不扣减本金。首期不能仅凭理由解除unknown。

借款材料沿现有PDF/图片字节检验,按种类归属借款、随机存储键、内容hash去重、授权下载理由和发送前审计;已确认材料保留,未新增物理删除接口。代账确认引用和四类材料承担本地业务证据门禁,不等同银行真伪核验。

下方“规划/尚未写schema/未运行”的文字为原方案形成时状态,当前状态以implement顶部实测回执为准。

本金归还最小方案(规划,未实施)

1. 复用边界

复用付款账户、批次制单/独立复核、回单存储/核对/交易去重及审计,不复制付款引擎。首期一张申请绑定一个活动批次、批次只有一笔付款;原借入分配保留在申请明细,不拆成两笔银行转账。付款批次复核即本次还款审批,不另接万能工作流;已有报销流程不改。

当前付款来源存在reimbursement/否则按travel_order处理的分支,新增loan_repayment必须逐消费者改为明确支持/拒绝,不能只加枚举。新来源覆盖候选/快照/权限/预检/创建/复核/导出/回单上传、job认领、匹配/人工复核/登记、列表统计和通知深链;未审消费者必须拒绝,不默认套差旅或报销。

2. 最小数据合同

  • 个人出借人记录:公司关系、可选OA员工关联、身份核对状态、加密收款资料及审计。非员工不虚建员工;已分配后的身份/账户变化使未付申请失去就绪资格,不能只改姓名避开自审。
  • 借款记录:公司/出借人/币种、原始本金、已确认未还本金、核对截止日、历史登记标识、原入账/协议证据及确认审计。待确认不能支付,原登记与后续变动均可追溯。
  • 本金还款申请与分配:一对多关联原借款、精确分配金额、事由和提交人;同公司/出借人/币种,合计与唯一付款明细一致。提交时冻结来源版本/收款信息,复核和登记时重验。
  • 付款/审批状态优先由关联批次权威事实投影,不维护第二套可以独自变成已付的流程;会计交接确认单独存储,不等同银行已付。

最终表/字段名、索引与外键在实施前按Prisma现有约定确定。金额用Decimal或最小货币单位,不用浮点累加;活跃分配唯一约束、金额正数/上限及交易指纹占用必须有服务端/数据库保证。数据清理走留痕,不新增批次级联删除来源/交易证据路径。

3. 并发与状态不变量

提交申请在事务中按稳定顺序锁定借款记录,重算已确认未还本金减活动占用;只有余额足够才创建分配及批次。并发同一借款只能占用可用额度,不以页面预检授权。编辑已提交申请须退回/取消原活动付款关系后重新提交,不能改已审快照。

登记路径保留既有批次→交易advisory→附件锁序;涉及多笔借款锁时按稳定ID顺序追加,核各路径不存在反向依赖后才落实现。交易claim、分配核销、付款事实和审计同事务提交;中途异常整体回滚。已付请求重试不重复减款,重复银行交易在新来源及报销来源间共用去重空间。

待复核/已复核未付仅占用本金;银行在途/未知保持占用并显示查证责任,不能为解锁重付而标失败。安全取消或有依据的确定失败才释放额度;已付纠错另审,不回写历史余额掩盖错误。

4. 权限与回单

新台账沿财务全账读取与付款审查分离:财务管理台账,审批人只读其有权审批的申请及必要证据,普通员工无全账入口。制单人、提交人、出借收款人身份集合统一传给提交预检/批次复核/人工回单复核/登记重验;admin通配不能替代独立身份。

2026-10-05 修订(取代原“在职状态和业务权限不吃历史批准”):资格按环节区分。

  • 付款前(新建申请、批次复核、导出制单、确认银行失败):校验当前在职、当前角色/权限、出借人就绪(身份已核实、未归档、法人与银行主数据启用)及出借员工在职。
  • 付款后(回单 OCR 认领、人工回单参与人、核销登记):原审批人与出借员工的资格以审批时为准,不再复核其当前在职/角色,也不再复核法人、银行主数据当前启用状态。理由:银行已实际付出的事实不能因事后人员或主数据变化而无法登记,否则本金永久占用且未还本金多记。仍须满足:身份已核实;身份/账户版本与提交时一致(在途期间维护被 loan.lender_in_flight 阻止);付款快照收款资料一致;reviewed_by/reviewed_at 存在且审批人不是制单人、提交人或出借人关联员工(这三者之间可重合);回单的账号、金额、币种、状态与交易唯一性匹配。审批时资格的依据是复核路由当时已用当前角色校验并写入 reviewed_by/reviewed_at。
  • 当前操作人(上传、人工复核、执行、会计交接)始终按当前权限与独立性校验。

银行备注采用短本金语义,年份不一致时不生成误导性单一年份;长事由留OA。对现有建行制单模板使用显式业务用途映射,原报销用途不变。回单识别范围只有经过新来源快照和权限校验才可扩展,不能无条件对新业务调用腾讯;真实样本/云调用另批,未验证前不宣称自动支持。

自动匹配需金额/币种/完整双方账号/成功状态/唯一交易身份满足;无OCR证据时沿既有双人手工录入复核边界,不把手工值称银行验真。人工复核不覆盖原失败或处理中状态,原件、指纹及版本证据保留;读取账号和原件继续权限/审计/脱敏。

5. 页面与会计边界

财务模块新增借款台账和本金还款入口,复用列表/详情壳、金额/日期格式、附件及下一步投影,保持既有PC/手机样式;不设计新视觉体系。详情显示已确认未还、占用、可还、历史借入分配和会计交接状态,不靠颜色单独表示风险;缺资料/无人可批/银行在途给具体责任提示。

只登记代账核对结果与凭证引用,不选择或生成会计科目、不作税务判断;历史确认和实际银行付款资料由有权人员提供,测试使用合成样例。

6. 验证与发布/回退

隔离DB/HTTP测完整申请→复核→回单→登记→分配核销;覆盖无独立审批人、收款人兼CEO、跨公司、余额并发、失败释放、在途不释放、重复登记、跨业务同交易、来源/账户变化及审计失败。浏览器用真实本地认证和合成数据,不把数据库直接置paid当付款流程通过。

新表和来源枚举属于迁移/权限/状态机变更,必须独立只读审查。新增枚举不保证旧镜像兼容;有新业务数据后不得直接退到仅识别两类来源的旧版,应保留兼容版本或写入隔离后另审前向修复,不删新账/claim“回退”。发布前重新核候选、备份、原密钥保管和相关敏感恢复风险,不沿用旧例外或已有一次演练授权。

7. 2026-09-17 源码消费者地图与技术定稿要求

消费者 已核事实 新来源实施前必须证明
Prisma PaymentBatchEntityType / PaymentBatch 现有两类来源;原有批次/回单/claim关系存在 增量枚举、新来源关系与索引显式约束,旧数据无回写;新增来源出现后旧镜像不作为无条件回退
paymentBatchReadiness.js、paymentBatches.js readiness非报销直接冻结;路由多处报销/否则差旅分支 loan_repayment单独资格与快照适配;未知来源一律拒绝,travel_order继续沿原冻结规则
paymentReceiptVerification.js、paymentReceiptManualPersistence.js 真实核对及人工持久化明确仅报销 新来源独立参与人集合、同一transaction claim去重、版本与成功状态规则;不能只删除reimbursement检查
paymentReceiptOcrJob.js、paymentReceiptMatching.js worker认领与匹配受业务来源限制 新来源eligibility与只读storage边界明确后才允许进入队列;真实云端样本未验另记
client/src/api/paymentBatches.ts、PaymentBatchesPage.tsx 创建按报销,详情部分二选一标签默认差旅 类型/入口/详情/深链/统计显式处理本金还款,保持原报销操作与普通员工权限

拟以LoanLender、CompanyLoan、LoanRepayment、LoanRepaymentAllocation四类核心关系承载出借人、原借入、还款申请和分配;借款材料使用专属证据关系,付款回单继续归原批次。命名和字段尚待T1按Prisma约定定稿,不创建通用财务台账/文件中心。约束至少包括来源版本、单公司/出借人/币种、申请与借款分配唯一、金额精确且为正、证据不级联删除及历史确认可追溯。

锁序定稿必须覆盖创建、重新提交、复核、取消、失败处置、回单登记和余额确认全部写入路径:既有批次先锁batch,再沿原交易advisory/附件顺序,之后按稳定ID锁借款并更新分配;不得存在先锁借款再等待同一既有batch的反向路径。新批次创建在同一事务中的新记录不会成为绕过额度锁的理由;若当前创建器要求反向锁序,应先调整技术方案并审阅,不能边编码边隐藏差异。并发与数据库回滚以真实隔离PG测试证明,mock只覆盖路由输入与调用边界。

8. T1字段与约束定稿草案(2026-09-17,仅本地设计)

本节把前述概念模型具体化为实施合同草案,尚未写Prisma/迁移或启动数据库。金额沿PaymentBatchItem的Decimal(14,2),首期currency_code固定CNY;日期@db.Date,标识UUID,snake_case列名、复数表名、created/updated及操作者沿项目约定。绝不以Number累加核额度。

模型/表 核心字段与不可变事实 约束/索引及删除
LoanLender / loan_lenders id、legal_entity_id、name、employee_id可空、identity_status(unverified/verified)、identity_version、account_version、bank_account_encrypted、bank_name、account_name_encrypted、archived_at FK主体/关联员工Restrict;(legal_entity_id,id)唯一用于复合归属;身份和账户变更递增对应版本及留审计;姓名不作唯一身份;不保存明文账号或密钥摘要
CompanyLoan / company_loans id、loan_no、legal_entity_id、lender_id、currency_code、original_principal、opening_outstanding_principal、received_date、balance_as_of、historical_entry、confirmation_status、version、confirmed_by/at、accounting_confirmation_ref loan_no唯一;主体/出借人复合FK;CHECK 0≤opening_outstanding≤original且original>0、CNY;索引(lender_id,confirmation_status,received_date);确认前不能分配;确认后本金/期初余额不可覆盖改写,纠错另审留存
LoanRepayment / loan_repayments id、repayment_no、legal_entity_id、lender_id、currency_code、reason、amount、version、submitted_by/at、lender_identity_version、lender_account_version、payee_snapshot_json(仅允许加密/脱敏值)、bank_result_state、accounting_handoff_by/at/ref repayment_no唯一;amount>0;CNY;主体/出借人复合FK;bank_result_state仅作为银行结果证据分类,不替代批次审批/付款状态;申请提交后快照不可原位改;会计交接不是银行成功
LoanRepaymentAllocation / loan_repayment_allocations id、repayment_id、loan_id、amount、loan_version、reservation_state(reserved/settled/released)、settled_at、released_at、release_reason (repayment_id,loan_id)唯一,amount>0;FK均Restrict;索引(loan_id,reservation_state);跨行总额和同主体/出借人/币种在锁内检查,不能谎称单行CHECK能保证聚合不超付
LoanEvidence / loan_evidences id、loan_id、kind(agreement/incoming/accounting_confirmation/adjustment)、storage_path、mime_type、file_size、file_sha256、governance_status、uploaded_by/at、archived_at/reason 专属材料关系;loan/uploader FK Restrict;大小/类型沿受控附件合同;同一借款同一hash/kind防重复引用;访问需权限/审计。银行付款回单继续放PaymentBatchReceiptAttachment,不复制OCR/claim体系
既有PaymentBatch增量 entity_type增加loan_repayment;loan_repayment_id可空且FK Restrict,其他来源必须为空 SQL CHECK来源与专属FK一致;对loan_repayment_id建status≠cancelled的部分唯一索引,executed仍占唯一,failed不自动解占;每批恰好一item、entity_id=repayment.id、amount=申请与分配之和由事务及延迟约束触发器验证,迁移原型需证明;旧两来源原数据不改

可用本金=已确认期初未还本金−本系统settled分配−reserved分配;已确认外部历史偿还只体现在期初未还及原证据,不能再次减账。每次提交/执行在CompanyLoan行锁下重算聚合,失败回滚不能留下孤儿claim/分配/审计。发布后修正期初余额需另有可追溯调整流程,不提供直接编辑confirmed字段的API。

活动批次取消后允许同一申请重提时,新建批次并重建新版本分配;原released分配不能覆盖掉历史金额,故首期更简单规则为取消后复制成新申请编号,旧申请/分配/批次保留。禁止对executed申请重新创建批次。批次草稿删除对loan_repayment明确拒绝,使用有理由取消;不能沿原Cascade删除回单/claim链。

9. T1锁图与并发验收(已对照当前源码,待数据库原型)

源码事实:paymentBatches.lockBatchWithItems锁batch;lockPaymentEntities目前reimbursement/否则travel_order;现execute先锁来源实体,再claimVerifiedReceipts;paymentReceiptVerification claim路径先交易advisory再按id锁附件,manualPersistence先batch→交易advisory→attachment。不能直接把新借款塞入原lockPaymentEntities分支并声称满足前节锁序。 新来源execute须显式分派,把借款锁放在现有receipt锁之后;旧两类路径保持原回归边界。

操作 固定锁序/验证 并发/失败退出
创建申请和新批次 lender→按id排序的loan→申请/分配→编号daily sequence advisory→插入本事务新batch;同请求幂等键唯一 在锁内重查确认/余额/版本;创建后不再等待任何已存在batch;两事务竞争同loan只能成功可用额度内的一笔
复核、取消、失败处置 既有batch→lender→排序loan→申请/分配;不取receipt锁的路径不可调用需要它的子流程 重验独立身份/账户版本;只有未送银行或有确认失败证据才释放;failed状态本身不构成释放证据
回单登记 batch→全局receipt transaction advisory→按id附件→lender→排序loan→申请/分配/claim/付款事实/审计 所有写同事务;精确claim去重;审计失败回滚;重复成功登记返回原事实、不再减本金
人工回单复核/OCR完成 继承原batch→advisory→attachment或原已核最小顺序;涉及额度时只能向后取lender/loan 不得由持loan的路径回调此操作;失败/在途回单不可被人工改成成功
出借人修改、余额确认 lender→排序loan;只改来源版本/证据,不锁/更新已有batch 未付资格在下一次预检/复核/登记重验时失效;禁止反向“来源锁→批次锁”广播更新

2026-09-17实施定稿:新申请先取得lender和排序loan锁,再分配编号并插入本事务的新batch;整个创建路径不等待既有batch。既有batch处理/重试不分配新编号,来源维护不反向锁batch。此顺序取代初稿序列锁优先的建议。数据库原型必须覆盖相反loan选择顺序、并行申请总额超过余额、取消与登记竞争、账户变更与复核竞争、同交易跨报销/借款竞争、最后审计抛错回滚、同幂等键重复请求。使用两条真实PG连接和barrier,不能由mock顺序调用替代。

bank_result_state分为not_sent/unknown/confirmed_failed/confirmed_success;新申请未制单可为not_sent,下载后不等于付款成功,也不允许仅凭OA记录仍未付就释放额度。无法证明是否已送银行时保持unknown并阻止重付;解除unknown需有范围的银行结果/未发送确认事实和审计。该状态仅控制风险守卫,已付仍以受核验的批次执行事实为准。

10. T1权限、接口和交付门禁

沿finance.ledger.view管全账读取,新增loan.manage管登记/确认/提交,不默认授予system_admin/普通员工;实际角色种子修改列独立权限审阅。payment.batch.review既有资格加“制单/提交/出借身份集合排除”,admin通配也不免除独立性。employee_id为空且identity_status未verified不得付款,已确认外部非员工不得伪建账号;同一人的多OA身份须先完成真实身份映射,否则不能假定独立。敏感查看沿专用权限与最小投影、审计和原字段密钥。

拟接口/lenders、/company-loans、/loan-repayments分开;创建与确认分离,提交返回关联批次,只通过既有/payment-batches复核/回单/登记完成付款。GET只读无隐式确认。每个写入采用版本检查及request key,409可重读不自动重复付款。界面沿现有样式,新增来源显式标签,不采用“非报销=差旅”默认。

T1文档切片完成;T1数据库约束原型、真实并发验证及独立审阅尚未完成,不勾原8项AC。T2–T4产品实现准入仍取决于本方案审阅和相关敏感恢复风险处置。没有运行Prisma迁移、建本地库、真实OCR、秘密/资料读取或付款。