Skip to content

Commit 7926e48

Browse files
committed
add position to application pkey & implement crud
1 parent cad1c90 commit 7926e48

File tree

4 files changed

+67
-22
lines changed

4 files changed

+67
-22
lines changed

src/alembic/versions/243190df5588_create_election_tables.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ def upgrade() -> None:
4747
"election_nominee_application",
4848
sa.Column("computing_id", sa.String(length=32), nullable=False),
4949
sa.Column("nominee_election", sa.String(length=64), nullable=False),
50+
sa.Column("position", sa.String(length=64), nullable=False),
5051
sa.Column("speech", sa.Text(), nullable=True),
51-
sa.Column("position", sa.String(length=64), nullable=True),
5252
sa.ForeignKeyConstraint(["computing_id"], ["election_nominee.computing_id"]),
5353
sa.ForeignKeyConstraint(["nominee_election"], ["election.slug"]),
54-
sa.PrimaryKeyConstraint("computing_id", "nominee_election")
54+
sa.PrimaryKeyConstraint("computing_id", "nominee_election", "position")
5555
)
5656

5757

src/elections/crud.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ async def update_election(db_session: AsyncSession, new_election: Election) -> b
3434
You attempting to change the name or slug will fail. Instead, you must create a new election.
3535
"""
3636
target_slug = new_election.slug
37+
# TODO: does this check need to be performed?
3738
target_election = await get_election(db_session, target_slug)
3839

3940
if target_election is None:
@@ -58,35 +59,55 @@ async def delete_election(db_session: AsyncSession, slug: str) -> None:
5859
.where(Election.slug == slug)
5960
)
6061

62+
# TODO: switch to only using one of application or registration
6163
async def get_all_registrations(
6264
db_session: AsyncSession,
6365
computing_id: str,
6466
election_slug: str
6567
) -> list[NomineeApplication] | None:
66-
raise NotImplementedError("todo")
68+
registrations = (await db_session.scalars(
69+
sqlalchemy
70+
.select(NomineeApplication)
71+
.where(
72+
NomineeApplication.computing_id == computing_id
73+
and NomineeApplication.election_slug == election_slug
74+
)
75+
)).all()
76+
return registrations
6777

6878
async def add_registration(
6979
db_session: AsyncSession,
7080
initial_application: NomineeApplication
71-
) -> NomineeApplication:
72-
raise NotImplementedError("todo")
81+
):
82+
db_session.add(initial_application)
7383

7484
async def update_registration(
7585
db_session: AsyncSession,
7686
initial_application: NomineeApplication
77-
) -> NomineeApplication:
78-
raise NotImplementedError("todo")
87+
):
88+
await db_session.execute(
89+
sqlalchemy
90+
.update(NomineeApplication)
91+
.where(
92+
NomineeApplication.computing_id == initial_application.computing_id
93+
and NomineeApplication.nominee_election == initial_application.nominee_election
94+
and NomineeApplication.position == initial_application.position
95+
)
96+
.values(initial_application.to_update_dict())
97+
)
7998

8099
async def delete_registration(
81100
db_session: AsyncSession,
82101
computing_id: str,
83-
election_slug: str
102+
election_slug: str,
103+
position: str
84104
):
85105
await db_session.execute(
86106
sqlalchemy
87107
.delete(NomineeApplication)
88108
.where(
89109
NomineeApplication.computing_id == computing_id
90110
and NomineeApplication.nominee_election == election_slug
111+
and NomineeApplication.position == position
91112
)
92113
)

src/elections/tables.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,17 +109,29 @@ class NomineeApplication(Base):
109109
# TODO: add index for nominee_election?
110110
computing_id = Column(ForeignKey("election_nominee.computing_id"), primary_key=True)
111111
nominee_election = Column(ForeignKey("election.slug"), primary_key=True)
112+
position = Column(String(64), primary_key=True)
113+
112114
speech = Column(Text)
113-
position = Column(String(64))
114115

115116
__table_args__ = (
116-
PrimaryKeyConstraint(computing_id, nominee_election),
117+
PrimaryKeyConstraint(computing_id, nominee_election, position),
117118
)
118119

119120
def serializable_dict(self) -> dict:
120121
return {
121122
"computing_id": self.computing_id,
122123
"nominee_election": self.nominee_election,
124+
"position": self.position,
125+
123126
"speech": self.speech,
127+
}
128+
129+
def to_update_dict(self) -> dict:
130+
return {
131+
"computing_id": self.computing_id,
132+
"nominee_election": self.nominee_election,
124133
"position": self.position,
134+
135+
"speech": self.speech,
125136
}
137+

src/elections/urls.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ async def delete_election(
257257
"/register/{election_name:str}",
258258
description="get your election registration(s)"
259259
)
260-
async def get_election_registration(
260+
async def get_election_registrations(
261261
request: Request,
262262
db_session: database.DBSession,
263263
election_name: str
@@ -289,19 +289,25 @@ async def get_election_registration(
289289

290290
@router.post(
291291
"/register/{election_name:str}",
292-
description="register for the election, but doesn't set any speeches or positions."
292+
description="register for a specific position in this election, but doesn't set a speech"
293293
)
294294
async def register_in_election(
295295
request: Request,
296296
db_session: database.DBSession,
297-
election_name: str
297+
election_name: str,
298+
position: str
298299
):
299300
logged_in, _, computing_id = await is_logged_in(request, db_session)
300301
if not logged_in:
301302
raise HTTPException(
302303
status_code=status.HTTP_401_UNAUTHORIZED,
303304
detail="must be logged in to register in election"
304305
)
306+
elif position not in OfficerPosition.position_list():
307+
raise HTTPException(
308+
status_code=status.HTTP_400_BAD_REQUEST,
309+
detail=f"invalid position {position}"
310+
)
305311

306312
election_slug = _slugify(election_name)
307313
if await get_election(db_session, election_slug) is None:
@@ -321,20 +327,20 @@ async def register_in_election(
321327
await elections.crud.add_registration(db_session, NomineeApplication(
322328
computing_id=computing_id,
323329
nominee_election=election_slug,
324-
speech=None,
325-
position=None,
330+
position=position,
331+
speech=None
326332
))
327333

328334
@router.patch(
329335
"/register/{election_name:str}",
330-
description="update your registration for an election"
336+
description="update your speech for a specific position for an election"
331337
)
332338
async def update_registration(
333339
request: Request,
334340
db_session: database.DBSession,
335341
election_name: str,
336-
speech: str | None,
337342
position: str,
343+
speech: str | None,
338344
):
339345
logged_in, _, computing_id = await is_logged_in(request, db_session)
340346
if not logged_in:
@@ -344,7 +350,7 @@ async def update_registration(
344350
)
345351
elif position not in OfficerPosition.position_list():
346352
raise HTTPException(
347-
status_code=status.HTTP_401_UNAUTHORIZED,
353+
status_code=status.HTTP_400_BAD_REQUEST,
348354
detail=f"invalid position {position}"
349355
)
350356

@@ -363,25 +369,31 @@ async def update_registration(
363369
await elections.crud.update_registration(db_session, NomineeApplication(
364370
computing_id=computing_id,
365371
nominee_election=election_slug,
366-
speech=speech,
367372
position=position,
373+
speech=speech
368374
))
369375

370376
@router.delete(
371377
"/register/{election_name:str}",
372-
description="revoke your registration in the election"
378+
description="revoke your registration for a specific position in this election"
373379
)
374380
async def delete_registration(
375381
request: Request,
376382
db_session: database.DBSession,
377-
election_name: str
383+
election_name: str,
384+
position: str,
378385
):
379386
logged_in, _, computing_id = await is_logged_in(request, db_session)
380387
if not logged_in:
381388
raise HTTPException(
382389
status_code=status.HTTP_401_UNAUTHORIZED,
383390
detail="must be logged in to delete election registeration"
384391
)
392+
elif position not in OfficerPosition.position_list():
393+
raise HTTPException(
394+
status_code=status.HTTP_400_BAD_REQUEST,
395+
detail=f"invalid position {position}"
396+
)
385397

386398
election_slug = _slugify(election_name)
387399
if await get_election(db_session, election_slug) is None:
@@ -395,4 +407,4 @@ async def delete_registration(
395407
detail="you are not yet registered in this election"
396408
)
397409

398-
await elections.crud.delete_registration(db_session, computing_id, election_slug)
410+
await elections.crud.delete_registration(db_session, computing_id, election_slug, position)

0 commit comments

Comments
 (0)