# 我的预约（机构）— 技术方案

> 依据：`我的预约(机构)功能需求.md`（同目录）；关联 `我的预约(兽医)技术方案.md`、`我的预约(专家)` 草稿与功能需求

---

## 1. 技术架构

| 项 | 说明 |
| --- | --- |
| **整体** | RuoYi **v3.9.2**（**springboot2** 分支）单体后端 + 若依 **Vue2** 管理端 |
| **运行时** | JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid |
| **数据库** | MySQL **5.7.39**，InnoDB，`utf8mb4` |
| **关联表** | `biz_medical_resource`（机构 `resource_type=3`，`sys_user_id` 绑定登录用户） |
| **预约数据** | 与兽医/专家共用 **`biz_service_appointment`**（见 **§2**）；本模块**无写接口** |
| **移动端** | 机构预约 `INSERT` 由「预约服务」完成；本模块为**机构后台只读查询** |

**后端分层（机构模块）**

| 层 | 职责 |
| --- | --- |
| `Controller` | 分页列表、详情；`@PreAuthorize`；`AjaxResult` / `TableDataInfo` |
| `Service` | 解析当前机构 `provider_id`、机构合法状态校验、越权校验 |
| `Mapper` + XML | 共用 `BizServiceAppointmentMapper`，按 `provider_type=2` 查询 |
| `support` | `OrgAppointmentValidation`、`OrgAppointmentStatusResolver`、`OrgProviderResolver`；复用 `ServiceAppointmentRules` |

**代码包（建议）**：`com.ruoyi.web.modules.diagnosis`（与兽医预约、医疗资源同域）  
**共用实体/Mapper**：`BizServiceAppointment`、`BizServiceAppointmentMapper`（兽医模块已建则**复用**，不重复建表）  
**初始化脚本**：`sql/biz_service_appointment.sql`（三端共用，机构迭代前须已执行）

---

## 2. 关联方案设计（三端共用）

### 2.1 统一预约主表 `biz_service_appointment`

| `provider_type` | 服务对象 | `provider_id` 指向 | 后台模块 | 移动端提交后 `status` |
| --- | --- | --- | --- | --- |
| `1` | 兽医 | `biz_medical_resource.id`（`resource_type=1`） | 我的预约（兽医） | `0` 待确认 |
| **`2`** | **诊疗机构** | **`biz_medical_resource.id`（`resource_type=3`）** | **我的预约（机构）** | **`5` 已预约** |
| `3` | 科技专家 | `biz_tech_resource.id`（`resource_type=1`） | 我的预约（专家） | `0` 待确认 |

机构与兽医共用 **`biz_medical_resource`**，以 `resource_type` 区分行；机构账号绑定 **`resource_type=3`** 的记录。

### 2.2 状态枚举（库表 `status` → 机构展示）

| 值 | 常量 | 机构展示 | 机构列表可筛 | 兽医/专家 |
| --- | --- | --- | --- | --- |
| `5` | `BOOKED` | 已预约 | ✓ | — |
| `3` | `CANCELLED` | 已取消 | ✓ | ✓ |
| `4` | `COMPLETED` | 已完成 | ✓ | ✓ |
| `0/1/2` | 待确认/已确认/已拒绝 | **不得出现** | — | ✓ |

应用层：`provider_type=2` 时，`status` 仅允许 **`3`、`4`、`5`**；列表筛选传入 `0/1/2` 视为非法。

### 2.3 三端接口对照

| 模块 | Base Path | 写操作 |
| --- | --- | --- |
| 兽医 | `/diseaseTreatment/myAppointment/vet` | 确认、拒绝 |
| **机构（本文档）** | **`/diseaseTreatment/myAppointment/org`** | **无** |
| 专家 | `/techService/myAppointment/expert` | 确认、拒绝；评价列表 |

### 2.4 当前登录人解析（机构）

```text
loginUser.userId
  → biz_medical_resource
      WHERE sys_user_id = ? AND resource_type = 3
        AND account_assigned = 1 AND del_flag = '0'
  → provider_id = id

列表/详情 WHERE provider_type = 2 AND provider_id = ?
```

无绑定：列表返回空；详情/越权访问返回「未绑定机构资源，无法查询预约」。

**Mapper 扩展（与兽医 `selectVetResourceBySysUserId` 对称）**

```sql
SELECT ... FROM biz_medical_resource
WHERE sys_user_id = #{sysUserId}
  AND resource_type = 3
  AND account_assigned = 1
  AND del_flag = '0'
LIMIT 1
```

