-- 文件职责:补齐 Tenant 端次卡管理权限与菜单权限绑定(可重复执行)。 -- 执行范围:takeout_identity 数据库(Portal=1,Tenant 端)。 BEGIN; -- 1) 新增/修正营销中心次卡管理权限码 WITH punch_card_permissions(code, name, sort_order) AS ( VALUES ('tenant:marketing:punch-card:view', '查看次卡管理', 36), ('tenant:marketing:punch-card:manage', '管理次卡管理', 37) ), missing AS ( SELECT source.code, source.name, source.sort_order, ROW_NUMBER() OVER (ORDER BY source.sort_order, source.code) AS rn FROM punch_card_permissions source LEFT JOIN public.permissions existing ON existing."Code" = source.code WHERE existing."Id" IS NULL ), base AS ( SELECT COALESCE(MAX("Id"), 820000000000000000) AS max_id FROM public.permissions ) INSERT INTO public.permissions ( "Id", "Name", "Code", "Description", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "ParentId", "SortOrder", "Type", "Portal" ) SELECT base.max_id + missing.rn, missing.name, missing.code, NULL, NOW(), NULL, NULL, NULL, NULL, NULL, 820000000000000005, missing.sort_order, 'leaf', 1 FROM missing CROSS JOIN base; WITH punch_card_permissions(code, name, sort_order) AS ( VALUES ('tenant:marketing:punch-card:view', '查看次卡管理', 36), ('tenant:marketing:punch-card:manage', '管理次卡管理', 37) ) UPDATE public.permissions target SET "Name" = source.name, "ParentId" = 820000000000000005, "SortOrder" = source.sort_order, "Type" = 'leaf', "Portal" = 1, "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW() FROM punch_card_permissions source WHERE target."Code" = source.code; -- 2) 绑定次卡管理菜单的访问权限与按钮权限 UPDATE public.menu_definitions SET "RequiredPermissions" = 'tenant:marketing:punch-card:view', "MetaPermissions" = 'tenant:marketing:punch-card:view,tenant:marketing:punch-card:manage', "AuthListJson" = '[{"title":"管理","authMark":"tenant:marketing:punch-card:manage"}]', "UpdatedAt" = NOW() WHERE "Portal" = 1 AND ("Path" = 'punch-card' OR "Component" = '/marketing/punch-card/index'); -- 3) 给角色模板补齐次卡管理权限(按满减权限映射) WITH code_mapping(source_code, target_code) AS ( VALUES ('tenant:marketing:full-reduction:view', 'tenant:marketing:punch-card:view'), ('tenant:marketing:full-reduction:create', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:update', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:delete', 'tenant:marketing:punch-card:manage') ), candidates AS ( SELECT DISTINCT source."RoleTemplateId", mapping.target_code FROM public.role_template_permissions source INNER JOIN code_mapping mapping ON mapping.source_code = source."PermissionCode" WHERE source."DeletedAt" IS NULL ), missing AS ( SELECT candidate."RoleTemplateId", candidate.target_code, ROW_NUMBER() OVER ( ORDER BY candidate."RoleTemplateId", candidate.target_code ) AS rn FROM candidates candidate LEFT JOIN public.role_template_permissions existing ON existing."RoleTemplateId" = candidate."RoleTemplateId" AND existing."PermissionCode" = candidate.target_code WHERE existing."Id" IS NULL ), base AS ( SELECT COALESCE(MAX("Id"), 820000000000000000) AS max_id FROM public.role_template_permissions ) INSERT INTO public.role_template_permissions ( "Id", "RoleTemplateId", "PermissionCode", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy" ) SELECT base.max_id + missing.rn, missing."RoleTemplateId", missing.target_code, NOW(), NULL, NULL, NULL, NULL, NULL FROM missing CROSS JOIN base; WITH code_mapping(source_code, target_code) AS ( VALUES ('tenant:marketing:full-reduction:view', 'tenant:marketing:punch-card:view'), ('tenant:marketing:full-reduction:create', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:update', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:delete', 'tenant:marketing:punch-card:manage') ) UPDATE public.role_template_permissions target SET "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW() FROM public.role_template_permissions source INNER JOIN code_mapping mapping ON mapping.source_code = source."PermissionCode" WHERE source."RoleTemplateId" = target."RoleTemplateId" AND target."PermissionCode" = mapping.target_code; -- 4) 给租户角色补齐次卡管理权限(按满减权限映射) WITH code_mapping(source_code, target_code) AS ( VALUES ('tenant:marketing:full-reduction:view', 'tenant:marketing:punch-card:view'), ('tenant:marketing:full-reduction:create', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:update', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:delete', 'tenant:marketing:punch-card:manage') ), source_rows AS ( SELECT DISTINCT source."RoleId", source."TenantId", source."Portal", mapping.target_code FROM public.role_permissions source INNER JOIN public.permissions source_permission ON source_permission."Id" = source."PermissionId" INNER JOIN code_mapping mapping ON mapping.source_code = source_permission."Code" WHERE source."DeletedAt" IS NULL AND source."Portal" = 1 ), candidates AS ( SELECT DISTINCT source_row."RoleId", source_row."TenantId", source_row."Portal", target_permission."Id" AS target_permission_id FROM source_rows source_row INNER JOIN public.permissions target_permission ON target_permission."Code" = source_row.target_code ), missing AS ( SELECT candidate."RoleId", candidate."TenantId", candidate."Portal", candidate.target_permission_id, ROW_NUMBER() OVER ( ORDER BY candidate."TenantId", candidate."RoleId", candidate.target_permission_id ) AS rn FROM candidates candidate LEFT JOIN public.role_permissions existing ON existing."RoleId" = candidate."RoleId" AND existing."PermissionId" = candidate.target_permission_id AND existing."Portal" = candidate."Portal" AND ( (existing."TenantId" IS NULL AND candidate."TenantId" IS NULL) OR existing."TenantId" = candidate."TenantId" ) WHERE existing."Id" IS NULL ), base AS ( SELECT COALESCE(MAX("Id"), 830000000000000000) AS max_id FROM public.role_permissions ) INSERT INTO public.role_permissions ( "Id", "RoleId", "PermissionId", "CreatedAt", "UpdatedAt", "DeletedAt", "CreatedBy", "UpdatedBy", "DeletedBy", "TenantId", "Portal" ) SELECT base.max_id + missing.rn, missing."RoleId", missing.target_permission_id, NOW(), NULL, NULL, NULL, NULL, NULL, missing."TenantId", missing."Portal" FROM missing CROSS JOIN base; WITH code_mapping(source_code, target_code) AS ( VALUES ('tenant:marketing:full-reduction:view', 'tenant:marketing:punch-card:view'), ('tenant:marketing:full-reduction:create', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:update', 'tenant:marketing:punch-card:manage'), ('tenant:marketing:full-reduction:delete', 'tenant:marketing:punch-card:manage') ) UPDATE public.role_permissions target SET "DeletedAt" = NULL, "DeletedBy" = NULL, "UpdatedAt" = NOW() FROM public.role_permissions source INNER JOIN public.permissions source_permission ON source_permission."Id" = source."PermissionId" INNER JOIN code_mapping mapping ON mapping.source_code = source_permission."Code" INNER JOIN public.permissions target_permission ON target_permission."Code" = mapping.target_code WHERE source."Portal" = 1 AND target."Portal" = source."Portal" AND target."RoleId" = source."RoleId" AND target."PermissionId" = target_permission."Id" AND ( (target."TenantId" IS NULL AND source."TenantId" IS NULL) OR target."TenantId" = source."TenantId" ); COMMIT;