Skip to content

Commit 8ce6a09

Browse files
committed
add endpoint to update the status of an application for a recruiter
Signed-off-by: longfight123 <[email protected]>
1 parent 411cc72 commit 8ce6a09

File tree

2 files changed

+75
-77
lines changed

2 files changed

+75
-77
lines changed

backend/crud/user_profile_job_crud.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,34 @@ def delete_applicant_application(db: Session, user_id: int, job_id: int) \
195195
db.commit()
196196
return application
197197

198-
def update_applicant_application_status(db: Session, user_id: int, job_id: int,
199-
new_status: application_status_model.ApplicationStatusEnum) \
198+
def update_applicant_application_status(db: Session,
199+
user_id: int,
200+
job_id: int,
201+
new_status: application_status_model.ApplicationStatusEnum,
202+
rejection_feedback: str | None) \
200203
-> user_profile_job_model.UserProfileJob:
204+
# Get the application
205+
current_application = get_application_by_user_id_and_job_id(db, user_id, job_id)
206+
207+
# Get the id for the new application status
208+
new_application_status_id = application_status_crud.get_application_status_by_name(db, new_status.value).id
209+
210+
# Update the current applications id
211+
current_application.application_status_id = new_application_status_id
212+
213+
# Update the other attributes of the current application depending on the new status
214+
if new_status.value == application_status_model.ApplicationStatusEnum.submitted.value:
215+
current_application.application_submitted_date = datetime.today()
216+
elif new_status.value == application_status_model.ApplicationStatusEnum.in_review.value:
217+
current_application.application_reviewed_date = datetime.today()
218+
elif new_status.value == application_status_model.ApplicationStatusEnum.screening.value:
219+
current_application.application_further_screening_date = datetime.today()
220+
elif new_status.value == application_status_model.ApplicationStatusEnum.rejected.value:
221+
current_application.application_rejected_date = datetime.today()
222+
current_application.rejection_feedback = rejection_feedback
223+
elif new_status.value == application_status_model.ApplicationStatusEnum.offer_sent.value:
224+
current_application.application_offer_sent_date = datetime.today()
201225

202-
application = get_application_by_user_id_and_job_id(db, user_id, job_id)
203-
application.application_status_id = new_status.value
204-
#application.application_reviewed_date = datetime.today()
205-
db.save(application)
206226
db.commit()
207-
db.refresh(application)
208-
return application
227+
db.refresh(current_application)
228+
return current_application

backend/routers/user_profile_job_router.py

Lines changed: 47 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from fastapi import APIRouter, Depends, status, HTTPException, Path
1+
from fastapi import APIRouter, Depends, status, HTTPException, Path, Body
22

33
from sqlalchemy.orm import Session
44

@@ -277,84 +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
280+
# PATCH /applications/{job_id}_{applicant_id}/ change status
281281
@router.patch(
282-
"/applications/{job_id}_{applicant_id}/review",
282+
"/applications/{job_id}_{applicant_id}/",
283283
response_model=user_profile_job_schema.UserProfileJob,
284284
status_code=status.HTTP_200_OK,
285285
tags=["Application"],
286-
summary="PATCH route for a recruiter to change the status of an application to under review.",
287-
description="Change the status of an application to under review for a job.",
288-
response_description="The updated application status to review."
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."
289291
)
290-
def change_application_status_to_under_review(db: Session = Depends(dependencies.get_db),
291-
job_id: int = Path(),
292-
applicant_id: int = Path(),
293-
recruiter: user_model.User = Depends(dependencies.get_current_recruiter_user)):
294-
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
295299
application = user_profile_job_crud.get_application_by_user_id_and_job_id(db, applicant_id, job_id)
296-
297300
if application is None:
298-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
299-
detail=f"Application for applicant {applicant_id} and job {job_id} not found.")
300-
301-
# check if the recruiter owns the job
302-
if application.job.user_profile_id != recruiter.id:
303-
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
304-
detail=f"Recruiter is not authorized to change the status of application {application.id}.")
305-
else:
306-
user_profile_job_model.UserProfileJob.application_status_id = application_status_model.ApplicationStatusEnum.in_review
307-
status_to_review = user_profile_job_model.UserProfileJob.application_status_id
308-
309-
#TODO : Save to database using db.save()
310-
return user_profile_job_crud.update_applicant_application_status(db, applicant_id, job_id , status_to_review)
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+
)
311305

312-
# PATCH /applications/{job_id}_{applicant_id}/offer change status to offer sent
313-
314-
def change_application_status_to_offer_sent(db: Session = Depends(dependencies.get_db),
315-
job_id: int = Path(),
316-
applicant_id: int = Path(),
317-
recruiter: user_model.User = Depends(dependencies.get_current_recruiter_user)):
318-
319-
application = user_profile_job_crud.get_application_by_user_id_and_job_id(db, applicant_id, job_id)
320-
321-
if application is None:
322-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
323-
detail=f"Application for applicant {applicant_id} and job {job_id} not found.")
324-
325-
# check if the recruiter owns the job
326-
if application.job.user_profile_id != recruiter.id:
327-
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
328-
detail=f"Recruiter is not authorized to change the status of application {application.id}.")
329-
else:
330-
user_profile_job_model.UserProfileJob.application_status_id = application_status_model.ApplicationStatusEnum.offer_sent
331-
status_to_offer_sent = user_profile_job_model.UserProfileJob.application_status_id
332-
333-
#TODO : Save to database using db.save()
334-
return user_profile_job_crud.update_applicant_application_status(db, applicant_id, job_id , status_to_offer_sent)
335-
336-
# PATCH /applications/ applicationId}/rejected change status to rejected
306+
# Check the recruiter owns the job
307+
job = job_crud.get_job_by_id(db, job_id)
337308

338-
def change_application_status_to_rejected(db: Session = Depends(dependencies.get_db),
339-
job_id: int = Path(),
340-
applicant_id: int = Path(),
341-
recruiter: user_model.User = Depends(dependencies.get_current_recruiter_user)):
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+
)
342315

343-
application = user_profile_job_crud.get_application_by_user_id_and_job_id(db, applicant_id, job_id)
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
344328

345-
if application is None:
346-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
347-
detail=f"Application for applicant {applicant_id} and job {job_id} not found.")
348-
349-
# check if the recruiter owns the job
350-
if application.job.user_profile_id != recruiter.id:
351-
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
352-
detail=f"Recruiter is not authorized to change the status of application {application.id}.")
353-
else:
354-
user_profile_job_model.UserProfileJob.application_status_id = application_status_model.ApplicationStatusEnum.rejected
355-
status_to_rejected = user_profile_job_model.UserProfileJob.application_status_id
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+
)
356335

357-
#TODO : Save to database using db.save()
358-
return user_profile_job_crud.update_applicant_application_status(db, applicant_id, job_id , status_to_rejected)
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)
359338

360-
#Test

0 commit comments

Comments
 (0)