diff --git a/deploy/postgres/README.md b/deploy/postgres/README.md index 4305552..c72d800 100644 --- a/deploy/postgres/README.md +++ b/deploy/postgres/README.md @@ -11,6 +11,7 @@ - `seed_tenant_punch_card_permissions.sql`:补齐租户端次卡管理权限码、菜单权限与角色授权映射(可重复执行)。 - `seed_tenant_calendar_permissions.sql`:补齐租户端营销日历权限码、菜单权限与角色授权映射(可重复执行)。 - `seed_tenant_customer_permissions.sql`:补齐租户端客户管理权限码、菜单权限与角色授权映射(可重复执行)。 +- `seed_tenant_member_permissions.sql`:补齐租户端会员管理权限码、菜单权限与角色授权映射(可重复执行)。 ## 前置条件 @@ -113,6 +114,20 @@ psql -h -p -U identity_user -d takeout_identity_db -f .\seed_tenan 2. 更新客户菜单 (`/customer/list|profile|analysis`) 的 `RequiredPermissions`、`MetaPermissions` 与 `AuthListJson`。 3. 按订单列表权限映射补齐客户列表(view/manage)与客户画像(profile/view)角色模板和租户角色授权;`analysis` 不做角色映射。 +## 会员管理权限补齐 + +在 `takeout_identity_db` 执行: + +```powershell +psql -h -p -U identity_user -d takeout_identity_db -f .\seed_tenant_member_permissions.sql +``` + +脚本会完成: + +1. 新增/修正 `tenant:member:*` 权限码(view/manage)。 +2. 更新会员管理菜单 (`/member/list/index`) 的 `RequiredPermissions`、`MetaPermissions` 与 `AuthListJson`。 +3. 按订单列表权限映射补齐会员管理权限的角色模板与租户角色授权。 + ## 常见问题 | 问题 | 处理方式 | diff --git a/deploy/postgres/seed_tenant_member_permissions.sql b/deploy/postgres/seed_tenant_member_permissions.sql new file mode 100644 index 0000000..b6883da --- /dev/null +++ b/deploy/postgres/seed_tenant_member_permissions.sql @@ -0,0 +1,281 @@ +-- 文件职责:补齐 Tenant 端会员管理权限与菜单权限绑定(可重复执行)。 +-- 执行范围:takeout_identity 数据库(Portal=1,Tenant 端)。 + +BEGIN; + +-- 1) 新增/修正会员管理权限码 +WITH member_permissions(code, name, sort_order) AS ( + VALUES + ('tenant:member:view', '查看会员管理', 44), + ('tenant:member:manage', '管理会员管理', 45) +), +missing AS ( + SELECT + source.code, + source.name, + source.sort_order, + ROW_NUMBER() OVER (ORDER BY source.sort_order, source.code) AS rn + FROM member_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 +), +parent AS ( + SELECT COALESCE( + ( + SELECT "ParentId" + FROM public.permissions + WHERE "Code" = 'tenant:order:list:view' + LIMIT 1 + ), + 820000000000000004 + ) AS parent_id +) +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, + parent.parent_id, + missing.sort_order, + 'leaf', + 1 +FROM missing +CROSS JOIN base +CROSS JOIN parent; + +WITH member_permissions(code, name, sort_order) AS ( + VALUES + ('tenant:member:view', '查看会员管理', 44), + ('tenant:member:manage', '管理会员管理', 45) +), +parent AS ( + SELECT COALESCE( + ( + SELECT "ParentId" + FROM public.permissions + WHERE "Code" = 'tenant:order:list:view' + LIMIT 1 + ), + 820000000000000004 + ) AS parent_id +) +UPDATE public.permissions target +SET + "Name" = source.name, + "ParentId" = parent.parent_id, + "SortOrder" = source.sort_order, + "Type" = 'leaf', + "Portal" = 1, + "DeletedAt" = NULL, + "DeletedBy" = NULL, + "UpdatedAt" = NOW() +FROM member_permissions source +CROSS JOIN parent +WHERE target."Code" = source.code; + +-- 2) 绑定会员管理菜单权限 +UPDATE public.menu_definitions +SET + "RequiredPermissions" = 'tenant:member:view', + "MetaPermissions" = 'tenant:member:view,tenant:member:manage', + "AuthListJson" = '[{"title":"编辑","authMark":"tenant:member:manage"}]', + "UpdatedAt" = NOW() +WHERE + "Portal" = 1 + AND ("Name" = 'MemberMgmt' OR "Component" = '/member/list/index'); + +UPDATE public.menu_definitions +SET + "RequiredPermissions" = 'tenant:member:view', + "MetaPermissions" = 'tenant:member:view,tenant:member:manage', + "AuthListJson" = NULL, + "UpdatedAt" = NOW() +WHERE + "Portal" = 1 + AND ("Name" = 'Member' OR "Path" = '/member'); + +-- 3) 给角色模板补齐会员管理权限(按订单列表权限映射) +WITH code_mapping(source_code, target_code) AS ( + VALUES + ('tenant:order:list:view', 'tenant:member:view'), + ('tenant:order:list:update', 'tenant:member: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:order:list:view', 'tenant:member:view'), + ('tenant:order:list:update', 'tenant:member: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:order:list:view', 'tenant:member:view'), + ('tenant:order:list:update', 'tenant:member: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:order:list:view', 'tenant:member:view'), + ('tenant:order:list:update', 'tenant:member: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;