完善借款、编号、付款与预算并发及验收(09-06-release-gate-integrity)
汇总已落盘的借款本金与还款、兼容历史编号的周期化编号、付款责任与回单核验、报销进度和排序、PWA/采购事务、错误原因与日期校验及ERP退役。 统一共享预算池锁序和锁后判断,恢复差旅原预算选择,补原因码固定夹具及反向完整性检查。 纳入配套迁移、测试、受管QA、分层验收合同、规约及任务记录;原始证据留在ignored artifacts。 关联任务:09-17-company-loan-principal-repayment、09-17-erp-exclusive-retirement、09-18-reimbursement-periodic-numbering、09-08-reimbursement-payment-closeout、09-18-local-concurrency-product-fixes、09-19-budget-pool-concurrency、09-05-error-explainability-payment-readiness。 预算补审由Claude定向验证2文件928项通过,原4446/28及r6结果仍仅对应各自历史输入;本轮未重跑测试。 完整新候选门禁、R1真实入口接入与12项公网义务仍开放。生产编号未启用、差旅仍冻结;不推送、不部署,不宣称发布资格。
这个提交包含在:
@@ -2,6 +2,13 @@ import { expect, test, type Page, type Route } from "@playwright/test";
|
||||
|
||||
import { ADMIN, EMPLOYEE, login } from "./helpers/auth";
|
||||
|
||||
// These APIs are page-level fixtures; a service worker must not bypass them.
|
||||
test.use({ serviceWorkers: "block" });
|
||||
|
||||
// Use the same scenario clock in the simulated API and browser. Wall-clock
|
||||
// passage must not turn the pending-acknowledgement case into an overdue one.
|
||||
const SCENARIO_NOW = new Date("2026-05-28T03:00:00.000Z");
|
||||
|
||||
type MockUserKey = "admin" | "employee";
|
||||
|
||||
type MockAnnouncement = {
|
||||
@@ -71,7 +78,7 @@ function buildMe(user: MockUserKey) {
|
||||
function mapAnnouncementForUser(item: MockAnnouncement, currentUser: MockUserKey) {
|
||||
const me = buildMe(currentUser);
|
||||
const acknowledged = item.acknowledgedEmployeeIds.has(me.id);
|
||||
const overdue = Boolean(item.acknowledgementDueAt && new Date(item.acknowledgementDueAt).getTime() < Date.now());
|
||||
const overdue = Boolean(item.acknowledgementDueAt && new Date(item.acknowledgementDueAt).getTime() < SCENARIO_NOW.getTime());
|
||||
return {
|
||||
...item,
|
||||
acknowledgedEmployeeIds: undefined,
|
||||
@@ -275,16 +282,21 @@ async function clearBrowserSession(page: Page) {
|
||||
});
|
||||
}
|
||||
|
||||
test("制度签收公告:管理员创建、员工签收、管理员看到统计变化", async ({ page }) => {
|
||||
for (const scenario of [
|
||||
{ title: "制度签收公告:管理员创建、员工签收、管理员看到统计变化", dueDate: "2026-06-03", status: "待签收", action: "确认签收" },
|
||||
{ title: "制度签收公告:逾期员工补签后管理员统计同步变化", dueDate: "2026-05-27", status: "已逾期", action: "逾期补签" },
|
||||
]) {
|
||||
test(scenario.title, async ({ page }) => {
|
||||
await page.clock.setFixedTime(SCENARIO_NOW);
|
||||
await mockPolicyAckApis(page);
|
||||
const title = `自动化制度签收 ${Date.now()}`;
|
||||
const title = `自动化制度签收 ${scenario.dueDate}`;
|
||||
|
||||
await login(page, ADMIN);
|
||||
await page.goto("/system/announcements");
|
||||
await page.getByRole("tab", { name: "制度签收" }).click();
|
||||
await page.getByPlaceholder("例如:费用报销制度签收").fill(title);
|
||||
await page.getByPlaceholder("写清楚适用范围、入口和处理要求。").fill("请全员阅读并确认制度签收流程。");
|
||||
await page.locator('input[type="date"]').fill("2026-06-03");
|
||||
await page.locator('input[type="date"]').fill(scenario.dueDate);
|
||||
await page.getByRole("button", { name: "创建制度签收公告" }).click();
|
||||
await expect(page.getByText(title)).toBeVisible();
|
||||
await expect(page.getByText("已签 0/2 · 待签 2")).toBeVisible();
|
||||
@@ -293,9 +305,9 @@ test("制度签收公告:管理员创建、员工签收、管理员看到统
|
||||
await login(page, EMPLOYEE);
|
||||
await page.goto("/announcements");
|
||||
await expect(page.getByText(title)).toBeVisible();
|
||||
await expect(page.getByText("待签收")).toBeVisible();
|
||||
await expect(page.getByText(scenario.status, { exact: true })).toBeVisible();
|
||||
await page.getByLabel("我已阅读并理解该制度内容,确认按公司制度执行。").check();
|
||||
await page.getByRole("button", { name: "确认签收" }).click();
|
||||
await page.getByRole("button", { name: scenario.action, exact: true }).click();
|
||||
await expect(page.getByText("已签收")).toBeVisible();
|
||||
await expect(page.getByText(/完成本人签收/)).toBeVisible();
|
||||
|
||||
@@ -305,3 +317,4 @@ test("制度签收公告:管理员创建、员工签收、管理员看到统
|
||||
await expect(page.getByText(title)).toBeVisible();
|
||||
await expect(page.getByText("已签 1/2 · 待签 1")).toBeVisible();
|
||||
});
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户