|
@@ -0,0 +1,103 @@
|
|
|
|
|
+-- ============================================================================
|
|
|
|
|
+-- 乐收赢 · 把「银联收单」目录下的三个**只读**页面补授给租户角色(role_id = 2)
|
|
|
|
|
+--
|
|
|
|
|
+-- 【本脚本尚未执行】执行由用户做。执行前请先读下面「★ 为什么补」与「★ 你可以否掉哪一条」。
|
|
|
|
|
+--
|
|
|
|
|
+-- 交付日期:2026-09-28
|
|
|
|
|
+-- 背景批次:收银台(扫码收款)页面联调。执行完 `lsy-cashier-menu.sql` 之后,
|
|
|
|
|
+-- 租户角色拿到了「银联收单 → 扫码收款」,但**看不到**同目录下的
|
|
|
|
|
+-- 支付订单 / 退款记录 / 商户映射 —— 本脚本补上。
|
|
|
|
|
+-- ============================================================================
|
|
|
|
|
+--
|
|
|
|
|
+-- ── ★ 为什么补:三条实测,不是推测 ─────────────────────────────────────────
|
|
|
|
|
+--
|
|
|
|
|
+-- 1) 活库只读实测(2026-09-28,`GET /system/role/detail/2` 递归遍历):
|
|
|
|
|
+-- 角色 2(租户角色,17 个用户持有)持 54 个菜单,**268/269/270/271/272 一个都没有**;
|
|
|
|
|
+-- 同法量角色 1(管理员角色):120 个菜单,五个 id 全有。
|
|
|
|
|
+-- ⇒ 两向读数,量具能分辨,不是「查不出来」。
|
|
|
|
|
+--
|
|
|
|
|
+-- 2) 文档记的**原本**形态是两个角色都有:`lsy-onboarding-menu.sql:105` 写
|
|
|
|
|
+-- 「「收付款」目录(id=268)与三个 lsy 兄弟页(269/270/271)**也都授给了两个角色**」。
|
|
|
|
|
+-- (`lsy-menu.sql` 自己那句「授权给 role_id = 1」是它初版写的,对不上活库现状 ——
|
|
|
|
|
+-- 同一份脚本第 141 行也承认了这一点。)
|
|
|
|
|
+-- ★ 成因**未定,不猜**:可能是有人改过角色配置,也可能是
|
|
|
|
|
+-- 「角色详情不带授权 ⇒ 抽屉全不勾且保存清空授权」那个缺陷(`1bda59a`,2026-09-28 才修)
|
|
|
|
|
+-- 期间被谁点过一次保存。两种都不改变本脚本要恢复的目标形态。
|
|
|
|
|
+--
|
|
|
|
|
+-- 3) 界面文案**要求**租户去那一页:收银台在没有商户号时抛
|
|
|
|
|
+-- 「该租户未配置商户号,请先在「手工登记商户号」中登记」
|
|
|
|
|
+-- (`LsyMerchantService.requireByTenant`)。而「手工登记商户号」正是
|
|
|
|
|
+-- `route_name = 'CollectionMerchant'` 那一页改名后的名字。
|
|
|
|
|
+-- ⇒ 租户没有这一页时,这句话是**一条死路**:它指的地方租户进不去。
|
|
|
|
|
+--
|
|
|
|
|
+-- ── ★ 你可以否掉哪一条 ────────────────────────────────────────────────────
|
|
|
|
|
+--
|
|
|
|
|
+-- 前两页(支付订单 / 退款记录)是**纯读**:控制器只有 `GET /page` 与 `GET /{...}`,
|
|
|
|
|
+-- 没有写端点,租户看到的是自己租户的行(实体继承 PaymentTenantBaseEntity,租户拦截器追加条件)。
|
|
|
|
|
+--
|
|
|
|
|
+-- **第三页(商户映射)是唯一有写权限的**,所以单独说明,你可以只删这一段:
|
|
|
|
|
+-- · 该页三个端点(page / save / delete)**共用同一个权限串**
|
|
|
|
|
+-- `module_payment:leshouying:merchant:list` ⇒ 授了页面就等于授了新增与删除;
|
|
|
|
|
+-- · 新增时归属被强制取自认证上下文(`LeshouyingMerchantController.save` 里
|
|
|
|
|
+-- `entity.setTenantId(null)`),请求体里写 tenant_id 无效;
|
|
|
|
|
+-- · `uk_lsy_merchant_mch_no` 是 **mch_no 全局唯一**索引 ⇒ 别人已登记的商户号抢不走。
|
|
|
|
|
+-- · 残余风险(我认为可接受,但这是判断):租户可以登记一个**尚无人登记**的商户号。
|
|
|
|
|
+-- 最坏后果是让那个商户号的账户收到本租户顾客的钱(钱进的是对方账户),
|
|
|
|
|
+-- 以及**占位**(该号之后别人登记不了,需管理员 delete 释放)。
|
|
|
|
|
+-- · 若你不接受这一点:把本文件里 `CollectionMerchant` 那一行从 `pages` 的 VALUES 中删掉再执行,
|
|
|
|
|
+-- 并把上面第 3 条的文案改成「请联系平台管理员开通」。
|
|
|
|
|
+--
|
|
|
|
|
+-- ── ★ 幂等 ────────────────────────────────────────────────────────────────
|
|
|
|
|
+--
|
|
|
|
|
+-- 末条 INSERT 逐行 `NOT EXISTS`:**重跑不插重复行,也不报错**。
|
|
|
|
|
+-- 与 `lsy-cashier-menu.sql` 不同,本脚本**不依赖任何 CTE 的非空性** ——
|
|
|
|
|
+-- 三个页面若已被手工删除,本脚本只授它找得到的行,不会去重建页面(重建请重跑 `lsy-menu.sql`,
|
|
|
|
|
+-- 但那份脚本在「目录在、页面被删」时也不会恢复,见它自己的注释)。
|
|
|
|
|
+--
|
|
|
|
|
+-- ── ★ 只读核对(执行后跑这三条)────────────────────────────────────────────
|
|
|
|
|
+--
|
|
|
|
|
+-- 1) 目录与三个页面在不在、route_name 是什么(锚点用身份,不用会变的 name):
|
|
|
|
|
+-- SELECT id, name, type, route_name, route_path, status
|
|
|
|
|
+-- FROM sys_menu
|
|
|
|
|
+-- WHERE route_name IN ('Collection','CollectionOrder','CollectionRefund','CollectionMerchant')
|
|
|
|
|
+-- ORDER BY id;
|
|
|
|
|
+-- 期望:**4 行**,status 全 '0'。(本次实测 id:268 目录 / 269 / 270 / 271,
|
|
|
|
|
+-- 但 id 不是锚点,别把它当判据。)
|
|
|
|
|
+--
|
|
|
|
|
+-- 2) 授权行:
|
|
|
|
|
+-- SELECT rm.role_id, m.name, m.permission
|
|
|
|
|
+-- FROM sys_role_menus rm JOIN sys_menu m ON m.id = rm.menu_id
|
|
|
|
|
+-- WHERE m.route_name IN ('Collection','CollectionOrder','CollectionRefund','CollectionMerchant')
|
|
|
|
|
+-- ORDER BY m.id, rm.role_id;
|
|
|
|
|
+-- 期望:role 1 与 role 2 **各 4 行 = 共 8 行**。
|
|
|
|
|
+--
|
|
|
|
|
+-- 3) 端到端(界面):以租户账号重新登录 ⇒ 「银联收单」下应出现 4 个页面。
|
|
|
|
|
+-- ★ 必须**重新登录**:路由与权限来自登录时下发的 user 快照,不重登看不到变化。
|
|
|
|
|
+--
|
|
|
|
|
+-- ── ★ 收回 ────────────────────────────────────────────────────────────────
|
|
|
|
|
+--
|
|
|
|
|
+-- DELETE FROM sys_role_menus
|
|
|
|
|
+-- WHERE role_id = 2
|
|
|
|
|
+-- AND menu_id IN (SELECT id FROM sys_menu
|
|
|
|
|
+-- WHERE route_name IN ('Collection','CollectionOrder',
|
|
|
|
|
+-- 'CollectionRefund','CollectionMerchant'));
|
|
|
|
|
+-- ★ 收回**目录行**(`route_name='Collection'`)才是让整块从角色 2 视野里消失的那一下 ——
|
|
|
|
|
+-- `UserService.buildMenuTree` 对「父不在集合里」的子节点是**静默丢弃**(无 else 分支,不报错)。
|
|
|
|
|
+-- ★ 若只想收回商户映射一页,把上面 IN 列表里的 'CollectionMerchant' 去掉即可;
|
|
|
|
|
+-- 但**不要**连 'Collection' 一起收回,否则另外两页也会一起消失。
|
|
|
|
|
+-- ============================================================================
|
|
|
|
|
+
|
|
|
|
|
+-- 目录 + 三个页面,一次算出要授的 menu_id 集合。锚 route_name(身份),不锚 name(标签)。
|
|
|
|
|
+WITH pages AS (
|
|
|
|
|
+ SELECT id FROM sys_menu
|
|
|
|
|
+ WHERE route_name IN ('CollectionOrder', 'CollectionRefund', 'CollectionMerchant')
|
|
|
|
|
+ AND type = 2 AND status = '0'
|
|
|
|
|
+ UNION ALL
|
|
|
|
|
+ SELECT id FROM sys_menu
|
|
|
|
|
+ WHERE route_name = 'Collection' AND type = 1 AND status = '0'
|
|
|
|
|
+)
|
|
|
|
|
+INSERT INTO sys_role_menus (role_id, menu_id)
|
|
|
|
|
+SELECT 2, p.id
|
|
|
|
|
+ FROM pages p
|
|
|
|
|
+ WHERE NOT EXISTS (SELECT 1 FROM sys_role_menus rm
|
|
|
|
|
+ WHERE rm.role_id = 2 AND rm.menu_id = p.id);
|