-- ============================================================================
-- 1.0.433：把 S5 库存冷链入站管理接口纳入按钮权限管控（P0 权限治理）
--
-- 缺陷（CODE VERIFIED + RUNTIME VERIFIED）：
--   JwtHandler.CheckAuthorizeAsync（Admin.NET.Web.Core/Handlers/JwtHandler.cs:74-97）
--   的判定是：
--     ① 超管(AccountType=999) 直接放行；
--     ② 命中「自有按钮权限」放行；
--     ③ 否则——**只要该路由名未登记为任何按钮权限，就兜底放行**。
--   /api/S5InventoryInbound/* 六个 POST 管理接口全部未登记，一律走 ③ 兜底放行，
--   任何已登录用户（含 AccountType=777 普通业务账号）都能触发库存贴源/物化/重建。
--   实测：UATAdminA（777 普通用户）成功调用 reconcile 与 transform-inventory-std。
--
-- 权限名为什么必须是路由派生名：
--   JwtHandler 把 /api/A/B 映射为权限名 A:B（Path.Value[5..] 把 '/' 换成 ':'），
--   再与用户自有权限做**忽略大小写的全等比较**。因此单个 s5InventoryInbound:admin
--   无法覆盖多个路由——必须逐接口登记，权限名等于各自路由派生名。
--   参照系统内已生效的先例 sysOrg:list ← /api/sysOrg/list（SysMenu Id=1300200030201）。
--   注：S8 的 s8:exception:* 属前端 v-auth 权限点，其路由为 /api/aidop/s8/...
--   （派生名 aidop:s8:...），并不参与 JwtHandler 鉴权，不能作为本次命名依据。
--
-- 授权对象（依据真实 AccountType / RoleId，不按账号名猜）：
--   SysMenuService.GetOwnBtnPermList（Service/Menu/SysMenuService.cs:336-357）对
--   AccountType=888(SysAdmin) 且未绑定任何角色的账号，返回「该租户 SysTenantMenu
--   允许的全部按钮权限」。租户 797403760988229 的 AIDopAdmin 正是此形态（888、无角色），
--   故只需给该租户加租户级菜单授权即可获得管理能力。
--   → 本脚本**不新建角色、不写任何 SysRoleMenu**，普通业务角色一律无权。
--
-- 明确不做：
--   - 不给 UAT 租户(838257186181189)加租户级授权（该租户 6 个账号全为 777 普通用户，
--     无任何 SysAdmin，不应具备库存重建能力）
--   - 不给 UAT_FUNCTION_USER / ROLE_WH_* / ROLE_QC 等任何业务角色授权
--   - 不使用 GrantRoleMenu（其语义是「删角色全部 SysRoleMenu 再全量重建」）
--   - 不按 RoleCode 跨租户模糊授权
--   - 不改任何既有菜单、不改任何既有角色权限
--   - 不改库存同步/STD/LIVE 数据逻辑
--
-- 幂等：全部 INSERT 带 NOT EXISTS（菜单按 Permission，租户授权按 TenantId+MenuId）。
--       重复执行 affected rows = 0。
--
-- ⚠️ 缓存：JwtHandler 用 GetAllBtnPermList（缓存键 sys_user_button:0）判断「是否已登记」，
--   GetOwnBtnPermList 缓存键 sys_user_button:<userId>，均为进程内 Memory 缓存
--   （Cache.json:7 CacheType=Memory），SQL 写库不会使其失效。
--   AutoVersionUpdate 在应用启动时执行本脚本，该进程缓存本就为空，随发布重启天然生效；
--   若在已运行实例上手工执行，必须重启后端。
-- ============================================================================

-- ---------------------------------------------------------------------------
-- 0. 作用域解析（不硬编码租户 Id，按 SysOrg.Code 反查，与 1.0.402/1.0.408 一致）
-- ---------------------------------------------------------------------------
SET @admin_tenant := (SELECT t.Id FROM SysTenant t JOIN SysOrg o ON o.Id = t.OrgId
                      WHERE o.Code = 'AIDOP' AND t.Status = 1 LIMIT 1);

-- 挂载点：S5 / 库存数据 / 库存查询（Type=2 页面菜单）。冷链入站即该页数据的来源。
SET @parent_menu := (SELECT Id FROM SysMenu
                     WHERE Name = 'aidopS5InventoryStockQuery' AND Type = 2 LIMIT 1);

-- ---------------------------------------------------------------------------
-- 1. 登记 6 个按钮权限（权限名 = 路由派生名，逐接口）
-- ---------------------------------------------------------------------------
INSERT INTO SysMenu (Id, Pid, Type, Name, Permission, Title, Icon,
                     IsIframe, IsHide, IsKeepAlive, IsAffix, OrderNo, Status, Remark, CreateTime)
SELECT s.Id, @parent_menu, 3, s.Name, s.Permission, s.Title, 'ele-Menu',
       0, 0, 1, 0, s.OrderNo, 1, s.Remark, NOW()
FROM (
  SELECT 1329015030101 AS Id, 'aidopS5InvInboundBtn01' AS Name,
         's5InventoryInbound:bootstrap'              AS Permission,
         '库存冷链首刷'                              AS Title, 910 AS OrderNo,
         'S5 冷链管理权限点 POST /api/S5InventoryInbound/bootstrap（写 STG + 全量替换 STD）' AS Remark
  UNION ALL SELECT 1329015030102, 'aidopS5InvInboundBtn02',
         's5InventoryInbound:run-once',
         '库存冷链跑一轮', 920,
         'S5 冷链管理权限点 POST /api/S5InventoryInbound/run-once（写 STG + UPSERT STD）'
  UNION ALL SELECT 1329015030103, 'aidopS5InvInboundBtn03',
         's5InventoryInbound:reconcile',
         '库存冷链全量校准', 930,
         'S5 冷链管理权限点 POST /api/S5InventoryInbound/reconcile（写 STG + 全量替换 STD）'
  UNION ALL SELECT 1329015030104, 'aidopS5InvInboundBtn04',
         's5InventoryInbound:transform-std',
         '库存流水 stg→std 补转换', 940,
         'S5 冷链管理权限点 POST /api/S5InventoryInbound/transform-std（写 mdp_std_inv_trans）'
  UNION ALL SELECT 1329015030105, 'aidopS5InvInboundBtn05',
         's5InventoryInbound:transform-inventory-std',
         '库存余额 stg→std 补物化', 950,
         'S5 冷链管理权限点 POST /api/S5InventoryInbound/transform-inventory-std（写 mdp_std_inventory）'
  UNION ALL SELECT 1329015030106, 'aidopS5InvInboundBtn06',
         's5InventoryInbound:daily-recon',
         '库存日终对账（手工）', 960,
         'S5 冷链管理权限点 POST /api/S5InventoryInbound/daily-recon（写 ado_inventory_recon_diff）'
) s
WHERE @parent_menu IS NOT NULL
  AND NOT EXISTS (SELECT 1 FROM SysMenu m WHERE m.Permission = s.Permission AND m.Type = 3);

-- ---------------------------------------------------------------------------
-- 2. 租户级授权：只给拥有真实 SysAdmin 运维账号的租户（AIDOP）
--    不给 UAT 租户，不给默认租户（超管走 AccountType=999 旁路，无需授权）
-- ---------------------------------------------------------------------------
SET @tm_base := (SELECT IFNULL(MAX(Id), 0) FROM SysTenantMenu);

INSERT INTO SysTenantMenu (Id, TenantId, MenuId)
SELECT @tm_base + ROW_NUMBER() OVER (ORDER BY m.Id), @admin_tenant, m.Id
FROM SysMenu m
WHERE @admin_tenant IS NOT NULL
  AND m.Type = 3
  AND m.Permission IN (
      's5InventoryInbound:bootstrap',
      's5InventoryInbound:run-once',
      's5InventoryInbound:reconcile',
      's5InventoryInbound:transform-std',
      's5InventoryInbound:transform-inventory-std',
      's5InventoryInbound:daily-recon')
  AND NOT EXISTS (
      SELECT 1 FROM SysTenantMenu tm
       WHERE tm.TenantId = @admin_tenant AND tm.MenuId = m.Id);
