Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c3a33a6
init: setup
arunPdl02 May 9, 2026
d517c24
feat: created sql table schema
arunPdl02 May 9, 2026
9ac1ab5
feat: create DTO models for events api
arunPdl02 May 9, 2026
ea8d416
bug: correct type for mapped_column eid, fixed column type for all th…
arunPdl02 May 9, 2026
e03cede
refactor: updated the DateTime to have timezone
arunPdl02 May 10, 2026
108cd5b
feat: completed alembic db migration for events table
arunPdl02 May 10, 2026
700f13f
feat: created GET(/event) API endpoint
arunPdl02 May 11, 2026
784e384
feat: added API and db function for get events for given year
arunPdl02 May 14, 2026
0d1dcb1
feat: added API and db function for get events for given year and month
arunPdl02 May 14, 2026
9f03e92
feat: implement post API for /event route
arunPdl02 May 14, 2026
91aeb59
feat: implement delete API for /event/<eid> route
arunPdl02 May 14, 2026
43ec487
fix: correct event response logic
arunPdl02 May 14, 2026
d910593
feat(event): implement patch API for event/<eid> endpoint
arunPdl02 May 14, 2026
7f82f03
feat:add constraints for start and end dates/times
arunPdl02 May 16, 2026
8caf569
feat: add integrity check for requests
arunPdl02 May 16, 2026
3324092
refactor: change col names of event_info table from start_date to rep…
arunPdl02 May 20, 2026
d7c4dd0
refactor: removed EventPublic Pydantic model and using just Event mod…
arunPdl02 May 20, 2026
7cdbd0e
chore: removed comments and unused code
arunPdl02 May 20, 2026
f7d8c60
fix: create, update and delete now requires site admin permission
arunPdl02 May 21, 2026
6b2eaa8
chore: cleanup code
arunPdl02 May 21, 2026
c9a319b
refactor: validation logic now handled by pydantic model for patch
arunPdl02 May 21, 2026
240774e
bug: caught validation error from pydantic and return proper status code
arunPdl02 May 21, 2026
7a06cac
fix: uncommented dependencies
arunPdl02 May 21, 2026
b0d457b
chore: ran ruff fix
arunPdl02 May 21, 2026
e52ccc2
refactor: changed the column name of repeat to frequency and the type…
arunPdl02 May 25, 2026
1b064f6
chore: ran ruff fix
arunPdl02 May 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import nominees.tables
import officers.tables
import candidates.tables
import event.tables
from alembic import context

# this is the Alembic Config object, which provides
Expand Down
42 changes: 42 additions & 0 deletions src/alembic/versions/f4c493a24799_create_event_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""create_event_table

