Skip to content

Commit 3bb1aa2

Browse files
authored
[NL-72] 운세 목록 조회 API 수정 (#19)
* feat: /users/{user_id}/daily-fortunes API 응답 수정 * feat: User DailyFortunes 없으면 생성
1 parent 47bf1b8 commit 3bb1aa2

File tree

4 files changed

+112
-9
lines changed

4 files changed

+112
-9
lines changed

src/fortune/entities/schemas.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class UserDailyFortuneSummary(CommonBase):
3939
image_url: str
4040
description: str
4141

42+
class UserDailyFortuneSummaries(CommonBase):
43+
title: str
44+
content: List[UserDailyFortuneSummary]
45+
4246

4347
class FortuneDetailItem(CommonBase):
4448
"""운세 상세 항목"""

src/fortune/repository.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import date
2-
from typing import List, Optional, Tuple
2+
from typing import List, Optional, Tuple, Iterable
33

44
from fastapi import Depends
55
from sqlalchemy import select, desc, and_
@@ -173,3 +173,77 @@ async def create_user_daily_fortune_detail(
173173
await self.session.flush()
174174
await self.session.refresh(model)
175175
return model
176+
177+
178+
async def get_user_daily_fortune_resources(
179+
self,
180+
ref_date: Optional[date] = None,
181+
) -> List[DailyFortuneResourceModel]:
182+
if ref_date is None:
183+
ref_date = date.today()
184+
dfr = DailyFortuneResourceModel
185+
186+
types_in_order = [
187+
FortuneType.GUIIN_INITIAL,
188+
FortuneType.LUCKY_OBJECT,
189+
FortuneType.PERFECT_TIMING,
190+
FortuneType.TABOO_OF_DAY,
191+
]
192+
193+
items: List[DailyFortuneResourceModel] = []
194+
for t in types_in_order:
195+
stmt = (
196+
select(dfr)
197+
.where(
198+
dfr.fortune_type == t,
199+
dfr.publish_date <= ref_date,
200+
)
201+
.order_by(dfr.publish_date.desc(), dfr.id.desc())
202+
.limit(1)
203+
)
204+
res = await self.session.execute(stmt)
205+
row = res.scalar_one_or_none()
206+
if row:
207+
items.append(row)
208+
209+
return items
210+
211+
async def bulk_upsert_user_daily_fortune_summaries(
212+
self,
213+
user_id: str,
214+
fortune_date: date,
215+
resource_ids: Iterable[int],
216+
) -> None:
217+
"""해당 user_id/fortune_date에 대해 주어진 resource_ids를 중복 없이 삽입."""
218+
if not resource_ids:
219+
return
220+
221+
Summary = UserDailyFortuneSummaryModel
222+
223+
# 이미 존재하는 것 조회
224+
exists_q = (
225+
select(Summary.daily_fortune_resource_id)
226+
.where(
227+
Summary.user_id == user_id,
228+
Summary.fortune_date == fortune_date,
229+
Summary.daily_fortune_resource_id.in_(list(resource_ids)),
230+
)
231+
)
232+
res = await self.session.execute(exists_q)
233+
existing_ids = set(res.scalars().all())
234+
235+
to_create = [rid for rid in resource_ids if rid not in existing_ids]
236+
if not to_create:
237+
return
238+
239+
# 새로 추가
240+
for rid in to_create:
241+
self.session.add(
242+
Summary(
243+
user_id=user_id,
244+
fortune_date=fortune_date,
245+
daily_fortune_resource_id=rid,
246+
)
247+
)
248+
249+
await self.session.flush()

src/fortune/service.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
UserDailyFortuneDetail,
1313
FortuneDetailItem,
1414
)
15-
from src.fortune.entities.schemas import UserDailyFortuneSummary
15+
from src.fortune.entities.schemas import UserDailyFortuneSummaries
1616
from src.fortune.repository import FortuneRepository
1717
from src.fortune.entities.constants import DAILY_FORTUNE_FALLBACK_DATA
1818
from src.hcx_client.client import HCXClient
@@ -87,16 +87,41 @@ async def delete_fortune(self, resource_id: int) -> None:
8787

8888
async def get_user_daily_fortune_summaries(
8989
self, user_id: str, fortune_date: date
90-
) -> List[UserDailyFortuneSummary]:
90+
) -> UserDailyFortuneSummaries:
91+
# 1) 먼저 조회
9192
summaries = await self.repository.get_user_daily_fortune_summaries(
9293
user_id, fortune_date
9394
)
95+
9496
if not summaries:
95-
raise HTTPException(
96-
status_code=status.HTTP_404_NOT_FOUND,
97-
detail="오늘의 운세 데이터를 찾을 수 없습니다.",
97+
# 2) 타입별 최신 리소스(오늘 포함 과거) 가져와서 요약 4건 생성
98+
resources = await self.repository.get_user_daily_fortune_resources(
99+
ref_date=fortune_date
100+
)
101+
if not resources:
102+
# 생성할 리소스 자체가 없으면 이때만 404
103+
raise HTTPException(
104+
status_code=status.HTTP_404_NOT_FOUND,
105+
detail="오늘 기준으로 생성 가능한 운세 리소스가 없습니다.",
106+
)
107+
108+
resource_ids = [r.id for r in resources]
109+
await self.repository.bulk_upsert_user_daily_fortune_summaries(
110+
user_id=user_id,
111+
fortune_date=fortune_date,
112+
resource_ids=resource_ids,
98113
)
99-
return summaries # Return the list directly
114+
115+
# 3) 다시 조회해서 반환 데이터 구성
116+
summaries = await self.repository.get_user_daily_fortune_summaries(
117+
user_id, fortune_date
118+
)
119+
120+
# 4) 래핑해서 리턴 (스키마에 맞게)
121+
return UserDailyFortuneSummaries(
122+
title="잘 되면 꼭 기억해 주시오",
123+
content=summaries,
124+
)
100125

101126
async def get_user_daily_fortune_detail(
102127
self, user_id: str, fortune_date: date

src/users/router.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from src.lotto.entities.schemas import LottoRecommendation
77
from src.lotto.service import LottoService
88
from src.users.entities.schemas import UserCreate, UserDetail, UserList, UserUpdate
9-
from src.fortune.entities.schemas import UserDailyFortuneSummary, UserDailyFortuneDetail
9+
from src.fortune.entities.schemas import UserDailyFortuneSummaries, UserDailyFortuneDetail
1010
from src.users.service import UserService
1111
from src.fortune.service import FortuneService
1212
from typing import List
@@ -116,7 +116,7 @@ async def get_lotto_recommendation(
116116

117117

118118
@user_router.get(
119-
"/{user_id}/daily-fortunes", response_model=List[UserDailyFortuneSummary]
119+
"/{user_id}/daily-fortunes", response_model=UserDailyFortuneSummaries
120120
)
121121
async def get_user_daily_fortunes(
122122
user_id: str,

0 commit comments

Comments
 (0)