收口导航与报销审批入口(05-30-nav-reimbursement-approval-surface)
这个提交包含在:
@@ -124,7 +124,6 @@ const FEATURE_FLAG_SNAPSHOT_SCHEMA = {
|
||||
};
|
||||
|
||||
const BACKUP_NAVIGATION_KEYS = new Set([
|
||||
"purchaseRequests",
|
||||
"travelRequests",
|
||||
"budgets",
|
||||
"paymentBatches",
|
||||
|
||||
@@ -310,7 +310,8 @@ async function ensureWorkspaceSetting(prisma) {
|
||||
systemSettings: "admin",
|
||||
featureFlags: "admin",
|
||||
auditLogs: "admin",
|
||||
purchaseRequests: "admin",
|
||||
contractsRegistry: "main",
|
||||
purchaseRequests: "main",
|
||||
travelRequests: "admin",
|
||||
budgets: "admin",
|
||||
paymentBatches: "admin",
|
||||
|
||||
@@ -157,7 +157,8 @@ async function ensureWorkspaceSetting(prisma) {
|
||||
systemSettings: "admin",
|
||||
featureFlags: "admin",
|
||||
auditLogs: "admin",
|
||||
purchaseRequests: "admin",
|
||||
contractsRegistry: "main",
|
||||
purchaseRequests: "main",
|
||||
travelRequests: "admin",
|
||||
budgets: "admin",
|
||||
paymentBatches: "admin",
|
||||
@@ -191,7 +192,8 @@ async function ensureWorkspaceSetting(prisma) {
|
||||
systemSettings: "admin",
|
||||
featureFlags: "admin",
|
||||
auditLogs: "admin",
|
||||
purchaseRequests: "admin",
|
||||
contractsRegistry: "main",
|
||||
purchaseRequests: "main",
|
||||
travelRequests: "admin",
|
||||
budgets: "admin",
|
||||
paymentBatches: "admin",
|
||||
|
||||
@@ -17,6 +17,7 @@ const FINANCE_ROLE_CODES = new Set(["finance", "finance_mgr"]);
|
||||
const TEAM_NAVIGATION_ROLE_CODES = new Set(["manager", "ceo", "finance_mgr", "hr", "admin"]);
|
||||
const FINANCE_PERMISSION_CODES = Object.freeze(["payment.batch.manage", "risk.review.manage", "expense.finance.pay"]);
|
||||
const FINANCE_NAVIGATION_MODULES = new Set(["paymentBatches", "apOperations", "invoicePool"]);
|
||||
const DAY_TO_DAY_BUSINESS_MODULES = new Set(["assets", "contractsRegistry", "purchaseRequests", "projects"]);
|
||||
const MANAGEMENT_CHILD_MODULES = new Set([
|
||||
"workspace",
|
||||
"people",
|
||||
@@ -33,11 +34,8 @@ const MANAGEMENT_CHILD_MODULES = new Set([
|
||||
"erpIntegrations",
|
||||
]);
|
||||
const BACKUP_NAVIGATION_MODULES = new Set([
|
||||
"assets",
|
||||
"weeklyReports",
|
||||
"announcements",
|
||||
"contractsRegistry",
|
||||
"purchaseRequests",
|
||||
"travelRequests",
|
||||
"budgets",
|
||||
"inventoryChecks",
|
||||
@@ -48,20 +46,20 @@ const NAVIGATION_SECTION_ORDER = Object.freeze({
|
||||
"portal",
|
||||
"workflowTasks",
|
||||
"reimbursements",
|
||||
"purchaseRequests",
|
||||
"contractsRegistry",
|
||||
"projects",
|
||||
"assets",
|
||||
"paymentBatches",
|
||||
"apOperations",
|
||||
"invoicePool",
|
||||
"projects",
|
||||
"team",
|
||||
"leaveRequests",
|
||||
],
|
||||
admin: ["systemSettings"],
|
||||
backup: [
|
||||
"assets",
|
||||
"weeklyReports",
|
||||
"announcements",
|
||||
"purchaseRequests",
|
||||
"contractsRegistry",
|
||||
"budgets",
|
||||
"attendance",
|
||||
"travelRequests",
|
||||
@@ -80,7 +78,7 @@ const NAVIGATION_REGISTRY = Object.freeze({
|
||||
weeklyReports: { key: "weeklyReports", label: "周报", icon: "article", href: "/weekly-reports", anyOf: [], featureFlagKey: FEATURE_FLAG_KEYS.weeklyReport },
|
||||
todos: { key: "todos", label: "待办", icon: "check_circle", href: "/todos", anyOf: [], featureFlagKey: FEATURE_FLAG_KEYS.todoBoard },
|
||||
announcements: { key: "announcements", label: "公告", icon: "campaign", href: "/announcements", anyOf: [], featureFlagKey: FEATURE_FLAG_KEYS.announcements },
|
||||
projects: { key: "projects", label: "项目", icon: "workspaces", href: "/projects", anyOf: ["project.view_all", "project.manage"], featureFlagKey: FEATURE_FLAG_KEYS.projectDomain },
|
||||
projects: { key: "projects", label: "项目", icon: "workspaces", href: "/projects", anyOf: ["project.view_own", "project.view_all", "project.manage"], featureFlagKey: FEATURE_FLAG_KEYS.projectDomain },
|
||||
|
||||
workspace: { key: "workspace", label: "工作区设置", icon: "tune", href: "/system/workspace", anyOf: ["system.settings"] },
|
||||
people: { key: "people", label: "人员管理", icon: "group", href: "/people", anyOf: ["system.users", "report.dashboard.view"], featureFlagKey: FEATURE_FLAG_KEYS.employeeLifecycle },
|
||||
@@ -116,7 +114,7 @@ const DEFAULT_MODULE_VISIBILITY = Object.freeze({
|
||||
leaveRequests: "main",
|
||||
attendance: "hidden",
|
||||
reimbursements: "main",
|
||||
assets: "admin",
|
||||
assets: "main",
|
||||
weeklyReports: "admin",
|
||||
todos: "hidden",
|
||||
announcements: "admin",
|
||||
@@ -125,7 +123,7 @@ const DEFAULT_MODULE_VISIBILITY = Object.freeze({
|
||||
workspace: "admin",
|
||||
people: "admin",
|
||||
organization: "admin",
|
||||
contractsRegistry: "admin",
|
||||
contractsRegistry: "main",
|
||||
workflowDefinitions: "admin",
|
||||
systemSettings: "admin",
|
||||
featureFlags: "admin",
|
||||
@@ -138,7 +136,7 @@ const DEFAULT_MODULE_VISIBILITY = Object.freeze({
|
||||
notificationChannels: "admin",
|
||||
workflowTasks: "admin",
|
||||
dashboard: "hidden",
|
||||
purchaseRequests: "admin",
|
||||
purchaseRequests: "main",
|
||||
travelRequests: "admin",
|
||||
budgets: "admin",
|
||||
paymentBatches: "admin",
|
||||
@@ -282,6 +280,10 @@ function resolveNavigationSection({ moduleKey, placement, financeNavigation }) {
|
||||
return financeNavigation ? "main" : null;
|
||||
}
|
||||
|
||||
if (DAY_TO_DAY_BUSINESS_MODULES.has(moduleKey)) {
|
||||
return "main";
|
||||
}
|
||||
|
||||
if (BACKUP_NAVIGATION_MODULES.has(moduleKey)) {
|
||||
return "backup";
|
||||
}
|
||||
|
||||
@@ -65,10 +65,15 @@ describe("workspace small-team navigation defaults", () => {
|
||||
"team",
|
||||
"leaveRequests",
|
||||
"reimbursements",
|
||||
"assets",
|
||||
"projects",
|
||||
"contractsRegistry",
|
||||
"purchaseRequests",
|
||||
]);
|
||||
expect(DEFAULT_MODULE_VISIBILITY.todos).toBe("hidden");
|
||||
expect(DEFAULT_MODULE_VISIBILITY.assets).toBe("admin");
|
||||
expect(DEFAULT_MODULE_VISIBILITY.assets).toBe("main");
|
||||
expect(DEFAULT_MODULE_VISIBILITY.contractsRegistry).toBe("main");
|
||||
expect(DEFAULT_MODULE_VISIBILITY.purchaseRequests).toBe("main");
|
||||
expect(DEFAULT_MODULE_VISIBILITY.attendance).toBe("hidden");
|
||||
});
|
||||
|
||||
@@ -103,19 +108,19 @@ describe("workspace small-team navigation defaults", () => {
|
||||
|
||||
const navigation = await getSystemNavigation({
|
||||
prisma: buildPrisma(["presence_board_v1", "project_domain_v1"]),
|
||||
config: buildConfig(),
|
||||
config: { ...buildConfig(), projectDomainEnabled: true },
|
||||
employee,
|
||||
hasPermission: (candidate, permissionCode) => hasPermission(candidate.permissionCodes, permissionCode),
|
||||
});
|
||||
|
||||
const mainLabels = navigation.sections.main.map((item) => item.label);
|
||||
expect(mainLabels).toEqual(["工作台", "报销", "请假记录"]);
|
||||
expect(mainLabels).toEqual(["工作台", "报销", "采购申请", "项目", "资产", "请假记录"]);
|
||||
expect(mainLabels).not.toContain("待我处理");
|
||||
expect(mainLabels).not.toContain("票据");
|
||||
expect(mainLabels).not.toContain("个人设置");
|
||||
|
||||
const backupKeys = navigation.sections.backup.map((item) => item.key);
|
||||
expect(backupKeys).toContain("purchaseRequests");
|
||||
expect(backupKeys).not.toContain("purchaseRequests");
|
||||
expect(backupKeys).not.toContain("travelRequests");
|
||||
expect(backupKeys).not.toContain("invoicePool");
|
||||
expect(backupKeys).not.toContain("contractsRegistry");
|
||||
@@ -135,8 +140,8 @@ describe("workspace small-team navigation defaults", () => {
|
||||
};
|
||||
|
||||
const managerNavigation = await getSystemNavigation({
|
||||
prisma: buildPrisma(["presence_board_v1", "project_domain_v1"]),
|
||||
config: { ...buildConfig(), projectDomainEnabled: true, presenceBoardEnabled: true },
|
||||
prisma: buildPrisma(["presence_board_v1", "project_domain_v1", "project_linking_v1"]),
|
||||
config: { ...buildConfig(), projectDomainEnabled: true, projectLinkingEnabled: true, presenceBoardEnabled: true },
|
||||
employee: manager,
|
||||
hasPermission: (candidate, permissionCode) => hasPermission(candidate.permissionCodes, permissionCode),
|
||||
});
|
||||
@@ -145,7 +150,10 @@ describe("workspace small-team navigation defaults", () => {
|
||||
"工作台",
|
||||
"待我处理",
|
||||
"报销",
|
||||
"采购申请",
|
||||
"合同台账",
|
||||
"项目",
|
||||
"资产",
|
||||
"团队",
|
||||
"请假记录",
|
||||
]);
|
||||
|
||||
在新工单中引用
屏蔽一个用户