1- from fastapi import APIRouter , Depends , status , HTTPException , Path
1+ from fastapi import APIRouter , Depends , status , HTTPException , Path , Body
22
33from sqlalchemy .orm import Session
44
@@ -277,13 +277,62 @@ def delete_applicant_application(db: Session = Depends(dependencies.get_db),
277277 return f"Deleted application for job { job_id } for applicant { applicant .id } ."
278278
279279
280- # PATCH /applications/{job_id}_{applicant_id}/review change status to under review
281- # @router.patch(
282- # "/applications/review/"
283- # )
280+ # PATCH /applications/{job_id}_{applicant_id}/ change status
281+ @router .patch (
282+ "/applications/{job_id}_{applicant_id}/" ,
283+ response_model = user_profile_job_schema .UserProfileJob ,
284+ status_code = status .HTTP_200_OK ,
285+ tags = ["Application" ],
286+ summary = "PATCH route for a recruiter to change the status of an application." ,
287+ description = "Change the status of an application for a job and provide optional rejection feedback " \
288+ "for the applicant. The status of an application cannot move backwards. The recruiter must " \
289+ "own the job to be able to change the status of an application." ,
290+ response_description = "The updated application."
291+ )
292+ def change_application_status (db : Session = Depends (dependencies .get_db ),
293+ job_id : int = Path (),
294+ applicant_id : int = Path (),
295+ new_status : application_status_model .ApplicationStatusEnum = Body (),
296+ rejection_feedback : str | None = Body (default = None ),
297+ recruiter : user_model .User = Depends (dependencies .get_current_recruiter_user )):
298+ # Check the application exists
299+ application = user_profile_job_crud .get_application_by_user_id_and_job_id (db , applicant_id , job_id )
300+ if application is None :
301+ raise HTTPException (
302+ status_code = status .HTTP_404_NOT_FOUND ,
303+ detail = f"Application for job { job_id } and applicant { applicant_id } does not exist."
304+ )
305+
306+ # Check the recruiter owns the job
307+ job = job_crud .get_job_by_id (db , job_id )
308+
309+ if job .user_profile_id != recruiter .id :
310+ raise HTTPException (
311+ status_code = status .HTTP_401_UNAUTHORIZED ,
312+ detail = f"Recruiter { recruiter .id } is not authorized to update applications for job " \
313+ "{job_id}."
314+ )
315+
316+ # Check the current status of the application and the new status of the application to see if it is allowed
317+ # The new status of an application must be greater or equal to the current status of an application
318+ # except in the case of REJECTED, which is a final status it can only be equal
319+ can_change_app_status = False
320+ new_application_status_id = application_status_crud .get_application_status_by_name (db , new_status .value ).id
321+
322+ if application .application_status .status == application_status_model .ApplicationStatusEnum .rejected .value :
323+ if new_application_status_id == application .application_status_id :
324+ can_change_app_status = True
325+ else :
326+ if new_application_status_id >= application . application_status_id :
327+ can_change_app_status = True
284328
285- # PATCH /applications/{job_id}_{applicant_id}/further_screening
329+ if not can_change_app_status :
330+ raise HTTPException (
331+ status_code = status .HTTP_400_BAD_REQUEST ,
332+ detail = f"Cannot change application status from { application .application_status .status } to " \
333+ f"{ new_status .value } ."
334+ )
286335
287- # PATCH /applications/{job_id}_{applicant_id}/offer change status to offer sent
336+ # Update the application status of the application
337+ return user_profile_job_crud .update_applicant_application_status (db , applicant_id , job_id , new_status , rejection_feedback )
288338
289- # PATCH /applications/{job_id}_{applicant_id}/rejected change status to rejected
0 commit comments