Prechádzať zdrojové kódy

docs(patient): 更新患者提醒定时任务设计文档

- 新增完整的定时任务处理流程与调度方式说明
- 补充权限开关与时间点来源的详细判定逻辑
- 增加数据库表结构定义与字段含义说明
- 添加微信订阅消息发送模块的架构设计
- 完善错误处理与监控建议
- 保留原始草稿内容供参考对比

feat(binding): 增强用户绑定关系的角色校验逻辑

- 校验 patientUserId 必须存在且角色为 PATIENT
- 校验 boundUserId 必须存在且角色与绑定类型匹配
- 增加 DOCTOR 类型绑定时的角色校验
- 增加 FAMILY 类型绑定时的角色校验
- 完善参数为空与用户不存在的异常处理
- 添加绑定类型无效时的错误提示
mcbaiyun 1 mesiac pred
rodič
commit
73168abd2e

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 132 - 0
docs/Dev/modules/Processing/PatientReminderTaskDesign.md


+ 2 - 0
docs/Dev/modules/用户绑定功能设计文档.md

@@ -68,6 +68,8 @@
 **业务规则与校验**
 - 创建绑定时:
   - 校验 `patientUserId` 与 `boundUserId` 不为空,且二者不同。
+  - 校验 `patientUserId` 对应的用户必须存在,且其角色必须为 **患者(PATIENT)**。
+  - 校验 `boundUserId` 对应的用户必须存在;若 `bindingType=DOCTOR` 则其角色必须为 **医生(DOCTOR)**,若 `bindingType=FAMILY` 则其角色必须为 **患者家属(PATIENT_FAMILY)**。
   - 不允许重复生效的绑定记录;如已存在有效绑定则返回幂等成功或说明已存在。
   - 可能需要目标用户同意(可扩展为双向确认流程),当前实现为直接创建(具体流程参照 `UserBindingService`)。
 - 删除绑定时:

+ 41 - 0
src/main/java/work/baiyun/chronicdiseaseapp/service/impl/UserBindingServiceImpl.java

@@ -16,6 +16,8 @@ import work.baiyun.chronicdiseaseapp.model.vo.CheckUserBindingResponse;
 import work.baiyun.chronicdiseaseapp.model.vo.CheckUserBindingRequest;
 import work.baiyun.chronicdiseaseapp.service.UserBindingService;
 import work.baiyun.chronicdiseaseapp.enums.UserBindingType;
+import work.baiyun.chronicdiseaseapp.enums.PermissionGroup;
+import work.baiyun.chronicdiseaseapp.exception.CustomException;
 
 import java.util.List;
 import java.util.Map;
@@ -33,6 +35,45 @@ public class UserBindingServiceImpl implements UserBindingService {
 
     @Override
     public void createUserBinding(CreateUserBindingRequest request) {
+        // 基础校验:参数非空由 controller/vo 注解完成,但需要检查用户存在性与角色一致性
+        if (request.getPatientUserId() == null || request.getBoundUserId() == null) {
+            throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(), "patientUserId or boundUserId is null");
+        }
+
+        if (request.getPatientUserId().equals(request.getBoundUserId())) {
+            throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(), "不能绑定自己");
+        }
+
+        // 验证 patientUserId 存在且角色为 PATIENT
+        work.baiyun.chronicdiseaseapp.model.po.UserInfo patient = userInfoMapper.selectById(request.getPatientUserId());
+        if (patient == null) {
+            throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.USER_NOT_EXIST.getCode(), "患者用户不存在");
+        }
+        if (patient.getRole() != PermissionGroup.PATIENT) {
+            throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(), "patientUserId 对应的用户不是患者");
+        }
+
+        // 验证 boundUserId 存在且角色与 bindingType 一致
+        work.baiyun.chronicdiseaseapp.model.po.UserInfo bound = userInfoMapper.selectById(request.getBoundUserId());
+        if (bound == null) {
+            throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.USER_NOT_EXIST.getCode(), "被绑定用户不存在");
+        }
+
+        UserBindingType type = UserBindingType.fromCode(request.getBindingType());
+        if (type == null) {
+            throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(), "bindingType 无效");
+        }
+
+        if (type == UserBindingType.DOCTOR) {
+            if (bound.getRole() != PermissionGroup.DOCTOR) {
+                throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.INVALID_DOCTOR.getCode(), "被绑定用户不是医生");
+            }
+        } else if (type == UserBindingType.FAMILY) {
+            if (bound.getRole() != PermissionGroup.PATIENT_FAMILY) {
+                throw new CustomException(work.baiyun.chronicdiseaseapp.enums.ErrorCode.PARAMETER_ERROR.getCode(), "被绑定用户不是患者家属");
+            }
+        }
+
         // 检查是否已存在绑定关系
         QueryWrapper<UserBinding> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("patient_user_id", request.getPatientUserId())

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov