using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using TakeoutSaaS.Infrastructure.Identity.Persistence; #nullable disable namespace TakeoutSaaS.Infrastructure.Migrations.IdentityDb; /// /// 写入成本管理菜单与权限定义。 /// [DbContext(typeof(IdentityDbContext))] [Migration("20260305013000_SeedFinanceCostMenuAndPermissions")] public sealed class SeedFinanceCostMenuAndPermissions : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.Sql( """ DO $$ DECLARE v_parent_permission_id bigint; v_view_permission_id bigint; v_manage_permission_id bigint; v_parent_menu_id bigint; v_cost_menu_id bigint; v_permission_seed_base bigint := 840100000000000000; v_menu_seed_base bigint := 850100000000000000; BEGIN -- 1. 确保财务权限分组存在。 SELECT "Id" INTO v_parent_permission_id FROM public.permissions WHERE "Code" = 'group:tenant:finance' ORDER BY "Id" LIMIT 1; IF v_parent_permission_id IS NULL THEN v_parent_permission_id := v_permission_seed_base + 1; INSERT INTO public.permissions ( "Id", "Name", "Code", "Description", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "ParentId", "SortOrder", "Type", "Portal") VALUES ( v_parent_permission_id, '财务中心', 'group:tenant:finance', '财务中心权限分组', NOW(), NULL, NULL, NULL, NULL, NULL, 0, 5000, 'group', 1) ON CONFLICT ("Code") DO NOTHING; END IF; -- 2. Upsert 成本管理查看权限。 INSERT INTO public.permissions ( "Id", "Name", "Code", "Description", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "ParentId", "SortOrder", "Type", "Portal") VALUES ( v_permission_seed_base + 11, '成本管理查看', 'tenant:finance:cost:view', '查看成本录入与成本分析', NOW(), NULL, NULL, NULL, NULL, NULL, v_parent_permission_id, 5110, 'leaf', 1) ON CONFLICT ("Code") DO UPDATE SET "Name" = EXCLUDED."Name", "Description" = EXCLUDED."Description", "ParentId" = EXCLUDED."ParentId", "SortOrder" = EXCLUDED."SortOrder", "Type" = EXCLUDED."Type", "Portal" = EXCLUDED."Portal", "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW(); -- 3. Upsert 成本管理维护权限。 INSERT INTO public.permissions ( "Id", "Name", "Code", "Description", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "ParentId", "SortOrder", "Type", "Portal") VALUES ( v_permission_seed_base + 12, '成本管理维护', 'tenant:finance:cost:manage', '维护成本录入明细与保存数据', NOW(), NULL, NULL, NULL, NULL, NULL, v_parent_permission_id, 5120, 'leaf', 1) ON CONFLICT ("Code") DO UPDATE SET "Name" = EXCLUDED."Name", "Description" = EXCLUDED."Description", "ParentId" = EXCLUDED."ParentId", "SortOrder" = EXCLUDED."SortOrder", "Type" = EXCLUDED."Type", "Portal" = EXCLUDED."Portal", "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW(); -- 4. 回填权限 ID。 SELECT "Id" INTO v_view_permission_id FROM public.permissions WHERE "Code" = 'tenant:finance:cost:view' LIMIT 1; SELECT "Id" INTO v_manage_permission_id FROM public.permissions WHERE "Code" = 'tenant:finance:cost:manage' LIMIT 1; -- 5. 确保租户端财务父菜单存在。 SELECT "Id" INTO v_parent_menu_id FROM public.menu_definitions WHERE "Portal" = 1 AND "Path" = '/finance' AND "DeletedAt" IS NULL ORDER BY "Id" LIMIT 1; IF v_parent_menu_id IS NULL THEN v_parent_menu_id := v_menu_seed_base + 1; INSERT INTO public.menu_definitions ( "Id", "ParentId", "Name", "Path", "Component", "Title", "Icon", "IsIframe", "Link", "KeepAlive", "SortOrder", "RequiredPermissions", "MetaPermissions", "MetaRoles", "AuthListJson", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "Portal") VALUES ( v_parent_menu_id, 0, 'Finance', '/finance', 'BasicLayout', '财务中心', 'lucide:wallet', FALSE, NULL, FALSE, 500, '', '', '', NULL, NOW(), NULL, NULL, NULL, NULL, NULL, 1) ON CONFLICT ("Id") DO NOTHING; END IF; -- 6. Upsert 成本管理菜单。 SELECT "Id" INTO v_cost_menu_id FROM public.menu_definitions WHERE "Portal" = 1 AND ("Path" = '/finance/cost' OR ("Path" = 'cost' AND "Component" = '/finance/cost/index')) ORDER BY "DeletedAt" NULLS FIRST, "Id" LIMIT 1; IF v_cost_menu_id IS NULL THEN v_cost_menu_id := v_menu_seed_base + 11; INSERT INTO public.menu_definitions ( "Id", "ParentId", "Name", "Path", "Component", "Title", "Icon", "IsIframe", "Link", "KeepAlive", "SortOrder", "RequiredPermissions", "MetaPermissions", "MetaRoles", "AuthListJson", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "Portal") VALUES ( v_cost_menu_id, v_parent_menu_id, 'CostManagement', '/finance/cost', '/finance/cost/index', '成本管理', 'lucide:circle-dollar-sign', FALSE, NULL, TRUE, 520, 'tenant:finance:cost:view', 'tenant:finance:cost:view,tenant:finance:cost:manage', '', NULL, NOW(), NULL, NULL, NULL, NULL, NULL, 1) ON CONFLICT ("Id") DO NOTHING; ELSE UPDATE public.menu_definitions SET "ParentId" = v_parent_menu_id, "Name" = 'CostManagement', "Path" = '/finance/cost', "Component" = '/finance/cost/index', "Title" = '成本管理', "Icon" = 'lucide:circle-dollar-sign', "IsIframe" = FALSE, "Link" = NULL, "KeepAlive" = TRUE, "SortOrder" = 520, "RequiredPermissions" = 'tenant:finance:cost:view', "MetaPermissions" = 'tenant:finance:cost:view,tenant:finance:cost:manage', "MetaRoles" = '', "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW(), "Portal" = 1 WHERE "Id" = v_cost_menu_id; END IF; -- 7. 为 tenant-admin 角色授予成本权限。 INSERT INTO public.role_permissions ( "Id", "RoleId", "PermissionId", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "TenantId", "Portal") SELECT ABS(HASHTEXTEXTENDED('tenant-admin:cost:' || role."Id"::text || ':' || permission_id::text, 0)), role."Id", permission_id, NOW(), NULL, NULL, NULL, NULL, NULL, role."TenantId", 1 FROM public.roles role CROSS JOIN LATERAL ( SELECT UNNEST(ARRAY[v_view_permission_id, v_manage_permission_id]) AS permission_id ) item WHERE role."Code" = 'tenant-admin' AND role."DeletedAt" IS NULL AND item.permission_id IS NOT NULL ON CONFLICT ("RoleId", "PermissionId") DO UPDATE SET "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW(), "Portal" = 1; -- 8. 为 tenant-admin 角色模板授予成本权限。 INSERT INTO public.role_template_permissions ( "Id", "RoleTemplateId", "PermissionCode", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy") SELECT ABS(HASHTEXTEXTENDED('template-cost:' || template."Id"::text || ':' || item.permission_code, 0)), template."Id", item.permission_code, NOW(), NULL, NULL, NULL, NULL, NULL FROM public.role_templates template CROSS JOIN LATERAL ( SELECT UNNEST(ARRAY['tenant:finance:cost:view', 'tenant:finance:cost:manage']) AS permission_code ) item WHERE template."TemplateCode" = 'tenant-admin' AND template."DeletedAt" IS NULL ON CONFLICT ("RoleTemplateId", "PermissionCode") DO UPDATE SET "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW(); END $$; """); } /// protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.Sql( """ DO $$ BEGIN DELETE FROM public.role_permissions WHERE "PermissionId" IN ( SELECT "Id" FROM public.permissions WHERE "Code" IN ('tenant:finance:cost:view', 'tenant:finance:cost:manage')); DELETE FROM public.role_template_permissions WHERE "PermissionCode" IN ('tenant:finance:cost:view', 'tenant:finance:cost:manage'); DELETE FROM public.menu_definitions WHERE "Portal" = 1 AND "Path" = '/finance/cost'; DELETE FROM public.permissions WHERE "Code" IN ('tenant:finance:cost:view', 'tenant:finance:cost:manage'); END $$; """); } }