Skip to content

Commit 7933a6d

Browse files
sunbagelemilyniee
andcommitted
Refactoring scheduling schema
Co-authored-by: emilyniee <[email protected]>
1 parent e0284c6 commit 7933a6d

File tree

14 files changed

+165
-112
lines changed

14 files changed

+165
-112
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from sqlalchemy import Column, ForeignKey, Table
2+
3+
from .Base import Base
4+
5+
# AvailableTimes as a pure association table
6+
# only exists to establish a relationship between Users and Time Blocks
7+
# a User has an Availability which is composed of many time blocks
8+
available_times = Table(
9+
"available_times",
10+
Base.metadata,
11+
Column("time_block_id", ForeignKey("time_blocks.id"), primary_key=True),
12+
Column("user_id", ForeignKey("users.id"), primary_key=True),
13+
)

backend/app/models/Schedule.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import uuid
2-
3-
from sqlalchemy import Column, DateTime, Enum, Interval, Integer, ForeignKey
1+
from sqlalchemy import Column, DateTime, ForeignKey, Integer, Interval
42
from sqlalchemy.orm import relationship
5-
from app.models.ScheduleStatus import ScheduleStatus
63

74
from .Base import Base
85

@@ -11,8 +8,8 @@ class Schedule(Base):
118
__tablename__ = "schedules"
129

1310
id = Column(Integer, primary_key=True)
14-
scheduled_time = Column(DateTime, nullable = True)
15-
duration = Column(Interval, nullable = True)
11+
scheduled_time = Column(DateTime, nullable=True)
12+
duration = Column(Interval, nullable=True)
1613
status_id = Column(Integer, ForeignKey("schedule_status.id"), nullable=False)
1714

1815
status = relationship("ScheduleStatus")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from sqlalchemy import Column, ForeignKey, Table
2+
3+
from .Base import Base
4+
5+
# SuggestedTimes as a pure association table
6+
# only exists to establish a relationship between Matches and Time Blocks (many to many)
7+
suggested_times = Table(
8+
"suggested_times",
9+
Base.metadata,
10+
# composite key of match and time block
11+
Column("match_id", ForeignKey("matches.id"), primary_key=True),
12+
Column("time_block_id", ForeignKey("time_blocks.id"), primary_key=True),
13+
)

backend/app/models/TimeBlock.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import uuid
2-
3-
from sqlalchemy import Column, DateTime, ForeignKey, Integer
4-
from sqlalchemy.dialects.postgresql import UUID
1+
from sqlalchemy import Column, DateTime, Integer
52
from sqlalchemy.orm import relationship
63

74
from .Base import Base
@@ -10,9 +7,19 @@
107
class TimeBlock(Base):
118
__tablename__ = "time_blocks"
129
id = Column(Integer, primary_key=True)
13-
schedule_id = Column(Integer, ForeignKey("schedules.id"), nullable = False)
1410
start_time = Column(DateTime)
15-
end_time = Column(DateTime)
1611

17-
schedule = relationship("Schedule", back_populates="time_blocks")
12+
# if a match has been confirmed on this time block, this is non null
13+
confirmed_match = relationship(
14+
"Match", back_populates="confirmed_time", uselist=False
15+
)
16+
17+
# suggested matches
18+
suggested_matches = relationship(
19+
"Match", secondary="suggested_times", back_populates="suggested_time_blocks"
20+
)
1821

22+
# the availability that the timeblock is a part of for a given user
23+
users = relationship(
24+
"User", secondary="available_times", back_populates="availability"
25+
)

backend/app/models/User.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@ class User(Base):
1717
auth_id = Column(String, nullable=False)
1818

1919
role = relationship("Role")
20+
21+
# time blocks in an availability for a user
22+
availability = relationship(
23+
"TimeBlock", secondary="available_times", back_populates="users"
24+
)

backend/app/models/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
# when autogenerating new migration
1010
from .Base import Base
1111
from .Role import Role
12-
from .User import User
1312
from .Schedule import Schedule
1413
from .ScheduleStatus import ScheduleStatus
1514
from .TimeBlock import TimeBlock
15+
from .User import User
1616

1717
# Used to avoid import errors for the models
18-
__all__ = ["Base", "User", "Role", "Schedule", "ScheduleStatus", "TimeBlock" ]
18+
__all__ = ["Base", "User", "Role", "Schedule", "ScheduleStatus", "TimeBlock"]
1919

2020
log = logging.getLogger(LOGGER_NAME("models"))
2121

backend/app/routes/schedule.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
21
from fastapi import APIRouter, Depends, HTTPException
32
from sqlalchemy.orm import Session
43

