feat: org router response models

This commit is contained in:
Chris Milne 2026-05-29 09:44:24 +01:00
parent d404ab3ea3
commit 987a050b4b
2 changed files with 47 additions and 14 deletions

View file

@ -38,8 +38,8 @@ from src.organisation.models import Organisation as Org
from src.organisation.schemas import OrgPostOrgRequest, OrgPatchQuestionnaireRequest, OrgPatchStatusRequest, \ from src.organisation.schemas import OrgPostOrgRequest, OrgPatchQuestionnaireRequest, OrgPatchStatusRequest, \
OrgPatchContactRequest, \ OrgPatchContactRequest, \
OrgPostUserRequest, OrgGetUserResponse, OrgGetContactResponse, OrgGetOrgResponse, OrgPatchRootRequest, \ OrgPostUserRequest, OrgGetUserResponse, OrgGetContactResponse, OrgGetOrgResponse, OrgPatchRootRequest, \
OrgGetGroupResponse, OrgDeleteUserRequest, OrgDeleteOrgRequest OrgGetGroupResponse, OrgDeleteUserRequest, OrgDeleteOrgRequest, OrgPostOrgResponse, OrgPatchQuestionnaireResponse, \
OrgPatchStatusResponse, OrgPostUserResponse, OrgPatchRootResponse
router = APIRouter( router = APIRouter(
prefix="/org", prefix="/org",
@ -73,6 +73,7 @@ async def get_org_by_id(org_model: org_model_root_claim_query_dependency):
@router.post("/", @router.post("/",
summary="Create new organisation.", summary="Create new organisation.",
status_code=status.HTTP_201_CREATED, status_code=status.HTTP_201_CREATED,
response_model=OrgPostOrgResponse,
responses={ responses={
status.HTTP_201_CREATED: {"description": "Successfully created organisation."}, status.HTTP_201_CREATED: {"description": "Successfully created organisation."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."}, status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
@ -80,7 +81,6 @@ async def get_org_by_id(org_model: org_model_root_claim_query_dependency):
status.HTTP_409_CONFLICT: {"description": "Organisation with this name already exists."}, status.HTTP_409_CONFLICT: {"description": "Organisation with this name already exists."},
}) })
async def create_org(db: db_dependency, user_model: user_model_claims_dependency, request_model: OrgPostOrgRequest): async def create_org(db: db_dependency, user_model: user_model_claims_dependency, request_model: OrgPostOrgRequest):
# TODO: Response model
if request_model.intake_questionnaire: if request_model.intake_questionnaire:
intake_questionnaire = request_model.intake_questionnaire.model_dump() intake_questionnaire = request_model.intake_questionnaire.model_dump()
else: else:
@ -103,46 +103,53 @@ async def create_org(db: db_dependency, user_model: user_model_claims_dependency
db.add(contact_model) db.add(contact_model)
db.flush() db.flush()
org_model.__setattr__(contact_type, contact_model.id) org_model.__setattr__(contact_type, contact_model.id)
response = OrgPostOrgResponse(**org_model.__dict__)
db.commit() db.commit()
return response
@router.patch("/questionnaire", @router.patch("/questionnaire",
summary="Update questionnaire.", summary="Update questionnaire.",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
response_model=OrgPatchQuestionnaireResponse,
responses={ responses={
status.HTTP_200_OK: {"description": "Successfully updated questionnaire."}, status.HTTP_200_OK: {"description": "Successfully updated questionnaire."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."}, status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."}, status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
}) })
async def update_questionnaire(db: db_dependency, org_model: org_model_root_claim_query_dependency, request_model: OrgPatchQuestionnaireRequest): async def update_questionnaire(db: db_dependency, org_model: org_model_root_claim_body_dependency, request_model: OrgPatchQuestionnaireRequest):
""" """
Route for updating questionnaire. Route for updating questionnaire.
The partial bool allows for submission of partially completed questionnaire and/or The partial bool allows for submission of partially completed questionnaire and/or
final "are you sure" check before setting the org to be in "submitted" status, awaiting admin approval. final "are you sure" check before setting the org to be in "submitted" status, awaiting admin approval.
""" """
# TODO: Response model
org_model.intake_questionnaire = request_model.intake_questionnaire.model_dump() org_model.intake_questionnaire = request_model.intake_questionnaire.model_dump()
# Allows for partially completed questionnaires to be saved without being submitted for review # Allows for partially completed questionnaires to be saved without being submitted for review
if not request_model.partial: if not request_model.partial:
org_model.status = "submitted" org_model.status = "submitted"
db.flush()
response = OrgPatchQuestionnaireResponse(**org_model.__dict__)
db.commit() db.commit()
return response
@router.patch("/status", @router.patch("/status",
summary="Update status of organisation.", summary="Update status of organisation.",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
response_model=OrgPatchStatusResponse,
responses={ responses={
status.HTTP_200_OK: {"description": "Successfully updated organisation status."}, status.HTTP_200_OK: {"description": "Successfully updated organisation status."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."}, status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be super admin."}, status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be super admin."},
}) })
async def update_status(db: db_dependency, org_model: org_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchStatusRequest): async def update_status(db: db_dependency, org_model: org_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchStatusRequest):
# TODO: Response model
org_model.status = request_model.status org_model.status = request_model.status
db.flush()
response = OrgPatchStatusResponse(**org_model.__dict__)
db.commit() db.commit()
return response
@router.get("/users", @router.get("/users",
@ -159,8 +166,9 @@ async def get_users(org_model: org_model_root_claim_query_dependency):
@router.post("/users", @router.post("/users",
summary="All user to the organisation.", summary="Add user to the organisation.",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
response_model=OrgPostUserResponse,
responses={ responses={
status.HTTP_200_OK: {"description": "Successfully added user to the organisation."}, status.HTTP_200_OK: {"description": "Successfully added user to the organisation."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."}, status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be org root user."},
@ -168,11 +176,13 @@ async def get_users(org_model: org_model_root_claim_query_dependency):
status.HTTP_409_CONFLICT: {"description": "User is already a member of the organisation."}, status.HTTP_409_CONFLICT: {"description": "User is already a member of the organisation."},
}) })
async def add_user_to_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgPostUserRequest): async def add_user_to_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgPostUserRequest):
# TODO: response model
if user_model in org_model.user_rel: if user_model in org_model.user_rel:
raise Conflict(message="User already a part of this organisation") raise Conflict(message="User already a part of this organisation")
org_model.user_rel.append(user_model) org_model.user_rel.append(user_model)
db.flush()
response = {"users": [user.email for user in org_model.user_rel]}
db.commit() db.commit()
return response
@router.delete("/", @router.delete("/",
@ -191,15 +201,19 @@ async def delete_organisation_by_id(db: db_dependency, org_model: org_model_body
@router.patch("/root_user", @router.patch("/root_user",
summary="Update the root user of the organisation.", summary="Update the root user of the organisation.",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
response_model=OrgPatchRootResponse,
responses={ responses={
status.HTTP_200_OK: {"description": "Successfully updated root user."}, status.HTTP_200_OK: {"description": "Successfully updated root user."},
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."}, status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be super admin."}, status.HTTP_401_UNAUTHORIZED: {"description": "Not authorised. Must be super admin."},
}) })
async def update_root_user(db: db_dependency, org_model: org_model_body_dependency, user_model: user_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchRootRequest): async def update_root_user(db: db_dependency, org_model: org_model_body_dependency, user_model: user_model_body_dependency, su: super_admin_dependency, request_model: OrgPatchRootRequest):
# TODO: response model # TODO: verify new user is already an org member
org_model.root_user_rel = user_model org_model.root_user_rel = user_model
db.flush()
response = OrgPatchRootResponse(**org_model.__dict__)
db.commit() db.commit()
return response
@router.get("/groups", @router.get("/groups",
@ -224,7 +238,6 @@ async def get_org_groups(org_model: org_model_root_claim_query_dependency):
status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."}, status.HTTP_422_UNPROCESSABLE_CONTENT: {"description": "Invalid data in request."},
}) })
async def remove_user_from_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgDeleteUserRequest): async def remove_user_from_org(db: db_dependency, org_model: org_model_root_claim_body_dependency, user_model: user_model_body_dependency, request_model: OrgDeleteUserRequest):
# TODO: response model
if user_model not in org_model.user_rel: if user_model not in org_model.user_rel:
return return

View file

@ -18,9 +18,9 @@ from src.organisation.constants import Status, ContactType
class Questionnaire(CustomBaseModel): class Questionnaire(CustomBaseModel):
question_one: str question_one: Optional[str] = None
question_two: str question_two: Optional[str] = None
question_three: str question_three: Optional[str] = None
class OrgIDMixin(CustomBaseModel): class OrgIDMixin(CustomBaseModel):
organisation_id: int organisation_id: int
@ -30,13 +30,26 @@ class OrgPostOrgRequest(CustomBaseModel):
name: str name: str
intake_questionnaire: Optional[Questionnaire] = None intake_questionnaire: Optional[Questionnaire] = None
class OrgPostOrgResponse(CustomBaseModel):
name: str
status: Status
class OrgPatchQuestionnaireRequest(OrgIDMixin): class OrgPatchQuestionnaireRequest(OrgIDMixin):
intake_questionnaire: Questionnaire intake_questionnaire: Questionnaire
partial: bool partial: bool
class OrgPatchQuestionnaireResponse(CustomBaseModel):
name: str
intake_questionnaire: Questionnaire
status: Status
class OrgPatchStatusRequest(OrgIDMixin): class OrgPatchStatusRequest(OrgIDMixin):
status: Status status: Status
class OrgPatchStatusResponse(CustomBaseModel):
name: str
status: Status
class OrgPatchContactRequest(OrgIDMixin): class OrgPatchContactRequest(OrgIDMixin):
contact_type: ContactType contact_type: ContactType
@ -56,12 +69,19 @@ class OrgPatchContactRequest(OrgIDMixin):
class OrgPostUserRequest(OrgIDMixin, UserIDMixin): class OrgPostUserRequest(OrgIDMixin, UserIDMixin):
pass pass
class OrgPostUserResponse(CustomBaseModel):
users: list[str]
class OrgDeleteUserRequest(OrgIDMixin, UserIDMixin): class OrgDeleteUserRequest(OrgIDMixin, UserIDMixin):
pass pass
class OrgPatchRootRequest(OrgIDMixin, UserIDMixin): class OrgPatchRootRequest(OrgIDMixin, UserIDMixin):
pass pass
class OrgPatchRootResponse(CustomBaseModel):
name: str
root_user_email: str
class OrgGetUserResponse(CustomBaseModel): class OrgGetUserResponse(CustomBaseModel):
users: list[str] users: list[str]