Skip to content

Commit 14b9f32

Browse files
authored
Merge pull request #35 from HappyProcess/feature/family-list-detail
가족 그룹 조회를 리스트/상세 API로 분리
2 parents 0835010 + 8ca4b93 commit 14b9f32

3 files changed

Lines changed: 96 additions & 36 deletions

File tree

src/main/java/com/haapyProcess/domain/family/controller/FamilyController.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.haapyProcess.domain.alert.dto.AlertResponse;
55
import com.haapyProcess.domain.alert.dto.UpdateAlertRequest;
66
import com.haapyProcess.domain.family.dto.AddFamilyRequest;
7+
import com.haapyProcess.domain.family.dto.FamilyListResponse;
78
import com.haapyProcess.domain.family.dto.FamilyMemberResponse;
89
import com.haapyProcess.domain.family.service.FamilyService;
910
import com.haapyProcess.domain.healthcondition.dto.UpdateConditionsRequest;
@@ -37,15 +38,26 @@ public ResponseEntity<Long> addFamily(@RequestBody @Valid AddFamilyRequest reque
3738
}
3839

3940
@Operation(
40-
summary = "가족 목록 및 위험도 조회",
41-
description = "가족 목록과 함께 각 가족 거주지의 실시간 날씨 위험도(isRisk), 등록된 지역(locations)과 알림 시간(alerts)을 반환합니다."
41+
summary = "가족 목록 조회 (리스트)",
42+
description = "가족 목록을 가볍게 반환합니다. 각 항목은 familyId, 이름, 질병 목록, 알림 시간 목록만 포함합니다. 상세 정보는 상세 조회 API를 사용하세요."
4243
)
4344
@ApiResponse(responseCode = "200", description = "조회 성공")
4445
@GetMapping
45-
public ResponseEntity<List<FamilyMemberResponse>> getMyFamilies() {
46+
public ResponseEntity<List<FamilyListResponse>> getMyFamilies() {
4647
return ResponseEntity.ok(familyService.getMyFamilies());
4748
}
4849

50+
@Operation(
51+
summary = "가족 상세 조회",
52+
description = "특정 가족의 전체 정보를 반환합니다. 나이, 알림 활성화 여부, 실시간 날씨 위험도(isRisk)와 원인 질병, 등록된 지역(locations), 알림 시간(alerts)을 모두 포함합니다."
53+
)
54+
@ApiResponse(responseCode = "200", description = "조회 성공")
55+
@ApiResponse(responseCode = "404", description = "권한이 없거나 존재하지 않는 가족 ID")
56+
@GetMapping("/{familyId}")
57+
public ResponseEntity<FamilyMemberResponse> getFamilyDetail(@PathVariable Long familyId) {
58+
return ResponseEntity.ok(familyService.getFamilyDetail(familyId));
59+
}
60+
4961
@Operation(
5062
summary = "가족 프로필(건강 상태) 수정",
5163
description = "특정 가족 구성원이 앓고 있는 질환 목록을 덮어씌웁니다. 내 프로필 수정과 동일한 DTO를 사용합니다."
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.haapyProcess.domain.family.dto;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
import java.util.List;
7+
8+
@Getter
9+
@Builder
10+
public class FamilyListResponse {
11+
12+
@Schema(description = "가족 관계 ID (상세 조회/수정용)", example = "1")
13+
private Long familyId;
14+
15+
@Schema(description = "가족 이름", example = "아빠")
16+
private String name;
17+
18+
@Schema(description = "가족이 가진 질병 이름 목록", example = "[\"관절염\", \"고혈압\"]")
19+
private List<String> healthConditionNames;
20+
21+
@Schema(description = "가족에게 설정된 알림 시간 목록 (HH:mm)", example = "[\"08:00\", \"18:30\"]")
22+
private List<String> alertTimes;
23+
}

src/main/java/com/haapyProcess/domain/family/service/FamilyService.java

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.haapyProcess.domain.condition.entity.Condition;
1111
import com.haapyProcess.domain.condition.repository.ConditionRepository;
1212
import com.haapyProcess.domain.family.dto.AddFamilyRequest;
13+
import com.haapyProcess.domain.family.dto.FamilyListResponse;
1314
import com.haapyProcess.domain.family.dto.FamilyMemberResponse;
1415
import com.haapyProcess.domain.family.entity.Family;
1516
import com.haapyProcess.domain.family.repository.FamilyRepository;
@@ -73,59 +74,83 @@ public Long addFamily(AddFamilyRequest request) {
7374
return familyRepository.save(family).getFamilyId();
7475
}
7576

76-
// 2. 가족 목록 조회 (위험도 + 지역 + 알림 시간 포함)
77+
// 2-1. 가족 목록 조회 (가벼운 버전: 이름 + 질병 + 알림 시간만)
7778
@Transactional(readOnly = true)
78-
public List<FamilyMemberResponse> getMyFamilies() {
79+
public List<FamilyListResponse> getMyFamilies() {
7980
Member me = memberService.getCurrentMember();
8081
List<Family> families = familyRepository.findAllByUser(me);
8182

8283
return families.stream().map(family -> {
8384
Member relative = family.getRelative();
8485

85-
int age = relative.getBirth() != null
86-
? Period.between(relative.getBirth(), LocalDate.now()).getYears()
87-
: 0;
88-
8986
List<String> conditionNames = relative.getHealthConditions().stream()
9087
.map(hc -> hc.getCondition().getConditionName())
9188
.toList();
9289

93-
// 날씨 위험도 분석 (가족이 위치 미등록이거나 기상청 에러 시 방어)
94-
RiskAnalysisResult riskResult;
95-
try {
96-
riskResult = riskAnalysisService.analyzeRiskForMember(relative);
97-
} catch (Exception e) {
98-
riskResult = new RiskAnalysisResult(false, null);
99-
}
100-
101-
List<String> causeDiseaseNames = riskResult.getRiskDetails() == null ? List.of()
102-
: riskResult.getRiskDetails().stream()
103-
.map(RiskAnalysisResult.RiskDetail::getDiseaseName)
104-
.toList();
105-
106-
List<LocationResponse> locations = locationRepository.findAllByMember(relative).stream()
107-
.map(LocationResponse::from)
108-
.toList();
109-
110-
List<AlertResponse> alerts = alertRepository.findAllByMemberOrderByAlertTimeAsc(relative).stream()
111-
.map(AlertResponse::from)
90+
List<String> alertTimes = alertRepository.findAllByMemberOrderByAlertTimeAsc(relative).stream()
91+
.map(Alert::getAlertTime)
11292
.toList();
11393

114-
return FamilyMemberResponse.builder()
94+
return FamilyListResponse.builder()
11595
.familyId(family.getFamilyId())
116-
.relativeId(relative.getMemberId())
11796
.name(relative.getName())
118-
.age(age)
119-
.isAlertEnabled(family.isAlertEnabled())
12097
.healthConditionNames(conditionNames)
121-
.isRisk(riskResult.isRisk())
122-
.causeDiseaseNames(causeDiseaseNames)
123-
.locations(locations)
124-
.alerts(alerts)
98+
.alertTimes(alertTimes)
12599
.build();
126100
}).toList();
127101
}
128102

103+
// 2-2. 가족 상세 조회 (위험도 + 지역 + 알림 시간 전부 포함)
104+
@Transactional(readOnly = true)
105+
public FamilyMemberResponse getFamilyDetail(Long familyId) {
106+
Member me = memberService.getCurrentMember();
107+
Family family = familyRepository.findByFamilyIdAndUser(familyId, me)
108+
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
109+
Member relative = family.getRelative();
110+
111+
int age = relative.getBirth() != null
112+
? Period.between(relative.getBirth(), LocalDate.now()).getYears()
113+
: 0;
114+
115+
List<String> conditionNames = relative.getHealthConditions().stream()
116+
.map(hc -> hc.getCondition().getConditionName())
117+
.toList();
118+
119+
// 날씨 위험도 분석 (가족이 위치 미등록이거나 기상청 에러 시 방어)
120+
RiskAnalysisResult riskResult;
121+
try {
122+
riskResult = riskAnalysisService.analyzeRiskForMember(relative);
123+
} catch (Exception e) {
124+
riskResult = new RiskAnalysisResult(false, null);
125+
}
126+
127+
List<String> causeDiseaseNames = riskResult.getRiskDetails() == null ? List.of()
128+
: riskResult.getRiskDetails().stream()
129+
.map(RiskAnalysisResult.RiskDetail::getDiseaseName)
130+
.toList();
131+
132+
List<LocationResponse> locations = locationRepository.findAllByMember(relative).stream()
133+
.map(LocationResponse::from)
134+
.toList();
135+
136+
List<AlertResponse> alerts = alertRepository.findAllByMemberOrderByAlertTimeAsc(relative).stream()
137+
.map(AlertResponse::from)
138+
.toList();
139+
140+
return FamilyMemberResponse.builder()
141+
.familyId(family.getFamilyId())
142+
.relativeId(relative.getMemberId())
143+
.name(relative.getName())
144+
.age(age)
145+
.isAlertEnabled(family.isAlertEnabled())
146+
.healthConditionNames(conditionNames)
147+
.isRisk(riskResult.isRisk())
148+
.causeDiseaseNames(causeDiseaseNames)
149+
.locations(locations)
150+
.alerts(alerts)
151+
.build();
152+
}
153+
129154
// 3. 가족 건강 상태(질환) 수정 (덮어쓰기)
130155
@Transactional
131156
public void updateFamilyConditions(Long familyId, UpdateConditionsRequest request) {

0 commit comments

Comments
 (0)