From 11a85a07fc0b881930b6c59889b18489523e3dbf Mon Sep 17 00:00:00 2001 From: SteveScorfield Date: Tue, 10 Sep 2024 12:15:45 +0100 Subject: [PATCH 1/4] The updated code that streamlines some of the dictionaries --- ras_party/controllers/business_controller.py | 15 +++- ras_party/controllers/party_controller.py | 9 ++- ras_party/models/model_functions.py | 40 ++++++++++ ras_party/models/models.py | 74 +------------------ ras_party/unified_buisness_party_functions.py | 18 +++++ 5 files changed, 78 insertions(+), 78 deletions(-) create mode 100644 ras_party/models/model_functions.py create mode 100644 ras_party/unified_buisness_party_functions.py diff --git a/ras_party/controllers/business_controller.py b/ras_party/controllers/business_controller.py index 3ef0debc..c1c439f7 100644 --- a/ras_party/controllers/business_controller.py +++ b/ras_party/controllers/business_controller.py @@ -5,6 +5,7 @@ from flask import current_app from werkzeug.exceptions import BadRequest, NotFound +from ras_party import unified_buisness_party_functions from ras_party.controllers.queries import ( query_business_attributes, query_business_attributes_by_collection_exercise, @@ -39,7 +40,9 @@ def get_business_by_ref(ref, session): logger.info("Business with reference does not exist.", ru_ref=ref) raise NotFound("Business with reference does not exist.") - return business.to_party_dict() + return unified_buisness_party_functions.to_unified_dict( + business, collection_exercise_id=None, attributes_required=True + ) @with_query_only_db_session @@ -60,7 +63,7 @@ def get_businesses_by_ids(party_uuids, session): raise BadRequest(f"'{party_uuid}' is not a valid UUID format for property 'id'") businesses = query_businesses_by_party_uuids(party_uuids, session) - return [business.to_business_summary_dict() for business in businesses] + return [unified_buisness_party_functions.to_unified_dict(business) for business in businesses] @with_query_only_db_session @@ -126,10 +129,14 @@ def get_business_by_id(party_uuid, session, verbose=False, collection_exercise_i logger.info("Business with id does not exist", party_uuid=party_uuid) raise NotFound("Business with party id does not exist") + unified_dict = unified_buisness_party_functions.to_unified_dict( + business, collection_exercise_id=collection_exercise_id, attributes_required=True + ) + if verbose: - return business.to_business_dict(collection_exercise_id=collection_exercise_id) + return dict(unified_dict, **unified_dict["attributes"]) - return business.to_business_summary_dict(collection_exercise_id=collection_exercise_id) + return unified_buisness_party_functions.to_unified_dict(business, collection_exercise_id=collection_exercise_id) @with_db_session diff --git a/ras_party/controllers/party_controller.py b/ras_party/controllers/party_controller.py index 02a5a786..28a5c159 100644 --- a/ras_party/controllers/party_controller.py +++ b/ras_party/controllers/party_controller.py @@ -4,6 +4,7 @@ from flask import current_app from werkzeug.exceptions import BadRequest, Conflict, NotFound +from ras_party import unified_buisness_party_functions from ras_party.controllers.queries import ( query_business_attributes_by_sample_summary_id, query_business_by_party_uuid, @@ -93,13 +94,17 @@ def get_party_by_id(sample_unit_type, party_id, session): if not business: logger.info("Business with id does not exist", business_id=party_id, status=404) raise NotFound("Business with id does not exist") - return business.to_party_dict() + return unified_buisness_party_functions.to_unified_dict( + business, collection_exercise_id=None, attributes_required=True + ) elif sample_unit_type == Respondent.UNIT_TYPE: respondent = query_respondent_by_party_uuid(party_id, session) if not respondent: logger.info("Respondent with id does not exist", respondent_id=party_id, status=404) raise NotFound("Respondent with id does not exist") - return respondent.to_party_dict() + return unified_buisness_party_functions.to_unified_dict( + respondent, collection_exercise_id=None, attributes_required=True + ) else: logger.info("Invalid sample unit type", type=sample_unit_type) raise BadRequest(f"{sample_unit_type} is not a valid value for sampleUnitType. Must be one of ['B', 'BI']") diff --git a/ras_party/models/model_functions.py b/ras_party/models/model_functions.py new file mode 100644 index 00000000..2d7b45e3 --- /dev/null +++ b/ras_party/models/model_functions.py @@ -0,0 +1,40 @@ +import logging + +import structlog +from werkzeug.exceptions import BadRequest + +from ras_party.models import models + +logger = structlog.wrap_logger(logging.getLogger(__name__)) + + +def get_respondents_associations(respondents): + associations = [] + for business_respondent in respondents: + respondent_dict = { + "partyId": business_respondent.respondent.party_uuid, + "businessRespondentStatus": business_respondent.respondent.status.name, + } + enrolments = business_respondent.enrolment + respondent_dict["enrolments"] = [] + for enrolment in enrolments: + enrolments_dict = { + "surveyId": enrolment.survey_id, + "enrolmentStatus": models.EnrolmentStatus(enrolment.status).name, + } + respondent_dict["enrolments"].append(enrolments_dict) + associations.append(respondent_dict) + return associations + + +def get_attributes_for_collection_exercise(model_attributes, collection_exercise_id=None): + if collection_exercise_id: + for attributes in model_attributes.attributes: + if attributes.collection_exercise == collection_exercise_id: + return attributes + + try: + return next((attributes for attributes in model_attributes.attributes if attributes.collection_exercise)) + except StopIteration: + logger.error("No active attributes for business", reference=model_attributes.business_ref, status=400) + raise BadRequest("Business with reference does not have any active attributes.") diff --git a/ras_party/models/models.py b/ras_party/models/models.py index f2168bdd..dcbbee94 100644 --- a/ras_party/models/models.py +++ b/ras_party/models/models.py @@ -19,8 +19,8 @@ from sqlalchemy.dialects.postgresql import JSONB, UUID from sqlalchemy.orm import declarative_base, relationship from sqlalchemy.types import Enum -from werkzeug.exceptions import BadRequest +from ras_party.models import model_functions from ras_party.support.util import filter_falsey_values, partition_dict Base = declarative_base() @@ -97,64 +97,6 @@ def _populate_name_and_trading_as(ba): ba.name = name ba.trading_as = trading_as - @staticmethod - def _get_respondents_associations(respondents): - associations = [] - for business_respondent in respondents: - respondent_dict = { - "partyId": business_respondent.respondent.party_uuid, - "businessRespondentStatus": business_respondent.respondent.status.name, - } - enrolments = business_respondent.enrolment - respondent_dict["enrolments"] = [] - for enrolment in enrolments: - enrolments_dict = { - "surveyId": enrolment.survey_id, - "enrolmentStatus": EnrolmentStatus(enrolment.status).name, - } - respondent_dict["enrolments"].append(enrolments_dict) - associations.append(respondent_dict) - return associations - - def to_business_dict(self, collection_exercise_id=None): - """ - Gets a dict that contains both summary data and collection exercise data. The collection exercise data will be - for either the specified one if supplied, or the most recent one if not supplied - - :param collection_exercise_id: A collection exercise uuid - :return: A dict containing both the summary data and business attributes for the business - :rtype: dict - """ - d = self.to_business_summary_dict() - attributes = self._get_attributes_for_collection_exercise(collection_exercise_id) - return dict(d, **attributes.attributes) - - def to_business_summary_dict(self, collection_exercise_id=None): - attributes = self._get_attributes_for_collection_exercise(collection_exercise_id) - d = { - "id": self.party_uuid, - "sampleUnitRef": self.business_ref, - "sampleUnitType": self.UNIT_TYPE, - "sampleSummaryId": attributes.sample_summary_id, - "name": attributes.attributes.get("name"), - "trading_as": attributes.attributes.get("trading_as"), - "associations": self._get_respondents_associations(self.respondents), - } - return d - - def to_party_dict(self): - attributes = self._get_attributes_for_collection_exercise() - return { - "id": self.party_uuid, - "sampleUnitRef": self.business_ref, - "sampleUnitType": self.UNIT_TYPE, - "sampleSummaryId": attributes.sample_summary_id, - "attributes": attributes.attributes, - "name": attributes.attributes.get("name"), - "trading_as": attributes.attributes.get("trading_as"), - "associations": self._get_respondents_associations(self.respondents), - } - def to_post_response_dict(self): return { "id": self.party_uuid, @@ -164,21 +106,9 @@ def to_post_response_dict(self): "attributes": self.attributes[-1].attributes, "name": self.attributes[-1].name, "trading_as": self.attributes[-1].trading_as, - "associations": self._get_respondents_associations(self.respondents), + "associations": model_functions.get_respondents_associations(self.respondents), } - def _get_attributes_for_collection_exercise(self, collection_exercise_id=None): - if collection_exercise_id: - for attributes in self.attributes: - if attributes.collection_exercise == collection_exercise_id: - return attributes - - try: - return next((attributes for attributes in self.attributes if attributes.collection_exercise)) - except StopIteration: - logger.error("No active attributes for business", reference=self.business_ref, status=400) - raise BadRequest("Business with reference does not have any active attributes.") - class BusinessAttributes(Base): __tablename__ = "business_attributes" diff --git a/ras_party/unified_buisness_party_functions.py b/ras_party/unified_buisness_party_functions.py new file mode 100644 index 00000000..43ef6bcc --- /dev/null +++ b/ras_party/unified_buisness_party_functions.py @@ -0,0 +1,18 @@ +from ras_party.models import model_functions + + +def to_unified_dict(model, collection_exercise_id=None, attributes_required=False): + attributes = model_functions.get_attributes_for_collection_exercise(model, collection_exercise_id) + unified_dict = { + "id": model.party_uuid, + "sampleUnitRef": model.business_ref, + "sampleUnitType": model.UNIT_TYPE, + "sampleSummaryId": attributes.sample_summary_id, + "name": attributes.attributes.get("name"), + "trading_as": attributes.attributes.get("trading_as"), + "associations": model_functions.get_respondents_associations(model.respondents), + } + if attributes_required: + unified_dict["attributes"] = attributes.attributes + + return unified_dict From bbd39803fa01a1cd4621ecbfd3a307f9de925a91 Mon Sep 17 00:00:00 2001 From: ras-rm-pr-bot Date: Tue, 10 Sep 2024 11:32:34 +0000 Subject: [PATCH 2/4] auto patch increment --- _infra/helm/party/Chart.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_infra/helm/party/Chart.yaml b/_infra/helm/party/Chart.yaml index a63360e7..4989807b 100644 --- a/_infra/helm/party/Chart.yaml +++ b/_infra/helm/party/Chart.yaml @@ -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.2 +version: 2.5.3 # 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.2 +appVersion: 2.5.3 From c177ba811888f31449777e620d662780efcc4084 Mon Sep 17 00:00:00 2001 From: SteveScorfield Date: Tue, 10 Sep 2024 13:02:56 +0100 Subject: [PATCH 3/4] Adding additional endpoint for rOps --- ras_party/controllers/business_controller.py | 4 ++-- ras_party/unified_buisness_party_functions.py | 5 +++-- ras_party/views/business_view.py | 7 +++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ras_party/controllers/business_controller.py b/ras_party/controllers/business_controller.py index c1c439f7..52e9c199 100644 --- a/ras_party/controllers/business_controller.py +++ b/ras_party/controllers/business_controller.py @@ -26,7 +26,7 @@ @with_query_only_db_session -def get_business_by_ref(ref, session): +def get_business_by_ref(ref, session, retrieve_associations=True): """ Get a Business by its unique business reference @@ -41,7 +41,7 @@ def get_business_by_ref(ref, session): raise NotFound("Business with reference does not exist.") return unified_buisness_party_functions.to_unified_dict( - business, collection_exercise_id=None, attributes_required=True + business, collection_exercise_id=None, attributes_required=True, retrieve_associations=retrieve_associations ) diff --git a/ras_party/unified_buisness_party_functions.py b/ras_party/unified_buisness_party_functions.py index 43ef6bcc..793ed6c7 100644 --- a/ras_party/unified_buisness_party_functions.py +++ b/ras_party/unified_buisness_party_functions.py @@ -1,7 +1,7 @@ from ras_party.models import model_functions -def to_unified_dict(model, collection_exercise_id=None, attributes_required=False): +def to_unified_dict(model, collection_exercise_id=None, attributes_required=False, retrieve_associations=True): attributes = model_functions.get_attributes_for_collection_exercise(model, collection_exercise_id) unified_dict = { "id": model.party_uuid, @@ -10,9 +10,10 @@ def to_unified_dict(model, collection_exercise_id=None, attributes_required=Fals "sampleSummaryId": attributes.sample_summary_id, "name": attributes.attributes.get("name"), "trading_as": attributes.attributes.get("trading_as"), - "associations": model_functions.get_respondents_associations(model.respondents), } if attributes_required: unified_dict["attributes"] = attributes.attributes + if retrieve_associations: + unified_dict["associations"] = model_functions.get_respondents_associations(model.respondents) return unified_dict diff --git a/ras_party/views/business_view.py b/ras_party/views/business_view.py index 154229c4..39e12844 100644 --- a/ras_party/views/business_view.py +++ b/ras_party/views/business_view.py @@ -79,6 +79,13 @@ def get_business_by_ref(ref): return jsonify(business) +@business_view.route("/businesses/ref/reporting-unit-only/", methods=["GET"]) +def get_business_by_ref_only(ref): + # This endpoint will retrieve the reporting unit only and not the associations. + business = business_controller.get_business_by_ref(ref, True) + return jsonify(business) + + @business_view.route("/businesses/sample/link/", methods=["PUT"]) def put_business_attributes_ce(sample): payload = request.get_json() or {} From 0167688adc6d3553f37f087d71e4d307cf3f64b9 Mon Sep 17 00:00:00 2001 From: SteveScorfield Date: Tue, 10 Sep 2024 13:13:38 +0100 Subject: [PATCH 4/4] Use declared variable in method call --- ras_party/views/business_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ras_party/views/business_view.py b/ras_party/views/business_view.py index 39e12844..7f720fec 100644 --- a/ras_party/views/business_view.py +++ b/ras_party/views/business_view.py @@ -82,7 +82,7 @@ def get_business_by_ref(ref): @business_view.route("/businesses/ref/reporting-unit-only/", methods=["GET"]) def get_business_by_ref_only(ref): # This endpoint will retrieve the reporting unit only and not the associations. - business = business_controller.get_business_by_ref(ref, True) + business = business_controller.get_business_by_ref(ref, retrieve_associations=True) return jsonify(business)