# product-v2: 产品改价权限入口拦截（业务铁规落地）

> **服务**: hl-product-service-v2 (端口 8083)
> **PR**: #2427
> **Issue**: #2424（P2 部分实施，剩余 P2.1 #2428 跟踪）
> **日期**: 2026-05-16
> **影响范围**: 4 个产品价格写入接口的角色权限拦截

---

## ⚠️ 关键变化（mmg 前端需注意）

新业务铁规：**只有定制师本人（CUSTOMIZER 且 product.created_by == 当前操作人）+ 超级管理员（SUPER_ADMIN）可以改价**。其他角色（运营/客服/房务/车务/素材/普通 ADMIN）调用价格写入接口一律返 `PERMISSION_DENIED`。

前端要做的事：

1. **隐藏改价按钮**：用户登录后获取 role，如果不是 SUPER_ADMIN 也不是 CUSTOMIZER+owner，前端**隐藏所有改价入口**（产品编辑页 STEP4、班期管理、价格日历编辑等）
2. **错误码处理**：调改价接口收到 `code=410115` 时，弹"无权改价，只有定制师本人或超级管理员可改价"提示（不要继续重试，不要刷新页面）
3. 兼容性：前端短期不改也没事（后端会拦），但 UX 不友好（运营点了按钮才发现"无权"），建议前端尽快配合

---

## 一、背景

用户口述铁规（2026-05-16）：定制师对自己的产品负责（价格策略也是个人决策），运营/客服等岗位不该改价。当前 4 个价格写入接口完全没角色校验，等于规则成空文 → 必须在 Service 入口拦截。

---

## 二、变更接口清单

| # | 接口 | 方法 | 路径 | 变更 |
|---|------|------|------|------|
| 1 | 批量设置价格日历 | POST | `/admin/product/item/price-calendar/batch-set` | **新增角色拦截** |
| 2 | 删除价格日历 | POST | `/admin/product/item/price-calendar/delete` | **新增角色拦截** |
| 3 | 保存班期 | POST | `/admin/product/item/schedule/save` | **新增角色拦截** |
| 4 | 批量创建班期 | POST | `/admin/product/item/schedule/batch-create` | **新增角色拦截** |

（精确路径以代码 `AdminProductController` 为准）

---

## 三、错误码

**新增** `PRICE_EDIT_PERMISSION_DENIED = 410115`

返回示例：

```json
{
  "code": 410115,
  "message": "无权改价,只有定制师本人或超级管理员可改价,productId=2055138817265897473",
  "data": null,
  "success": false
}
```

HTTP status 仍是 200（业务错误码在 Result.code），保持项目惯例。

---

## 四、校验逻辑（伪代码）

```java
public void checkPriceEditPermission(Long productId) {
    String role = AdminContextUtil.getRole();
    if ("SUPER_ADMIN".equals(role)) return;                    // 超管放行
    if ("CUSTOMIZER".equals(role)) {
        ProductDO p = getProductOrThrow(productId);
        if (currentAdminId.equals(p.getCreatedBy())) return;   // 定制师 + 本人创建放行
    }
    throw new BusinessException(PRICE_EDIT_PERMISSION_DENIED, productId);
}
```

---

## 五、向后兼容

- ✅ 接口路径、入参、出参字段全部不变（只是多了一种业务错误码）
- ✅ SUPER_ADMIN 和 CUSTOMIZER（本人产品）行为不变
- ❌ OPERATOR / CUSTOMER_SERVICE / ROOM_MANAGER / VEHICLE_MANAGER / MATERIAL_ADMIN / 普通 ADMIN 改价**会被拒**——但本来就不该改

---

## 六、不在本期范围（P2.1 #2428 跟踪）

- 集合深 diff（dayHotels/dayNodes 子项变化展示）
- JSON size cap 20KB 防爆
- CR 4 小修
- helper 自身行为 4 case 单测

---

## 七、部署

测试服公网光信号红灯，**P2 暂未部署测试服**。等公网恢复后部署，前端可同步联调。
