借款出借人线上确认借款并以站内通知直达(09-17-company-loan-principal-repayment)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

- 新增出借人确认声明:财务发起,出借人本人查看原件后确认或退回;快照与决定不可改删,金额、日期、原件或身份变化后整组失效
- 余额确认接受纸质协议或有效线上声明二选一,代账余额核对材料仍必需;声明与公司代表授权分离
- 普通员工无常驻入口,财务发起后仅通知对应出借人并直达确认页
- 新增迁移 20261010010000_loan_lender_acknowledgements(仅新增三表)
- 测试:单测、隔离 HTTP/浏览器、完整借款回归;独立只读复核无阻断;同步发布记录与操作手册

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
2026-10-10 15:22:12 +08:00
共同撰写人 Claude Opus 5.5
父节点 2063ff1e93
当前提交 4a5cd8f2b3
共修改 34 个文件,包含 1610 行新增和 41 行删除
+10
查看文件
@@ -421,6 +421,12 @@ module.exports = async function runLoanHttpFixture(pool, scratch) {
// Incoming-receipt scenarios add lenders; in a full run they go last so they
// cannot shift the pagination other browser scenarios rely on.
const runIncoming = () => require('./company-loan-incoming-fixture.cjs')({ ...employeeHarness, verifiedLender });
const runLenderAck = () => require('./company-loan-lender-ack-fixture.cjs')({ ...employeeHarness, verifiedLender, admin, system });
if (process.env.RUN_ISOLATED_LOAN_ACK_ONLY === '1') {
const lenderAck = await runLenderAck();
if (process.env.RUN_ISOLATED_LOAN_BROWSER === '1') await require('./company-loan-lender-ack-browser.cjs')({ ...employeeHarness, lenderAck });
return;
}
if (process.env.RUN_ISOLATED_LOAN_INCOMING_ONLY === '1') {
const incomingReceipt = await runIncoming();
if (process.env.RUN_ISOLATED_LOAN_BROWSER === '1') await require('./company-loan-incoming-browser.cjs')({ app, finance, otherFinance: await actor(['finance']), password, prisma, config, company, incomingReceipt });
@@ -1402,6 +1408,10 @@ module.exports = async function runLoanHttpFixture(pool, scratch) {
await require('./company-loan-browser.cjs')({ app, finance, manager, ordinary, password, company, bank, lender, loan, config, prisma, attributionUi, reconciliationUi, relatedParty, employeeSources });
}
await runIncoming();
// Keep the new lenders last so existing pagination scenarios retain their
// own deterministic data; the acknowledgement UI handles its own pages.
const lenderAck = await runLenderAck();
if (process.env.RUN_ISOLATED_LOAN_BROWSER === '1') await require('./company-loan-lender-ack-browser.cjs')({ ...employeeHarness, lenderAck });
console.log(JSON.stringify({ stage: 'loan_ledger_http', status: 'PASS', checks }));
} finally { await app.close(); await prisma.$disconnect(); }
};