### 2.5 机构与兽医/专家差异（实现约束）

| 项 | 机构 | 兽医/专家 |
| --- | --- | --- |
| 列表 SQL | 同表；`provider_type=2`；可不返回 `reject_reason` 列给前端（或返回但前端不展示） | `provider_type=1/3` |
| 详情 | 全字段只读；**不展示** `rejectReason`、评价 | 兽医无评价；专家有评价子表 |
| 状态标签 | `OrgAppointmentStatusResolver`（三态） | `VetAppointmentStatusResolver`（五态） |
| 专家评价表 | **不涉及** | 仅专家 `biz_service_appointment_review`（待建） |

---

## 3. 数据库设计

### 3.1 复用表 `biz_service_appointment`

机构模块**不新增业务表**；字段与兽医方案 **§3.1** 一致。机构侧关心字段如下：

| 字段 | 机构用途 |
| --- | --- |
| `provider_type` | 固定 `2` |
| `provider_id` | 机构医疗资源主键 |
| `appointee_name` / `appoint_date` / `time_start` / `time_end` | 列表（日期）+ 详情（时段） |
| `contact_phone` | 列表 + 详情 |
| `service_address` / `service_requirement` | **仅详情**（列表前端不展示，SQL 可仍查询） |
| `status` | `5/3/4` |
| `reject_reason` / `confirm_time` / `reject_time` | 机构流程不使用，**不展示** |

**DDL**：见 `sql/biz_service_appointment.sql`（项目已提供则无需重复执行）。

### 3.2 机构列表查询（Mapper XML 语义）

```sql
WHERE provider_type = 2 AND provider_id = #{providerId}
  <if test="appointeeName != null and appointeeName != ''">
    AND appointee_name LIKE concat('%', #{appointeeName}, '%')
  </if>
  <if test="startDate != null and startDate != ''">
    AND appoint_date &gt;= #{startDate}
  </if>
  <if test="endDate != null and endDate != ''">
    AND appoint_date &lt;= #{endDate}
  </if>
  <if test="status != null">
    AND status = #{status}
  </if>
ORDER BY appoint_date DESC, create_time DESC, id DESC
```

**详情/越权**：`id` + `provider_type=2` + `provider_id=当前机构`。

### 3.3 机构侧无需的子表

- 无分圈、无评价子表；**不**为机构单独建表。

---

## 4. 接口设计（机构）

统一响应：RuoYi `AjaxResult` / `TableDataInfo`（`code`、`msg`、`data` / `rows`、`total`）。

**权限标识（示例）**：`diseaseTreatment:orgMyAppointment:list|query|complete`（**无** confirm/reject）

**Base Path（示例）**：`/diseaseTreatment/myAppointment/org`

| # | 说明 | Method | URI | 权限 | 要点 |
| --- | --- | --- | --- | --- | --- |
| 4.1 | 分页列表 | GET | `/list` | `...:list` | Query：`pageNum`（默认 1）、`pageSize`（默认 **20**）、`appointeeName`（模糊）、`startDate`、`endDate`（`yyyy-MM-dd`）、`status`（**仅 `3/4/5`**）；**禁止**前端传 `providerId` |
| 4.2 | 详情 | GET | `/{id}` | `...:query` | 校验 `provider_type=2` 且归属当前机构；返回详情全字段（见下表） |

| 4.3 | 完成接诊 | POST | `/complete/{id}` | `...:complete` | 前置 `status=5`（已预约）；更新 `status=4`（已完成） |

**本期不提供**：`POST` 确认/拒绝；除 **完成接诊** 外无其他写操作。

### 4.1 列表响应字段（建议）

与功能需求列表列对齐，后端可返回：

`id`、`appointeeName`、`appointDate`、`contactPhone`、`status`、`statusLabel`。

（`timeStart`、`timeEnd`、`serviceAddress` 等可由 SQL 查出但列表页不绑定，或不下发以减流量。）

### 4.2 详情 `data` 字段（建议）

| 字段 | 说明 |
| --- | --- |
| `id` | 主键 |
| `appointeeName` | 预约人 |
| `appointDate` | `yyyy-MM-dd` |
| `timeStart` / `timeEnd` | 时段；前端拼 `HH:mm~HH:mm` |
| `contactPhone` | 联系电话 |
| `serviceAddress` | 服务地址 |
| `serviceRequirement` | 服务需求 |
| `status` / `statusLabel` | 状态码与展示名 |
| `createTime` | 提交时间（审计，可选） |

