77
88import database
99import elections
10+ import elections .tables
1011from elections .tables import Election , NomineeApplication , election_types
1112from officers .constants import OfficerPosition
1213from permission .types import ElectionOfficer , WebsiteAdmin
@@ -56,7 +57,7 @@ async def list_elections(
5657
5758 current_time = datetime .now ()
5859 election_metadata_list = [
59- election .public_details (current_time )
60+ election .public_metadata (current_time )
6061 for election in election_list
6162 ]
6263
@@ -94,6 +95,45 @@ async def get_election(
9495
9596 return JSONResponse (election_json )
9697
98+ def _raise_if_bad_election_data (
99+ name : str ,
100+ election_type : str ,
101+ datetime_start_nominations : datetime ,
102+ datetime_start_voting : datetime ,
103+ datetime_end_voting : datetime ,
104+ avaliable_positions : str | None ,
105+ ):
106+ if election_type not in election_types :
107+ raise HTTPException (
108+ status_code = status .HTTP_400_BAD_REQUEST ,
109+ detail = f"unknown election type { election_type } " ,
110+ )
111+ elif not (
112+ (datetime_start_nominations <= datetime_start_voting )
113+ and (datetime_start_voting <= datetime_end_voting )
114+ ):
115+ raise HTTPException (
116+ status_code = status .HTTP_400_BAD_REQUEST ,
117+ detail = "dates must be in order from earliest to latest" ,
118+ )
119+ elif avaliable_positions is not None :
120+ for position in avaliable_positions .split ("," ):
121+ if position not in OfficerPosition .position_list ():
122+ raise HTTPException (
123+ status_code = status .HTTP_400_BAD_REQUEST ,
124+ detail = f"unknown position found in position list { position } " ,
125+ )
126+ elif len (name ) > elections .tables .MAX_ELECTION_NAME :
127+ raise HTTPException (
128+ status_code = status .HTTP_400_BAD_REQUEST ,
129+ detail = f"election name { name } is too long" ,
130+ )
131+ elif len (_slugify (name )) > elections .tables .MAX_ELECTION_SLUG :
132+ raise HTTPException (
133+ status_code = status .HTTP_400_BAD_REQUEST ,
134+ detail = f"election slug { _slugify (name )} is too long" ,
135+ )
136+
97137@router .post (
98138 "/by_name/{name:str}" ,
99139 description = "Creates an election and places it in the database. Returns election json on success" ,
@@ -106,15 +146,19 @@ async def create_election(
106146 datetime_start_nominations : datetime ,
107147 datetime_start_voting : datetime ,
108148 datetime_end_voting : datetime ,
149+ # allows None, which assigns it to the default
150+ avaliable_positions : str | None ,
109151 survey_link : str | None ,
110152):
111153 current_time = datetime .now ()
112-
113- if election_type not in election_types :
114- raise HTTPException (
115- status_code = status .HTTP_400_BAD_REQUEST ,
116- detail = f"unknown election type { election_type } " ,
117- )
154+ _raise_if_bad_election_data (
155+ name ,
156+ election_type ,
157+ datetime_start_nominations ,
158+ datetime_start_voting ,
159+ datetime_end_voting ,
160+ avaliable_positions ,
161+ )
118162
119163 is_valid_user , _ , _ = await _validate_user (request , db_session )
120164 if not is_valid_user :
@@ -124,30 +168,25 @@ async def create_election(
124168 # TODO: is this header actually required?
125169 headers = {"WWW-Authenticate" : "Basic" },
126170 )
127- elif len (name ) > elections .tables .MAX_ELECTION_NAME :
128- raise HTTPException (
129- status_code = status .HTTP_400_BAD_REQUEST ,
130- detail = f"election name { name } is too long" ,
131- )
132- elif len (_slugify (name )) > elections .tables .MAX_ELECTION_SLUG :
133- raise HTTPException (
134- status_code = status .HTTP_400_BAD_REQUEST ,
135- detail = f"election slug { _slugify (name )} is too long" ,
136- )
137171 elif await elections .crud .get_election (db_session , _slugify (name )) is not None :
138172 # don't overwrite a previous election
139173 raise HTTPException (
140174 status_code = status .HTTP_400_BAD_REQUEST ,
141175 detail = "would overwrite previous election" ,
142176 )
143- elif not (
144- (datetime_start_nominations <= datetime_start_voting )
145- and (datetime_start_voting <= datetime_end_voting )
146- ):
147- raise HTTPException (
148- status_code = status .HTTP_400_BAD_REQUEST ,
149- detail = "dates must be in order from earliest to latest" ,
150- )
177+
178+ if avaliable_positions is None :
179+ if election_type == "general_election" :
180+ avaliable_positions = elections .tables .DEFAULT_POSITIONS_GENERAL_ELECTION
181+ elif election_type == "by_election" :
182+ avaliable_positions = elections .tables .DEFAULT_POSITIONS_BY_ELECTION
183+ elif election_type == "council_rep_election" :
184+ avaliable_positions = elections .tables .DEFAULT_POSITIONS_COUNCIL_REP_ELECTION
185+ else :
186+ raise HTTPException (
187+ status_code = status .HTTP_400_BAD_REQUEST ,
188+ detail = f"invalid election type { election_type } for avaliable positions"
189+ )
151190
152191 await elections .crud .create_election (
153192 db_session ,
@@ -158,6 +197,7 @@ async def create_election(
158197 datetime_start_nominations = datetime_start_nominations ,
159198 datetime_start_voting = datetime_start_voting ,
160199 datetime_end_voting = datetime_end_voting ,
200+ avaliable_positions = avaliable_positions ,
161201 survey_link = survey_link
162202 )
163203 )
@@ -185,47 +225,49 @@ async def update_election(
185225 datetime_start_nominations : datetime ,
186226 datetime_start_voting : datetime ,
187227 datetime_end_voting : datetime ,
228+ avaliable_positions : str ,
188229 survey_link : str | None ,
189230):
190231 current_time = datetime .now ()
232+ _raise_if_bad_election_data (
233+ name ,
234+ election_type ,
235+ datetime_start_nominations ,
236+ datetime_start_voting ,
237+ datetime_end_voting ,
238+ avaliable_positions ,
239+ )
191240
192241 is_valid_user , _ , _ = await _validate_user (request , db_session )
193242 if not is_valid_user :
194- # let's workshop how we actually wanna handle this
195243 raise HTTPException (
196244 status_code = status .HTTP_401_UNAUTHORIZED ,
197245 detail = "must have election officer or admin permission" ,
198246 headers = {"WWW-Authenticate" : "Basic" },
199247 )
200- elif not (
201- (datetime_start_nominations <= datetime_start_voting )
202- and (datetime_start_voting <= datetime_end_voting )
203- ):
248+ elif await elections .crud .get_election (db_session , _slugify (name )) is None :
204249 raise HTTPException (
205250 status_code = status .HTTP_400_BAD_REQUEST ,
206- detail = "dates must be in order from earliest to latest " ,
251+ detail = f"election with slug { _slugify ( name ) } does not exist " ,
207252 )
208253
209- new_election = Election (
210- slug = _slugify (name ),
211- name = name ,
212- type = election_type ,
213- datetime_start_nominations = datetime_start_nominations ,
214- datetime_start_voting = datetime_start_voting ,
215- datetime_end_voting = datetime_end_voting ,
216- survey_link = survey_link
217- )
218- success = await elections .crud .update_election (db_session , new_election )
219- if not success :
220- raise HTTPException (
221- status_code = status .HTTP_400_BAD_REQUEST ,
222- detail = f"election with slug { _slugify (name )} does not exist" ,
254+ await elections .crud .update_election (
255+ db_session ,
256+ Election (
257+ slug = _slugify (name ),
258+ name = name ,
259+ type = election_type ,
260+ datetime_start_nominations = datetime_start_nominations ,
261+ datetime_start_voting = datetime_start_voting ,
262+ datetime_end_voting = datetime_end_voting ,
263+ avaliable_positions = avaliable_positions ,
264+ survey_link = survey_link
223265 )
224- else :
225- await db_session .commit ()
266+ )
267+ await db_session .commit ()
226268
227- election = await elections .crud .get_election (db_session , _slugify (name ))
228- return JSONResponse (election .private_details (current_time ))
269+ election = await elections .crud .get_election (db_session , _slugify (name ))
270+ return JSONResponse (election .private_details (current_time ))
229271
230272@router .delete (
231273 "/by_name/{name:str}" ,
0 commit comments