54
from app.schemas.schedule import ScheduleCreateRequest, ScheduleEntity
65
from app.services.implementations.schedule_service import ScheduleService
76
from app.utilities.db_utils import get_db
87

9-
10-
118
router = APIRouter(
129
prefix="/schedules",
1310
tags=["schedules"],
@@ -17,9 +14,11 @@
1714
def get_schedule_service(db: Session = Depends(get_db)):
1815
return ScheduleService(db)
1916

17+
2018
@router.post("/", response_model=ScheduleEntity)
2119
async def create_schedule(
22-
schedule: ScheduleCreateRequest, schedule_service: ScheduleService = Depends(get_schedule_service)
20+
schedule: ScheduleCreateRequest,
21+
schedule_service: ScheduleService = Depends(get_schedule_service),
2322
):
2423
try:
2524
created_schedule = await schedule_service.create_schedule(schedule)
@@ -29,4 +28,3 @@ async def create_schedule(
2928
except Exception as e:
3029
print(e)
3130
raise HTTPException(status_code=500, detail=str(e))
32-

backend/app/schemas/schedule.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
from enum import Enum
2-
from uuid import UUID
31
from datetime import datetime, timedelta
2+
from enum import Enum
43
from typing import List, Optional
5-
from app.schemas.time_block import TimeBlockBase, TimeBlockId, TimeBlockFull
4+
from uuid import UUID
5+
66
from pydantic import BaseModel, ConfigDict
77

8+
from app.schemas.time_block import TimeBlockBase, TimeBlockFull, TimeBlockId
89

910

1011
class ScheduleStatus(str, Enum):
@@ -19,10 +20,12 @@ def to_schedule_status_id(cls, state: "ScheduleStatus") -> int:
1920
cls.PENDING_VOLUNTEER: 1,
2021
cls.PENDING_PARTICIPANT: 2,
2122
cls.SCHEDULED: 3,
22-
cls.COMPLETED: 4}
23+
cls.COMPLETED: 4,
24+
}
2325

2426
return status_map[state]
2527

28+
2629
class ScheduleBase(BaseModel):
2730
scheduled_time: Optional[datetime]
2831
duration: Optional[timedelta]
@@ -34,19 +37,22 @@ class ScheduleEntity(ScheduleBase):
3437

3538
model_config = ConfigDict(from_attributes=True)
3639

37-
# Provides both Schedule data and full TimeBlock data
40+
41+
# Provides both Schedule data and full TimeBlock data
3842
class ScheduleGetResponse(ScheduleEntity):
3943
time_blocks: List[TimeBlockFull]
4044

45+
4146
# List of Start and End times to Create a Schedule with
4247
class ScheduleCreateRequest(BaseModel):
4348
time_blocks: List[TimeBlockBase]
4449

50+
4551
class ScheduleUpdateRequest(BaseModel):
4652
schedule_id: UUID
4753
time_blocks: List[TimeBlockBase]
4854

55+
4956
class ScheduleDeleteRequest(BaseModel):
5057
schedule_id: UUID
5158
time_blocks: List[TimeBlockId]
52-

backend/app/schemas/time_block.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1-
2-
from pydantic import BaseModel
31
from datetime import datetime
42
from uuid import UUID
53

4+
from pydantic import BaseModel
5+
6+
67
class TimeBlockBase(BaseModel):
78
start_time: datetime
89
end_time: datetime
910

11+
1012
class TimeBlockId(BaseModel):
1113
id: UUID
1214

15+
1316
class TimeBlockFull(TimeBlockBase, TimeBlockId):
14-
'''
17+
"""
1518
Combines TimeBlockBase and TimeBlockId.
1619
Represents a full time block with an ID and time range.
17-
'''
20+
"""
21+
1822
pass
1923

24+
2025
class TimeBlockEntity(BaseModel):
2126
id: UUID
2227
schedule_id: int

backend/app/server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from fastapi import FastAPI
77

88
from . import models
9-
from .routes import send_email, user, schedule
9+
from .routes import schedule, send_email, user
1010
from .utilities.constants import LOGGER_NAME
1111
from .utilities.firebase_init import initialize_firebase
1212
from .utilities.ses.ses_init import ensure_ses_templates
@@ -33,6 +33,7 @@ async def lifespan(_: FastAPI):
3333
app.include_router(schedule.router)
3434
app.include_router(send_email.router)
3535

36+
3637
@app.get("/")
3738
def read_root():
3839
log.info("Hello World")

0 commit comments

Comments
 (0)