fix: 财务本人报销由总经理独立审批(09-04-reimbursement-state-gap-finance-view)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-09-12 20:03:29 +08:00
父节点 31ab9fbb2b
当前提交 229867f5fd
共修改 18 个文件,包含 629 行新增和 20 行删除
+22 -7
查看文件
@@ -6,15 +6,16 @@ const path = require("node:path");
module.exports = async function verifyPaymentExperience({
app, prisma, employee, approvers, form, post, origin, tokens, serverRequire, passed, browser, preview, loginPassword, handoffCheck,
payee = employee, fixtureCode = "SYN-PAY",
}) {
app.config.fieldEncryptionKey = randomBytes(32).toString("base64");
app.config.fieldEncryptionKey ??= randomBytes(32).toString("base64");
app.config.paymentBatchEnabled = true;
const { encryptStringOrThrow } = serverRequire("./src/services/crypto");
const company = await prisma.legalEntity.create({ data: { code: "SYN-PAY", name: "合成测试主体" } });
const company = await prisma.legalEntity.create({ data: { code: fixtureCode, name: "合成测试主体" } });
const bank = await prisma.bankInstitution.upsert({
where: { code: "CCB" }, create: { code: "CCB", name: "中国建设银行" }, update: {},
});
await prisma.employee.update({ where: { id: employee.id }, data: {
await prisma.employee.update({ where: { id: payee.id }, data: {
legal_entity_id: company.id, bank_institution_id: bank.id, bank_name: bank.name,
bank_account_encrypted: encryptStringOrThrow(app.config, `6222${"0".repeat(8)}5678`),
} });
@@ -22,7 +23,11 @@ module.exports = async function verifyPaymentExperience({
legal_entity_id: company.id, bank_institution_id: bank.id, account_name: "合成测试主体",
account_number_encrypted: encryptStringOrThrow(app.config, `6217${"0".repeat(8)}1234`),
} });
await prisma.featureFlag.create({ data: { flag_key: "payment_batch_v1", override_mode: "force_on", rollout_type: "global", department_ids: [] } });
await prisma.featureFlag.upsert({
where: { flag_key: "payment_batch_v1" },
create: { flag_key: "payment_batch_v1", override_mode: "force_on", rollout_type: "global", department_ids: [] },
update: {},
});
await handoffCheck?.(approvers.finance, "reimbursement_batch", form.id, 1);
await handoffCheck?.(approvers.ceo, "reimbursement_batch", form.id, 0);
const readProgress = async (actor) => {
@@ -73,7 +78,15 @@ module.exports = async function verifyPaymentExperience({
assert.equal((await readProgress(approvers.finance)).stages.find((stage) => stage.key === "payment_and_receipt").detail,
"已生成银行制单,等待付款完成并上传回单,非审批环节");
}
assert.equal((await readProgress(employee)).stages.some((stage) => stage.targetHref), false);
if (payee.id === employee.id) {
assert.equal((await readProgress(employee)).stages.some((stage) => stage.targetHref), false);
} else {
const unrelatedRead = await fetch(`${origin}/api/reimbursements/${form.id}`, {
headers: { authorization: `Bearer ${tokens.get(employee.id)}` },
signal: AbortSignal.timeout(15000),
});
assert.equal(unrelatedRead.status, 403);
}
const audits = await prisma.auditLog.findMany({ where: { target_id: batch.id, action: { in: ["PAYMENT_ORDER_EXPORTED", "PAYMENT_ORDER_REEXPORTED"] } } });
assert.equal(audits.length, 2);
for (const audit of audits) {
@@ -106,8 +119,10 @@ module.exports = async function verifyPaymentExperience({
const actions = page.getByTestId(mobile ? "payment-batch-mobile-actions" : "payment-batch-action-panel");
await expect(actions.getByRole("button", { name: "上传银行回单" })).toBeVisible();
await actions.getByText("更多", { exact: true }).click();
if (mobile) await page.getByRole("menuitem", { name: "重新下载制单" }).click();
else await actions.getByTestId("payment-batch-action-redownloadOrder").click();
const redownload = page.getByRole("menuitem", { name: "重新下载制单", exact: true });
await expect(redownload).toHaveCount(1);
await expect(redownload).toBeVisible();
await redownload.click();
const dialog = page.getByRole("dialog");
await expect(dialog).toContainText("请勿重复提交");
await expect(dialog.getByRole("textbox")).toHaveCount(0);