|
|
@@ -768,7 +768,7 @@ public class HealthReportService {
|
|
|
String nm = nameToMatch.trim().replaceAll("\\s+", "");
|
|
|
if (nm.equals(cleanName)) {
|
|
|
log.info("User 姓名精确匹配: {} -> userId={}", cleanName, user.getId());
|
|
|
- return user.getId();
|
|
|
+ return resolveSubjectToMemberId(user.getId(), familyId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -778,7 +778,7 @@ public class HealthReportService {
|
|
|
|
|
|
if (cleanName.contains(nameToMatch) || nameToMatch.contains(cleanName)) {
|
|
|
log.info("User 姓名模糊匹配: {} -> userId={}", cleanName, user.getId());
|
|
|
- return user.getId();
|
|
|
+ return resolveSubjectToMemberId(user.getId(), familyId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -788,7 +788,7 @@ public class HealthReportService {
|
|
|
|
|
|
if (fuzzyMatch(cleanName, nameToMatch)) {
|
|
|
log.info("User 姓名fuzzy匹配: {} -> userId={}", cleanName, user.getId());
|
|
|
- return user.getId();
|
|
|
+ return resolveSubjectToMemberId(user.getId(), familyId);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1222,9 +1222,71 @@ public class HealthReportService {
|
|
|
payloadJson, reportId);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 归一化 subject_id 到 family_members.id 口径(A方案:报告统一挂 member_id)。
|
|
|
+ *
|
|
|
+ * <p>历史 subject_id 混用 users.id / family_members.id:确认/采集/编辑各链路都可能
|
|
|
+ * 把 users.id 直接写入。本方法把"users.id 或跨家庭成员 id"回查为指定家庭内的
|
|
|
+ * family_members.id,保证报告、维度分、食材推荐全部按成员卡统一挂接,
|
|
|
+ * 成员迁移(改 family_id 保留 member_id)后自动跟随。</p>
|
|
|
+ *
|
|
|
+ * @param subjectId 待归一化的被检测人 id(可能是 users.id 或 family_members.id)
|
|
|
+ * @param familyId 报告所属家庭
|
|
|
+ * @return 该家庭内的 family_members.id;无法解析时原样返回
|
|
|
+ */
|
|
|
+ public Long resolveSubjectToMemberId(Long subjectId, Long familyId) {
|
|
|
+ if (subjectId == null || familyId == null) {
|
|
|
+ return subjectId;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // 已是本家庭成员 id -> 原样返回
|
|
|
+ FamilyMember direct = familyMemberMapper.selectById(subjectId);
|
|
|
+ if (direct != null && familyId.equals(direct.getFamilyId())) {
|
|
|
+ return subjectId;
|
|
|
+ }
|
|
|
+ // subjectId 是 users.id -> 回查该用户在本家庭的成员行
|
|
|
+ User u = userMapper.selectById(subjectId);
|
|
|
+ if (u != null) {
|
|
|
+ FamilyMember byUser = familyMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyMember>()
|
|
|
+ .eq(FamilyMember::getFamilyId, familyId)
|
|
|
+ .eq(FamilyMember::getUserId, subjectId)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (byUser != null) {
|
|
|
+ return byUser.getId();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // subjectId 是跨家庭 member 行 -> 按该成员的 user_id 回查本家庭
|
|
|
+ if (direct != null && direct.getUserId() != null) {
|
|
|
+ FamilyMember same = familyMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyMember>()
|
|
|
+ .eq(FamilyMember::getFamilyId, familyId)
|
|
|
+ .eq(FamilyMember::getUserId, direct.getUserId())
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (same != null) {
|
|
|
+ return same.getId();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("subjectId归一化失败 subjectId={}, familyId={}: {}", subjectId, familyId, e.getMessage());
|
|
|
+ }
|
|
|
+ return subjectId;
|
|
|
+ }
|
|
|
+
|
|
|
public void bindReportToMember(Long reportId, Long subjectId) {
|
|
|
// 使用 JdbcTemplate 直接 UPDATE,避免 MyBatis-Plus NOT_NULL 策略导致 NULL 值不更新
|
|
|
String sql = "UPDATE health_reports SET subject_id = ? WHERE id = ?";
|
|
|
+ // A方案:写库前归一化为 family_members.id 口径
|
|
|
+ if (subjectId != null && subjectId > 0) {
|
|
|
+ HealthReport rep = healthReportMapper.selectById(reportId);
|
|
|
+ if (rep != null) {
|
|
|
+ Long resolved = resolveSubjectToMemberId(subjectId, rep.getFamilyId());
|
|
|
+ if (resolved != null && !resolved.equals(subjectId)) {
|
|
|
+ log.info("subjectId归一化 reportId={}, {} -> {}", reportId, subjectId, resolved);
|
|
|
+ }
|
|
|
+ subjectId = resolved;
|
|
|
+ }
|
|
|
+ }
|
|
|
int updatedRows = jdbcTemplate.update(sql, subjectId, reportId);
|
|
|
if (updatedRows == 0) {
|
|
|
log.warn("reportId={}, subjectId={} 更新失败 - 报告不存在", reportId, subjectId);
|
|
|
@@ -1261,7 +1323,10 @@ public class HealthReportService {
|
|
|
throw new RuntimeException("报告不存在");
|
|
|
}
|
|
|
|
|
|
- // 权限检查:确保报告属于该家庭
|
|
|
+ // 权限检查:确保报告属于该家庭(familyId 为空视为未加入家庭,防 NPE)
|
|
|
+ if (familyId == null) {
|
|
|
+ throw new RuntimeException("请先加入家庭");
|
|
|
+ }
|
|
|
if (!familyId.equals(report.getFamilyId())) {
|
|
|
throw new RuntimeException("报告不属于该家庭");
|
|
|
}
|