Revision ID: f4c493a24799
Revises: 0a2c458d1ddd
Create Date: 2026-05-15 23:00:45.680647

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'f4c493a24799'
down_revision: Union[str, None] = '0a2c458d1ddd'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('event_info',
sa.Column('eid', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('name', sa.String(length=64), nullable=False),
sa.Column('start_time', sa.DateTime(timezone=True), nullable=False),
sa.Column('end_time', sa.DateTime(timezone=True), nullable=False),
sa.Column('repeat', sa.String(length=64), nullable=False),
sa.Column('start_date', sa.Date(), nullable=True),
sa.Column('end_date', sa.Date(), nullable=True),
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated
sa.CheckConstraint('start_date < end_date', name=op.f('ck_event_info_check_start_date_before_end_date')),
sa.CheckConstraint('start_time < end_time', name=op.f('ck_event_info_check_start_time_before_end_time')),
sa.PrimaryKeyConstraint('eid', name=op.f('pk_event_info'))
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('event_info')
# ### end Alembic commands ###
79 changes: 79 additions & 0 deletions src/event/crud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from collections.abc import Sequence

from sqlalchemy import select, or_, and_, extract, delete
from sqlalchemy.ext.asyncio import AsyncSession

from event.tables import EventDB

from datetime import datetime, date

Check failure on line 8 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (I001)

src/event/crud.py:1:1: I001 Import block is un-sorted or un-formatted help: Organize imports


async def get_all_events(
db_session: AsyncSession
) -> Sequence[EventDB]:
events = (await db_session.scalars(select(EventDB))).all()
return events


async def get_events_for_this_year(
db_session: AsyncSession,
year: int,
) -> Sequence[EventDB]:
events = (await db_session.scalars(select(EventDB).where
(
or_(
extract('year', EventDB.start_time) == year,

Check failure on line 25 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (W291)

src/event/crud.py:25:57: W291 Trailing whitespace help: Remove trailing whitespace

Check failure on line 25 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (Q000)

src/event/crud.py:25:21: Q000 Single quotes found but double quotes preferred help: Replace single quotes with double quotes
extract('year', EventDB.end_time) == year

Check failure on line 26 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (Q000)

src/event/crud.py:26:21: Q000 Single quotes found but double quotes preferred help: Replace single quotes with double quotes
)
))).all()
return events

async def get_events_for_this_year_month(
db_session: AsyncSession,
year: int,
month: int,
) -> Sequence[EventDB]:
events = (
await db_session.scalars(
select(EventDB).where(
or_(
and_(
extract('year', EventDB.start_time) == year,

Check failure on line 41 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (Q000)

src/event/crud.py:41:33: Q000 Single quotes found but double quotes preferred help: Replace single quotes with double quotes
extract('month', EventDB.start_time) == month

Check failure on line 42 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (Q000)

src/event/crud.py:42:33: Q000 Single quotes found but double quotes preferred help: Replace single quotes with double quotes
),
and_(
extract('year', EventDB.end_time) == year,

Check failure on line 45 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (Q000)

src/event/crud.py:45:33: Q000 Single quotes found but double quotes preferred help: Replace single quotes with double quotes
extract('month', EventDB.end_time) == month

Check failure on line 46 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (Q000)

src/event/crud.py:46:33: Q000 Single quotes found but double quotes preferred help: Replace single quotes with double quotes
)
)
)
)
).all()
return events


async def get_event_by_eid(
db_session: AsyncSession,
eid: int
) -> EventDB | None:
return (await db_session.execute(
select(EventDB).where(EventDB.eid == eid)
)).scalar_one_or_none()


async def create_event(
db_session: AsyncSession,
info: EventDB
):
db_session.add(info)


async def delete_event(
db_session: AsyncSession,
eid: int
):
result = await db_session.execute(delete(EventDB).where(
EventDB.eid == eid
))
# Return the number of rows affected
return result.rowcount

Check failure on line 79 in src/event/crud.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (W292)

src/event/crud.py:79:27: W292 No newline at end of file help: Add trailing newline
69 changes: 69 additions & 0 deletions src/event/models.py
Comment thread
arunPdl02 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from pydantic import BaseModel, ConfigDict, model_validator
import datetime

Check failure on line 2 in src/event/models.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (I001)

src/event/models.py:1:1: I001 Import block is un-sorted or un-formatted help: Organize imports

class Event(BaseModel):
model_config = ConfigDict(from_attributes=True)
eid: int
name: str
start_time: datetime.datetime
end_time: datetime.datetime
description: str | None = None
repeat: str | None = None
start_date: datetime.date | None = None
end_date: datetime.date | None = None
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated

class EventPublic(BaseModel):
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated
model_config = ConfigDict(from_attributes=True)
name: str
start_time: datetime.datetime
end_time: datetime.datetime
description: str | None = None
repeat: str | None = None
start_date: datetime.date | None = None
end_date: datetime.date | None = None
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated

class EventCreate(BaseModel):
name: str
start_time: datetime.datetime
end_time: datetime.datetime
description: str | None = None
repeat: str | None = None
start_date: datetime.date | None = None
end_date: datetime.date | None = None
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated

@model_validator(mode="after")
def validate_time_range(self) -> "EventCreate":
if self.start_time >= self.end_time:
raise ValueError("The event start must be before the event end")

if self.start_date and self.end_date:
if self.start_date > self.end_date:
raise ValueError("The event repeat start date must be before the end date")

if self.start_date and not self.end_date:
raise ValueError("The event can't have start date but not end date")

if not self.start_date and self.end_date:
raise ValueError("The event can't have end date but not start date")

return self

class EventUpdate(BaseModel):
name: str | None = None
start_time: datetime.datetime | None = None
end_time: datetime.datetime | None = None
description: str | None = None
repeat: str | None = None
start_date: datetime.date | None = None
end_date: datetime.date | None = None
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated

@model_validator(mode="after")
def validate_time_range(self) -> "EventUpdate":
if self.start_time and self.end_time:
if self.start_time > self.end_time:
raise ValueError("The event start time must be before end time")
return self
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated

class EventDelete(BaseModel):
result: bool
eid: int
70 changes: 70 additions & 0 deletions src/event/tables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from sqlalchemy import (
Integer,
String,
DateTime,
Text,
Date,
CheckConstraint
)
from sqlalchemy.orm import Mapped, mapped_column

from database import Base
from datetime import datetime, date

class EventDB(Base):
__tablename__ = "event_info"

eid: Mapped[int] = mapped_column(
Integer,
primary_key=True,
autoincrement=True
)
description: Mapped[str] = mapped_column(
Text,
nullable=True
)
name: Mapped[str] = mapped_column(
String(64)
)
start_time: Mapped[datetime] = mapped_column(
DateTime(timezone=True)
)
end_time: Mapped[datetime] = mapped_column(
DateTime(timezone=True)
)
repeat: Mapped[str] = mapped_column(
String(64)
)
start_date: Mapped[date] = mapped_column(
Date,
nullable=True
)
end_date: Mapped[date] = mapped_column(
Date,
nullable=True
)
Comment thread
arunPdl02 marked this conversation as resolved.
Outdated

__table_args__ = (
CheckConstraint(
'start_time < end_time',
name='check_start_time_before_end_time'
),
CheckConstraint(
'start_date < end_date',
name='check_start_date_before_end_date'
)
)


def serialize(self) -> dict:
return{
"eid": self.eid,
"name": self.name,
"description": self.description,
"start_time": self.start_time,
"end_time": self.end_time,
"start_date": self.start_date,
"end_date": self.end_date,
}

Comment thread
arunPdl02 marked this conversation as resolved.
Outdated

Loading
Loading