Skip to content

Commit 69c646f

Browse files
authored
Merge pull request #27 from 9git9git/SCRUM-139-main-일정-페이지-서비스-API-개발
[Scrum-139]-[BE]-main-일정-페이지-서비스-API-개발
2 parents cc02350 + 50dcfd9 commit 69c646f

File tree

14 files changed

+249
-110
lines changed

14 files changed

+249
-110
lines changed

app/api/v1/endpoints/chat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async def get_chats_by_storage(
5252
)
5353

5454

55-
@router.get("/category/{category_id}", response_model=ResponseBase[List[ChatResponse]])
55+
@router.get("/", response_model=ResponseBase[List[ChatResponse]])
5656
async def get_chats_by_category(
5757
user_id: UUID,
5858
category_id: UUID,

app/api/v1/endpoints/main.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from http.client import HTTPException
2+
from app.schemas.main import TodosAndMemosResponse
3+
from app.services.main import select_todos_and_memos_by_period
4+
from app.schemas.base import ResponseBase
5+
from fastapi import APIRouter, Depends, status
6+
from sqlalchemy.ext.asyncio import AsyncSession
7+
from uuid import UUID
8+
from datetime import date
9+
from app.db.session import get_db
10+
from app.schemas.progress import TodayProgressResponse
11+
from app.services.main import select_today_progresses
12+
13+
router = APIRouter()
14+
15+
16+
@router.get("/todos-and-memos", response_model=ResponseBase[TodosAndMemosResponse])
17+
async def get_todos_and_memos(
18+
user_id: UUID,
19+
start_date: date,
20+
end_date: date,
21+
db: AsyncSession = Depends(get_db),
22+
) -> ResponseBase[TodosAndMemosResponse]:
23+
try:
24+
todos_and_memos = await select_todos_and_memos_by_period(
25+
db, user_id, start_date, end_date
26+
)
27+
return ResponseBase(status_code=status.HTTP_200_OK, data=todos_and_memos)
28+
except HTTPException as e:
29+
return ResponseBase(status_code=e.status_code, error=e.detail)
30+
except Exception as e:
31+
return ResponseBase(
32+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, error=str(e)
33+
)
34+
35+
36+
@router.get("/today-progresses", response_model=ResponseBase[TodayProgressResponse])
37+
async def get_today_progresses(
38+
user_id: UUID,
39+
db: AsyncSession = Depends(get_db),
40+
) -> ResponseBase[TodayProgressResponse]:
41+
try:
42+
today_progresses = await select_today_progresses(db, user_id)
43+
return ResponseBase(status_code=status.HTTP_200_OK, data=today_progresses)
44+
except HTTPException as e:
45+
return ResponseBase(status_code=e.status_code, error=e.detail)
46+
except Exception as e:
47+
return ResponseBase(
48+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, error=str(e)
49+
)

app/api/v1/endpoints/memo.py

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
from app.schemas.base import ResponseBase
22
from app.schemas.memo import MemoCreate, MemoResponse, MemoUpdate
33
from app.services.memo import (
4-
select_today_memos_service,
5-
select_month_memos_service,
6-
select_month_memos_by_category_id_service,
4+
select_memos_by_period,
75
add_memo_service,
86
edit_memo_service,
97
delete_memo_service,
@@ -13,52 +11,20 @@
1311
from sqlalchemy.ext.asyncio import AsyncSession
1412
from typing import List
1513
from uuid import UUID
14+
from datetime import date
1615

1716
router = APIRouter()
1817

1918

2019
@router.get("/", response_model=ResponseBase[List[MemoResponse]])
21-
async def get_today_memos(
22-
user_id: UUID, db: AsyncSession = Depends(get_db)
23-
) -> ResponseBase[List[MemoResponse]]:
24-
try:
25-
memos = await select_today_memos_service(db, user_id)
26-
return ResponseBase(status_code=status.HTTP_200_OK, data=memos)
27-
except HTTPException as e:
28-
return ResponseBase(status_code=e.status_code, error=e.detail)
29-
except Exception as e:
30-
return ResponseBase(
31-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, error=str(e)
32-
)
33-
34-
35-
@router.get("/", response_model=ResponseBase[List[MemoResponse]])
36-
async def get_month_memos(
37-
user_id: UUID, year: int, month: int, db: AsyncSession = Depends(get_db)
38-
) -> ResponseBase[List[MemoResponse]]:
39-
try:
40-
memos = await select_month_memos_service(db, user_id, year, month)
41-
return ResponseBase(status_code=status.HTTP_200_OK, data=memos)
42-
except HTTPException as e:
43-
return ResponseBase(status_code=e.status_code, error=e.detail)
44-
except Exception as e:
45-
return ResponseBase(
46-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, error=str(e)
47-
)
48-
49-
50-
@router.get("/", response_model=ResponseBase[List[MemoResponse]])
51-
async def get_month_memos_by_category(
20+
async def get_memos_by_period(
5221
user_id: UUID,
53-
category_id: UUID,
54-
year: int,
55-
month: int,
22+
start_date: date,
23+
end_date: date,
5624
db: AsyncSession = Depends(get_db),
5725
) -> ResponseBase[List[MemoResponse]]:
5826
try:
59-
memos = await select_month_memos_by_category_id_service(
60-
db, user_id, category_id, year, month
61-
)
27+
memos = await select_memos_by_period(db, user_id, start_date, end_date)
6228
return ResponseBase(status_code=status.HTTP_200_OK, data=memos)
6329
except HTTPException as e:
6430
return ResponseBase(status_code=e.status_code, error=e.detail)

app/api/v1/endpoints/progress.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ async def post_progress(
3636

3737
@router.get("/", response_model=ResponseBase[List[ProgressResponse]])
3838
async def get_all_progresses(
39+
user_id: UUID,
3940
db: AsyncSession = Depends(get_db),
4041
) -> ResponseBase[List[ProgressResponse]]:
4142
try:
42-
progresses = await select_all_progresses(db)
43+
progresses = await select_all_progresses(db, user_id)
4344
return ResponseBase(status_code=status.HTTP_200_OK, data=progresses)
4445
except HTTPException as e:
4546
return ResponseBase(status_code=e.status_code, error=e.detail)

app/api/v1/endpoints/todo.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from fastapi import APIRouter, Depends, HTTPException, status
1+
from datetime import date
2+
from fastapi import APIRouter, Depends, HTTPException, status, Query
23
from sqlalchemy.ext.asyncio import AsyncSession
34
from typing import List
45
from uuid import UUID
@@ -8,6 +9,7 @@
89
add_todo,
910
select_all_todos,
1011
select_todo_by_id,
12+
select_todos_by_period,
1113
update_todo_by_id,
1214
delete_todo_service,
1315
)
@@ -54,6 +56,26 @@ async def get_all_todos(
5456
)
5557

5658

59+
# 날짜 범위로 할 일 조회
60+
@router.get("/period", response_model=ResponseBase[List[TodoResponse]])
61+
async def get_todos_by_period(
62+
user_id: UUID,
63+
startDate: date = Query(..., description="시작 날짜 (YYYY-MM-DD)"),
64+
endDate: date = Query(..., description="종료 날짜 (YYYY-MM-DD)"),
65+
db: AsyncSession = Depends(get_db),
66+
) -> ResponseBase[List[TodoResponse]]:
67+
try:
68+
todos = await select_todos_by_period(db, user_id, startDate, endDate)
69+
return ResponseBase(status_code=status.HTTP_200_OK, data=todos)
70+
except HTTPException as e:
71+
return ResponseBase(status_code=e.status_code, error=e.detail)
72+
except Exception as e:
73+
return ResponseBase(
74+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
75+
error=str(e),
76+
)
77+
78+
5779
# 특정 할 일 조회
5880
@router.get("/{todo_id}", response_model=ResponseBase[TodoResponse])
5981
async def get_todo_by_id(

app/api/v1/router.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from uuid import main
12
from fastapi import APIRouter
23
from app.api.v1.endpoints import (
34
auth,
@@ -13,6 +14,7 @@
1314
chat,
1415
progress,
1516
todo,
17+
main,
1618
)
1719

1820
router = APIRouter()
@@ -53,15 +55,16 @@
5355
)
5456
router.include_router(
5557
chat.router,
56-
prefix="/users/{user_id}",
58+
prefix="/users/{user_id}/categories/{category_id}/chats",
5759
tags=["chats"],
5860
)
5961
router.include_router(
60-
progress.router, prefix="/ users/{user_id}/progresses", tags=["Progress"]
62+
progress.router, prefix="/users/{user_id}/progresses", tags=["Progress"]
6163
)
62-
router.include_router(todo.router, prefix="/todos", tags=["todos"])
64+
router.include_router(todo.router, prefix="/users/{user_id}/todos", tags=["todos"])
6365
router.include_router(
6466
todo.router,
6567
prefix="/users/{user_id}/categories/{category_id}/todos",
6668
tags=["todos"],
6769
)
70+
router.include_router(main.router, prefix="/users/{user_id}", tags=["main"])

app/crud/memo.py

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from sqlalchemy import select, delete
22
from sqlalchemy.ext.asyncio import AsyncSession
3+
from sqlalchemy.orm import selectinload
34
from uuid import UUID
4-
from datetime import datetime
5+
from datetime import date
56
from typing import List
67
from app.models.category import Memo
78
from app.schemas.memo import MemoCreate, MemoResponse, MemoUpdate
@@ -41,28 +42,19 @@ async def read_memo_by_id(
4142
return db_memo.scalars().first()
4243

4344

44-
async def read_memos_by_date(
45-
db: AsyncSession, user_id: UUID, date: datetime
46-
) -> List[MemoResponse]:
47-
db_memo = await db.execute(
48-
select(Memo).where(
49-
Memo.user_id == user_id, Memo.start_date <= date, date <= Memo.end_date
50-
)
51-
)
52-
return db_memo.scalars().all()
53-
54-
5545
async def read_memos_by_period(
56-
db: AsyncSession, user_id: UUID, start_date: datetime, end_date: datetime
46+
db: AsyncSession, user_id: UUID, start_date: date, end_date: date
5747
) -> List[MemoResponse]:
5848
db_memo = await db.execute(
59-
select(Memo).where(
49+
select(Memo)
50+
.options(selectinload(Memo.category))
51+
.where(
6052
Memo.user_id == user_id,
61-
Memo.start_date >= start_date,
62-
Memo.end_date <= end_date,
53+
Memo.start_date <= end_date,
54+
Memo.end_date >= start_date,
6355
)
6456
)
65-
return db_memo.scalars().all()
57+
return db_memo.unique().scalars().all()
6658

6759

6860
async def read_memos_by_category_id(
@@ -74,24 +66,6 @@ async def read_memos_by_category_id(
7466
return db_memo.scalars().all()
7567

7668

77-
async def read_memos_by_period_and_category_id(
78-
db: AsyncSession,
79-
user_id: UUID,
80-
category_id: UUID,
81-
start_date: datetime,
82-
end_date: datetime,
83-
) -> List[MemoResponse]:
84-
db_memo = await db.execute(
85-
select(Memo).where(
86-
Memo.user_id == user_id,
87-
Memo.category_id == category_id,
88-
Memo.start_date >= start_date,
89-
Memo.end_date <= end_date,
90-
)
91-
)
92-
return db_memo.scalars().all()
93-
94-
9569
async def update_memo(
9670
db: AsyncSession, user_id: UUID, memo_id: UUID, memo_data: MemoUpdate
9771
) -> MemoResponse:

app/crud/progress.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from sqlalchemy import select, delete
33
from sqlalchemy.ext.asyncio import AsyncSession
44
from uuid import UUID
5-
5+
from sqlalchemy.orm import selectinload
66
from app.models.category import Progress
77
from app.schemas.progress import ProgressCreate, ProgressUpdate, ProgressResponse
88

@@ -27,15 +27,23 @@ async def create_progress(
2727
async def read_all_progresses(
2828
db: AsyncSession, user_id: UUID
2929
) -> List[ProgressResponse]:
30-
result = await db.execute(select(Progress).where(Progress.user_id == user_id))
30+
result = await db.execute(
31+
select(Progress)
32+
.options(selectinload(Progress.category))
33+
.where(Progress.user_id == user_id)
34+
)
3135
return result.scalars().all()
3236

3337

3438
# ID로 진행 조회
3539
async def read_progress_by_id(
3640
db: AsyncSession, progress_id: UUID
3741
) -> Optional[ProgressResponse]:
38-
result = await db.execute(select(Progress).where(Progress.id == progress_id))
42+
result = await db.execute(
43+
select(Progress)
44+
.options(selectinload(Progress.category))
45+
.where(Progress.id == progress_id)
46+
)
3947
return result.scalars().first()
4048

4149

app/crud/todo.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from app.models.week import Week
2-
from sqlalchemy import select, delete
2+
from sqlalchemy import select, delete, and_
33
from sqlalchemy.ext.asyncio import AsyncSession
44
from uuid import UUID
55
from typing import List, Optional
66
from app.models.category import Todo
77
from app.schemas.todo import TodoCreate, TodoUpdate, TodoResponse
88
from sqlalchemy.orm import selectinload
99
from app.utils.to_snake_case import camel_to_snake
10+
from datetime import date
1011

1112

1213
# 할 일 생성
@@ -87,6 +88,29 @@ async def read_raw_todo_by_id(
8788
return result.scalars().first()
8889

8990

91+
# 날짜 범위로 할 일 조회 (기본)
92+
async def read_todos_by_period(
93+
db: AsyncSession, user_id: UUID, start_date: date, end_date: date
94+
) -> List[Todo]:
95+
96+
# 해당 기간과 겹치는 모든 Todo 가져오기 (간소화된 조건)
97+
query = (
98+
select(Todo)
99+
.options(selectinload(Todo.weeks), selectinload(Todo.category))
100+
.where(
101+
Todo.user_id == user_id,
102+
# 모든 겹침 케이스를 처리하는 단일 조건
103+
Todo.start_date <= end_date,
104+
Todo.end_date >= start_date,
105+
)
106+
)
107+
108+
result = await db.execute(query)
109+
110+
# unique -> 조인 쿼리 시 중복 데이터 제거
111+
return result.unique().scalars().all()
112+
113+
90114
# 특정 유저의 특정 카테고리에 속한 할 일 목록 조회
91115
async def read_todos_by_user_and_category(
92116
db: AsyncSession, user_id: UUID, category_id: UUID

app/schemas/main.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from app.schemas.todo import TodoResponse
2+
from app.schemas.memo import MemoResponse
3+
from app.schemas.base import BaseModel
4+
from typing import List
5+
6+
7+
class TodosAndMemosResponse(BaseModel):
8+
todos: List[TodoResponse]
9+
memos: List[MemoResponse]

0 commit comments

Comments
 (0)