feat(P25-1/P25-5/P26-1/P26-3/P24-1/P29-4): 落地内部OA够用版后端与试运行能力

关联 Issue: P25-1, P25-2, P25-3, P25-4, P25-5, P26-1, P26-3, P24-1, P24-2, P29-1, P29-2, P29-3, P29-4
这个提交包含在:
2026-03-21 18:03:20 +08:00
父节点 9b7cd818f7
当前提交 e39e41287e
共修改 45 个文件,包含 4571 行新增和 328 行删除
+110
查看文件
@@ -233,6 +233,70 @@ const DEFAULT_FEATURE_FLAGS = [
department_ids: [],
note: "bootstrap default: force_off",
},
{
flag_key: "budget_precheck_v1",
override_mode: "force_off",
rollout_type: "global",
department_ids: [],
note: "bootstrap default: force_off",
},
{
flag_key: "payment_batch_v1",
override_mode: "force_off",
rollout_type: "global",
department_ids: [],
note: "bootstrap default: force_off",
},
{
flag_key: "portal_home_v1",
override_mode: "force_off",
rollout_type: "global",
department_ids: [],
note: "bootstrap default: force_off",
},
{
flag_key: "global_search_v1",
override_mode: "force_off",
rollout_type: "global",
department_ids: [],
note: "bootstrap default: force_off",
},
{
flag_key: "announcements_v1",
override_mode: "force_off",
rollout_type: "global",
department_ids: [],
note: "bootstrap default: force_off",
},
{
flag_key: "workflow_definition_admin_v1",
override_mode: "force_off",
rollout_type: "global",
department_ids: [],
note: "bootstrap default: force_off",
},
{
flag_key: "cutover_console_v1",
override_mode: "force_off",
rollout_type: "global",
department_ids: [],
note: "bootstrap default: force_off",
},
];
const DEFAULT_BUDGET_CONTROL_RULES = [
{
name: "默认全局预算预警",
entity_type: "all",
department_id: null,
legal_entity_id: null,
cost_center_id: null,
expense_type_id: null,
control_mode: "warn",
priority: 100,
enabled: true,
notes: "bootstrap default global warn rule",
},
];
const DEFAULT_LEAVE_TYPES = [
@@ -411,6 +475,51 @@ async function seedFeatureFlags(prisma) {
}
}
async function seedBudgetControlRules(prisma) {
const now = new Date();
for (const item of DEFAULT_BUDGET_CONTROL_RULES) {
const existing = await prisma.budgetControlRule.findFirst({
where: {
name: item.name,
entity_type: item.entity_type,
archived_at: null,
},
select: { id: true },
});
if (existing) {
await prisma.budgetControlRule.update({
where: { id: existing.id },
data: {
department_id: item.department_id,
legal_entity_id: item.legal_entity_id,
cost_center_id: item.cost_center_id,
expense_type_id: item.expense_type_id,
control_mode: item.control_mode,
priority: item.priority,
enabled: item.enabled,
notes: item.notes,
archived_at: null,
updated_at: now,
updated_by: null,
},
});
continue;
}
await prisma.budgetControlRule.create({
data: {
...item,
created_at: now,
created_by: null,
updated_at: now,
updated_by: null,
},
});
}
}
async function seedLeaveTypes(prisma) {
const now = new Date();
@@ -608,6 +717,7 @@ async function main() {
await seedWorkflowDefinition(prisma);
await seedLeaveTypes(prisma);
await seedFeatureFlags(prisma);
await seedBudgetControlRules(prisma);
// eslint-disable-next-line no-console
console.log("Seeded config data:");