Skip to content

Commit

Permalink
RAS-1290 Add clean get respondent by party_id endpoint to party servi…
Browse files Browse the repository at this point in the history
…ce (#437)

* RAS-1290 Add clean get respondent by party_id endpoint to party service
  • Loading branch information
LJBabbage authored Oct 11, 2024
1 parent 7fcbbb3 commit 30d6003
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 3 deletions.
4 changes: 2 additions & 2 deletions _infra/helm/party/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: 2.5.5
version: 2.5.6

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 2.5.5
appVersion: 2.5.6
60 changes: 60 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,31 @@ paths:
description: The respondent does not exist
409:
description: The email address is already in use
/respondents/party_id/{party_id}:
get:
tags:
- respondents
summary: Get a respondent by party_id
description: Get a respondent by party_id
parameters:
- name: party_id
in: path
required: true
description: The UUID of the respondent
schema:
type: string
format: uuid
responses:
200:
description: The respondent has been retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/Respondent'
400:
description: The provided ID wasn't a UUID
404:
description: The respondent does not exist
/respondents/survey_id/{survey_id}/business_id/{business_id}:
get:
tags:
Expand Down Expand Up @@ -1394,6 +1419,41 @@ paths:
description: The batch number or the respondent from the batch does not exist
components:
schemas:
Respondent:
type: object
properties:
created_on:
type: string
format: date
email_address:
type: string
format: email
firstName:
type: string
example: Jane
id:
type: string
format: integer
lastName:
type: string
example: Doe
markForDeletion:
type: boolean
partyId:
type: string
format: uuid
passwordResetCounter:
type: integer
passwordVerificationToken:
type: string
pendingEmailAddress:
type: string
format: email
status:
type: string
enum: [ CREATED, ACTIVE, SUSPENDED ]
telephone:
type: string
RespondentWithAssociations:
type: object
properties:
Expand Down
5 changes: 5 additions & 0 deletions ras_party/controllers/respondent_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ def get_respondents_by_name_and_email(first_name, last_name, email, page, limit,
}


@with_query_only_db_session
def get_respondent_by_party_id(party_id: UUID, session: session) -> Respondent:
return query_respondent_by_party_uuid(party_id, session)


@with_query_only_db_session
def get_respondent_by_id(respondent_id, session):
"""
Expand Down
16 changes: 16 additions & 0 deletions ras_party/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,22 @@ def to_respondent_dict(self):
"password_reset_counter": self.password_reset_counter,
}

def to_dict(self) -> dict:
return {
"id": self.id,
"party_uuid": self.party_uuid,
"status": RespondentStatus(self.status).name,
"email_address": self.email_address,
"pending_email_address": self.pending_email_address,
"first_name": self.first_name,
"last_name": self.last_name,
"telephone": self.telephone,
"created_on": self.created_on,
"mark_for_deletion": self.mark_for_deletion,
"password_verification_token": self.password_verification_token,
"password_reset_counter": self.password_reset_counter,
}

def to_respondent_with_associations_dict(self):
respondent_dict = self.to_respondent_dict()
respondent_dict["associations"] = self._get_business_associations(self.businesses)
Expand Down
12 changes: 12 additions & 0 deletions ras_party/views/respondent_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ def _validate_get_respondent_params(ids, first_name, last_name, email):
raise BadRequest(f"'{party_id}' is not a valid UUID format for property 'id'")


@respondent_view.route("/respondents/party_id/<party_id>", methods=["GET"])
def get_respondent_by_party_id(party_id: UUID) -> Response:
if not is_valid_uuid4(party_id):
return make_response("party_id is not UUID", 400)

respondent = respondent_controller.get_respondent_by_party_id(party_id)
if respondent:
return make_response(respondent.to_dict(), 200)

return make_response(f"respondent not found for party_id {party_id}", 404)


@respondent_view.route("/respondents/id/<respondent_id>", methods=["GET"])
def get_respondent_by_id(respondent_id):
response = respondent_controller.get_respondent_by_id(respondent_id)
Expand Down
4 changes: 4 additions & 0 deletions test/party_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,7 @@ def get_respondents_by_survey_and_business_id(self, survey_id, business_id):
f"/party-api/v1/respondents/survey_id/{survey_id}/business_id/{business_id}", headers=self.auth_headers
)
return response

def get_respondents_by_party_id(self, party_id):
response = self.client.get(f"/party-api/v1/respondents/party_id/{party_id}", headers=self.auth_headers)
return response
10 changes: 10 additions & 0 deletions test/test_respondent_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,16 @@ def test_get_respondents_by_survey_business_id_no_enrolments(self):
# Then an empty list is returned
self.assertEqual(enrolled_respondents, [])

def test_get_respondent_by_party_id(self):
# Given there is respondent
respondent = self.populate_with_respondent(respondent=self.mock_respondent)

# When get_respondent_by_party_id is called with the correct party_uuid
respondent_by_party_id = respondent_controller.get_respondent_by_party_id(respondent.party_uuid)

# Then the respondent is returned
self.assertEqual(respondent.id, respondent_by_party_id.id)

@with_db_session
def _enroll_respondent(self, session):
respondent = self.populate_with_respondent(respondent=self.mock_respondent)
Expand Down
44 changes: 43 additions & 1 deletion test/test_respondent_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from test.test_data.mock_respondent import MockRespondent
from unittest.mock import patch

from ras_party.models.models import EnrolmentStatus
from ras_party.models.models import EnrolmentStatus, Respondent


class TestRespondentView(PartyTestClient):
Expand All @@ -34,3 +34,45 @@ def test_get_respondents_by_business_and_survey_id_invalid_uuid(self):
# Then a 400 is returned with description of the error
self.assertEqual(response.status_code, 400)
self.assertEqual(response.text, "Bad request, business or survey id not UUID")

@patch("ras_party.views.respondent_view.respondent_controller.get_respondent_by_party_id")
def test_get_respondents_by_party_id(self, respondents_by_party_id):
# Given get_respondent_by_party_id is mocked to return a respondent
respondent = {
"party_uuid": "7ab8f3b6-f436-400d-8911-335a61ec58e5",
"email_address": "email address",
"first_name": "first name",
"last_name": "last name",
"telephone": "telephone",
"status": 1,
}
respondents_by_party_id.return_value = Respondent(**respondent)

# When the end point is called with the respondents party_id
response = self.get_respondents_by_party_id("7ab8f3b6-f436-400d-8911-335a61ec58e5")

# Then a 200 is returned with the correct Respondent
json_response = json.loads(response.data)
respondent["status"] = "ACTIVE" # The to_dict is returning the ResponseStatus name so this needs to be updated
self.assertEqual(response.status_code, 200)
self.assertEqual(json_response, json_response | respondent)

def test_get_respondents_by_party_id_invalid_uuid(self):
# Given/When the end point is called with an invalid uuid for party_id
response = self.get_respondents_by_party_id("invalid_uuid")

# Then a 400 is returned with description of the error
self.assertEqual(response.status_code, 400)
self.assertEqual(response.text, "party_id is not UUID")

@patch("ras_party.views.respondent_view.respondent_controller.get_respondent_by_party_id")
def test_get_respondents_by_party_id_not_found(self, respondents_by_party_id):
# Given get_respondent_by_party_id is mocked to return None
respondents_by_party_id.return_value = None

# When the end point is called
response = self.get_respondents_by_party_id("28f07933-1746-45d3-8a81-706444c33c03")

# Then a 404 is returned
self.assertEqual(response.status_code, 404)
self.assertEqual(response.text, "respondent not found for party_id 28f07933-1746-45d3-8a81-706444c33c03")

0 comments on commit 30d6003

Please sign in to comment.