**不下发**：`rejectReason`、`confirmTime`、`rejectTime`（机构无对应流程）。

### 4.3 业务错误（`msg` 示例）

| 场景 | 文案 |
| --- | --- |
| 日期筛选 | 结束日期不能早于开始日期 |
| 状态筛选非法 | 状态筛选无效 |
| 无机构绑定 | 未绑定机构资源，无法查询预约 |
| 越权 | 无权操作该预约记录 / 无权查看该预约记录 |
| 不存在 | 预约记录不存在或已删除 |

### 4.4 与兽医/专家接口差异（实现对照）

| 能力 | 机构 | 兽医 | 专家 |
| --- | --- | --- | --- |
| 列表 | `GET .../org/list` | `GET .../vet/list` | `GET .../expert/list` |
| 详情 | `GET .../org/{id}` | `GET .../vet/{id}` | `GET .../expert/{id}` |
| 确认 | — | `POST .../vet/confirm/{id}` | `POST .../expert/confirm/{id}` |
| 拒绝 | — | `POST .../vet/reject/{id}` | `POST .../expert/reject/{id}` |
| 评价 | — | — | `GET .../expert/reviewList/{id}` |

---

## 5. 实现要点

| 项 | 说明 |
| --- | --- |
| 越权 | 详情必须 `provider_type=2` 且 `provider_id=当前机构` |
| 只读 | Controller **仅** `GET`；Service 无 `insert/update` 预约方法 |
| 状态展示 | `status=5` →「已预约」；勿与兽医「已确认」混用 |
| 数据串单防护 | 若查到 `status∈{0,1,2}` 且 `provider_type=2`，记日志并按「数据异常」处理（不展示或报错） |
| 日志 | 详情查看可记 `@Log`（查询类，按平台惯例） |
| 组件路径 | `diseaseTreatment/myAppointment/org/index` |

**建议新增类（机构）**

| 类 | 职责 |
| --- | --- |
| `OrgProviderResolver` | `resource_type=3` 解析 `provider_id` |
| `OrgAppointmentValidation` | 列表日期区间、`status∈{3,4,5}` |
| `OrgAppointmentStatusResolver` | 三态中文标签 |
| `OrgMyAppointmentServiceImpl` | 列表/详情 scope |
| `BizOrgMyAppointmentController` | 两个 GET 接口 |

**复用（兽医已建）**

- `ServiceAppointmentRules`、`BizServiceAppointment`、`BizServiceAppointmentMapper`  
- 扩展 Mapper：`selectOrgAppointmentList`、`selectOrgAppointmentByIdAndProvider`（或泛化 `selectByProvider` 减少重复）

---

## 6. 与上下游衔接

| 系统 | 说明 |
| --- | --- |
| 移动端预约服务 | 用户选机构并提交 → `INSERT`：`provider_type=2`，`status=5` |
| 移动端取消 | 更新 `status=3` |
| 已完成 | 业务闭环置 `status=4` |
| 畜牧医疗资源管理 | 机构须**已发布**且**已分配账号**（角色 **102**） |
| 我的预约（兽医） | 同表不同 `provider_type`；列表互不可见 |

---

## 7. 菜单与权限（示例）

| 类型 | 名称 | 权限标识 |
| --- | --- | --- |
| 菜单 | 我的预约（机构） | `diseaseTreatment:orgMyAppointment:list` |
| 按钮 | 查询 | `diseaseTreatment:orgMyAppointment:query` |
| 按钮 | 完成接诊 | `diseaseTreatment:orgMyAppointment:complete` |

组件路径：`diseaseTreatment/myAppointment/org/index`（「牧业疫病诊疗服务」目录下）。

---

## 8. 交付清单

- [ ] `BizMedicalResourceMapper.selectOrgResourceBySysUserId`（若尚未添加）  
- [ ] `BizServiceAppointmentMapper` 机构查询方法 + XML  
- [ ] `OrgMyAppointmentController` + Service + 校验/状态解析  
- [ ] 菜单权限 SQL（机构，仅 list/query）  
- [ ] 单元测试 + MockMvc（列表 scope、三态筛选、越权、无写接口）  

---

## 9. 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初稿：共用 `biz_service_appointment`；机构只读接口；三态与兽医/专家关联；复用 diagnosis 包与医疗资源绑定 |
