Skip to content

Commit 13f51bb

Browse files
committed
fix: election tests now work
* refactored how the election officers are looked up * changed the Nominee put back to a patch * made election tests work with the new testing setup
1 parent b6fbde6 commit 13f51bb

File tree

7 files changed

+395
-362
lines changed

7 files changed

+395
-362
lines changed

src/nominees/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
NomineeInfoUpdateParams,
99
)
1010
from nominees.tables import NomineeInfo
11-
from utils.shared_models import DetailModel, SuccessResponse
11+
from utils.shared_models import DetailModel
1212
from utils.urls import AdminTypeEnum, admin_or_raise
1313

1414
router = APIRouter(
@@ -89,7 +89,7 @@ async def delete_nominee_info(request: Request, db_session: database.DBSession,
8989
await db_session.commit()
9090

9191

92-
@router.put(
92+
@router.patch(
9393
"/{computing_id:str}",
9494
description="Will create or update nominee info. Returns an updated copy of their nominee info.",
9595
response_model=NomineeInfoModel,

src/officers/crud.py

Lines changed: 88 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from collections.abc import Sequence
2-
from datetime import date, datetime
2+
from datetime import date
33

44
import sqlalchemy
55
from fastapi import HTTPException
@@ -11,120 +11,119 @@
1111
import utils
1212
from data import semesters
1313
from officers.constants import OfficerPosition
14-
from officers.models import OfficerInfoResponse, OfficerTermCreate
14+
from officers.models import OfficerInfoResponse
1515
from officers.tables import OfficerInfo, OfficerTerm
1616

1717
# NOTE: this module should not do any data validation; that should be done in the urls.py or higher layer
1818

19+
1920
async def current_officers(
2021
db_session: database.DBSession,
2122
) -> list[OfficerInfoResponse]:
2223
"""
2324
Get info about officers that are active. Go through all active & complete officer terms.
24-
25-
Returns a mapping between officer position and officer terms
2625
"""
2726
curr_time = date.today()
28-
query = (sqlalchemy.select(OfficerTerm, OfficerInfo)
29-
.join(OfficerInfo, OfficerTerm.computing_id == OfficerInfo.computing_id)
30-
.where((OfficerTerm.start_date <= curr_time) & (OfficerTerm.end_date >= curr_time))
31-
.order_by(OfficerTerm.start_date.desc())
32-
)
27+
query = (
28+
sqlalchemy.select(OfficerTerm, OfficerInfo)
29+
.join(OfficerInfo, OfficerTerm.computing_id == OfficerInfo.computing_id)
30+
.where((OfficerTerm.start_date <= curr_time) & (OfficerTerm.end_date >= curr_time))
31+
.order_by(OfficerTerm.start_date.desc())
32+
)
3333

3434
result: Sequence[sqlalchemy.Row[tuple[OfficerTerm, OfficerInfo]]] = (await db_session.execute(query)).all()
35-
officer_list = []
35+
officer_list: list[OfficerInfoResponse] = []
3636
for term, officer in result:
37-
officer_list.append(OfficerInfoResponse(
38-
legal_name = officer.legal_name,
39-
is_active = True,
40-
position = term.position,
41-
start_date = term.start_date,
42-
end_date = term.end_date,
43-
biography = term.biography,
44-
csss_email = OfficerPosition.to_email(term.position),
45-
46-
discord_id = officer.discord_id,
47-
discord_name = officer.discord_name,
48-
discord_nickname = officer.discord_nickname,
49-
computing_id = officer.computing_id,
50-
phone_number = officer.phone_number,
51-
github_username = officer.github_username,
52-
google_drive_email = officer.google_drive_email,
53-
photo_url = term.photo_url
54-
))
37+
officer_list.append(
38+
OfficerInfoResponse(
39+
legal_name=officer.legal_name,
40+
is_active=True,
41+
position=term.position,
42+
start_date=term.start_date,
43+
end_date=term.end_date,
44+
biography=term.biography,
45+
csss_email=OfficerPosition.to_email(term.position),
46+
discord_id=officer.discord_id,
47+
discord_name=officer.discord_name,
48+
discord_nickname=officer.discord_nickname,
49+
computing_id=officer.computing_id,
50+
phone_number=officer.phone_number,
51+
github_username=officer.github_username,
52+
google_drive_email=officer.google_drive_email,
53+
photo_url=term.photo_url,
54+
)
55+
)
5556

5657
return officer_list
5758

58-
async def all_officers(
59-
db_session: AsyncSession,
60-
include_future_terms: bool
61-
) -> list[OfficerInfoResponse]:
59+
60+
async def all_officers(db_session: AsyncSession, include_future_terms: bool) -> list[OfficerInfoResponse]:
6261
"""
6362
This could be a lot of data, so be careful
6463
"""
6564
# NOTE: paginate data if needed
66-
query = (sqlalchemy.select(OfficerTerm, OfficerInfo)
67-
.join(OfficerInfo, OfficerTerm.computing_id == OfficerInfo.computing_id)
68-
.order_by(OfficerTerm.start_date.desc())
69-
)
65+
query = (
66+
sqlalchemy.select(OfficerTerm, OfficerInfo)
67+
.join(OfficerInfo, OfficerTerm.computing_id == OfficerInfo.computing_id)
68+
.order_by(OfficerTerm.start_date.desc())
69+
)
7070

7171
if not include_future_terms:
7272
query = utils.has_started_term(query)
7373
result: Sequence[sqlalchemy.Row[tuple[OfficerTerm, OfficerInfo]]] = (await db_session.execute(query)).all()
74-
officer_list = []
74+
officer_list: list[OfficerInfoResponse] = []
7575
for term, officer in result:
76-
officer_list.append(OfficerInfoResponse(
77-
legal_name = officer.legal_name,
78-
is_active = utils.is_active_term(term),
79-
position = term.position,
80-
start_date = term.start_date,
81-
end_date = term.end_date,
82-
biography = term.biography,
83-
csss_email = OfficerPosition.to_email(term.position),
84-
85-
discord_id = officer.discord_id,
86-
discord_name = officer.discord_name,
87-
discord_nickname = officer.discord_nickname,
88-
computing_id = officer.computing_id,
89-
phone_number = officer.phone_number,
90-
github_username = officer.github_username,
91-
google_drive_email = officer.google_drive_email,
92-
photo_url = term.photo_url
93-
))
76+
officer_list.append(
77+
OfficerInfoResponse(
78+
legal_name=officer.legal_name,
79+
is_active=utils.is_active_term(term),
80+
position=term.position,
81+
start_date=term.start_date,
82+
end_date=term.end_date,
83+
biography=term.biography,
84+
csss_email=OfficerPosition.to_email(term.position),
85+
discord_id=officer.discord_id,
86+
discord_name=officer.discord_name,
87+
discord_nickname=officer.discord_nickname,
88+
computing_id=officer.computing_id,
89+
phone_number=officer.phone_number,
90+
github_username=officer.github_username,
91+
google_drive_email=officer.google_drive_email,
92+
photo_url=term.photo_url,
93+
)
94+
)
9495

9596
return officer_list
9697

98+
9799
async def get_officer_info_or_raise(db_session: database.DBSession, computing_id: str) -> OfficerInfo:
98100
officer_term = await db_session.scalar(
99-
sqlalchemy
100-
.select(OfficerInfo)
101-
.where(OfficerInfo.computing_id == computing_id)
101+
sqlalchemy.select(OfficerInfo).where(OfficerInfo.computing_id == computing_id)
102102
)
103103
if officer_term is None:
104104
raise HTTPException(status_code=404, detail=f"officer_info for computing_id={computing_id} does not exist yet")
105105
return officer_term
106106

107+
107108
async def get_new_officer_info_or_raise(db_session: database.DBSession, computing_id: str) -> OfficerInfo:
108109
"""
109110
This check is for after a create/update
110111
"""
111112
officer_term = await db_session.scalar(
112-
sqlalchemy
113-
.select(OfficerInfo)
114-
.where(OfficerInfo.computing_id == computing_id)
113+
sqlalchemy.select(OfficerInfo).where(OfficerInfo.computing_id == computing_id)
115114
)
116115
if officer_term is None:
117116
raise HTTPException(status_code=500, detail=f"failed to fetch {computing_id} after update")
118117
return officer_term
119118

119+
120120
async def get_officer_terms(
121121
db_session: database.DBSession,
122122
computing_id: str,
123123
include_future_terms: bool,
124124
) -> list[OfficerTerm]:
125125
query = (
126-
sqlalchemy
127-
.select(OfficerTerm)
126+
sqlalchemy.select(OfficerTerm)
128127
.where(OfficerTerm.computing_id == computing_id)
129128
# In order of most recent start date first
130129
.order_by(OfficerTerm.start_date.desc())
@@ -134,17 +133,14 @@ async def get_officer_terms(
134133

135134
return (await db_session.scalars(query)).all()
136135

137-
async def get_active_officer_terms(
138-
db_session: database.DBSession,
139-
computing_id: str
140-
) -> list[OfficerTerm]:
136+
137+
async def get_active_officer_terms(db_session: database.DBSession, computing_id: str) -> list[OfficerTerm]:
141138
"""
142139
Returns the list of active officer terms for a user. Returns [] if the user is not currently an officer.
143140
An officer can have multiple positions at once, such as Webmaster, Frosh chair, and DoEE.
144141
"""
145142
query = (
146-
sqlalchemy
147-
.select(OfficerTerm)
143+
sqlalchemy.select(OfficerTerm)
148144
.where(OfficerTerm.computing_id == computing_id)
149145
# In order of most recent start date first
150146
.order_by(OfficerTerm.start_date.desc())
@@ -154,54 +150,46 @@ async def get_active_officer_terms(
154150
officer_term_list = (await db_session.scalars(query)).all()
155151
return officer_term_list
156152

153+
157154
async def current_officer_positions(db_session: database.DBSession, computing_id: str) -> list[str]:
158155
"""
159156
Returns the list of officer positions a user currently has. [] if not currently an officer.
160157
"""
161158
officer_term_list = await get_active_officer_terms(db_session, computing_id)
162159
return [term.position for term in officer_term_list]
163160

164-
async def get_officer_term_by_id_or_raise(db_session: database.DBSession, term_id: int, is_new: bool = False) -> OfficerTerm:
165-
officer_term = await db_session.scalar(
166-
sqlalchemy
167-
.select(OfficerTerm)
168-
.where(OfficerTerm.id == term_id)
169-
)
161+
162+
async def get_officer_term_by_id_or_raise(
163+
db_session: database.DBSession, term_id: int, is_new: bool = False
164+
) -> OfficerTerm:
165+
officer_term = await db_session.scalar(sqlalchemy.select(OfficerTerm).where(OfficerTerm.id == term_id))
170166
if officer_term is None:
171167
if is_new:
172168
raise HTTPException(status_code=500, detail=f"could not find new officer_term with id={term_id}")
173169
else:
174170
raise HTTPException(status_code=404, detail=f"could not find officer_term with id={term_id}")
175171
return officer_term
176172

177-
async def create_new_officer_info(
178-
db_session: database.DBSession,
179-
new_officer_info: OfficerInfo
180-
) -> bool:
173+
174+
async def create_new_officer_info(db_session: database.DBSession, new_officer_info: OfficerInfo) -> bool:
181175
"""Return False if the officer already exists & don't do anything."""
182176
if not await auth.crud.site_user_exists(db_session, new_officer_info.computing_id):
183177
# if computing_id has not been created as a site_user yet, add them
184-
db_session.add(auth.tables.SiteUser(
185-
computing_id=new_officer_info.computing_id,
186-
first_logged_in=None,
187-
last_logged_in=None
188-
))
178+
db_session.add(
179+
auth.tables.SiteUser(computing_id=new_officer_info.computing_id, first_logged_in=None, last_logged_in=None)
180+
)
189181

190182
existing_officer_info = await db_session.scalar(
191-
sqlalchemy
192-
.select(OfficerInfo)
193-
.where(OfficerInfo.computing_id == new_officer_info.computing_id)
183+
sqlalchemy.select(OfficerInfo).where(OfficerInfo.computing_id == new_officer_info.computing_id)
194184
)
195185
if existing_officer_info is not None:
196186
return False
197187

198188
db_session.add(new_officer_info)
199189
return True
200190

201-
async def create_new_officer_term(
202-
db_session: database.DBSession,
203-
new_officer_term: OfficerTerm
204-
):
191+
192+
async def create_new_officer_term(db_session: database.DBSession, new_officer_term: OfficerTerm):
205193
position_length = OfficerPosition.length_in_semesters(new_officer_term.position)
206194
if position_length is not None:
207195
# when creating a new position, assign a default end date if one exists
@@ -211,31 +199,27 @@ async def create_new_officer_term(
211199
)
212200
db_session.add(new_officer_term)
213201

214-
async def update_officer_info(
215-
db_session: database.DBSession,
216-
new_officer_info: OfficerInfo
217-
) -> bool:
202+
203+
async def update_officer_info(db_session: database.DBSession, new_officer_info: OfficerInfo) -> bool:
218204
"""
219205
Return False if the officer doesn't exist yet
220206
"""
221207
officer_info = await db_session.scalar(
222-
sqlalchemy
223-
.select(OfficerInfo)
224-
.where(OfficerInfo.computing_id == new_officer_info.computing_id)
208+
sqlalchemy.select(OfficerInfo).where(OfficerInfo.computing_id == new_officer_info.computing_id)
225209
)
226210
if officer_info is None:
227211
return False
228212

229213
# NOTE: if there's ever an insert entry error, it will raise SQLAlchemyError
230214
# see: https://stackoverflow.com/questions/2136739/how-to-check-and-handle-errors-in-sqlalchemy
231215
await db_session.execute(
232-
sqlalchemy
233-
.update(OfficerInfo)
216+
sqlalchemy.update(OfficerInfo)
234217
.where(OfficerInfo.computing_id == officer_info.computing_id)
235218
.values(new_officer_info.to_update_dict())
236219
)
237220
return True
238221

222+
239223
async def update_officer_term(
240224
db_session: database.DBSession,
241225
new_officer_term: OfficerTerm,
@@ -244,25 +228,17 @@ async def update_officer_term(
244228
Update all officer term data in `new_officer_term` based on the term id.
245229
Returns false if the above entry does not exist.
246230
"""
247-
officer_term = await db_session.scalar(
248-
sqlalchemy
249-
.select(OfficerTerm)
250-
.where(OfficerTerm.id == new_officer_term.id)
251-
)
231+
officer_term = await db_session.scalar(sqlalchemy.select(OfficerTerm).where(OfficerTerm.id == new_officer_term.id))
252232
if officer_term is None:
253233
return False
254234

255235
await db_session.execute(
256-
sqlalchemy
257-
.update(OfficerTerm)
236+
sqlalchemy.update(OfficerTerm)
258237
.where(OfficerTerm.id == new_officer_term.id)
259238
.values(new_officer_term.to_update_dict())
260239
)
261240
return True
262241

242+
263243
async def delete_officer_term_by_id(db_session: database.DBSession, term_id: int):
264-
await db_session.execute(
265-
sqlalchemy
266-
.delete(OfficerTerm)
267-
.where(OfficerTerm.id == term_id)
268-
)
244+
await db_session.execute(sqlalchemy.delete(OfficerTerm).where(OfficerTerm.id == term_id))

0 commit comments

Comments
 (0)