From a721f62683738c29f30d09464bc462f98f80a643 Mon Sep 17 00:00:00 2001 From: Doug Lovett Date: Mon, 19 Aug 2024 13:26:39 -0700 Subject: [PATCH] Fix transfer of ownership verification report bug. (#2003) Signed-off-by: Doug Lovett --- .../src/mhr_api/models/mhr_registration.py | 66 ++++++++++++------- .../mhr_api/models/registration_json_utils.py | 39 ++++++----- .../src/mhr_api/models/registration_utils.py | 7 +- .../mhr_api/resources/registration_utils.py | 2 + mhr_api/src/mhr_api/resources/v1/transfers.py | 62 +++++++++-------- mhr_api/src/mhr_api/version.py | 2 +- 6 files changed, 107 insertions(+), 71 deletions(-) diff --git a/mhr_api/src/mhr_api/models/mhr_registration.py b/mhr_api/src/mhr_api/models/mhr_registration.py index d391a6e86..b15bca146 100755 --- a/mhr_api/src/mhr_api/models/mhr_registration.py +++ b/mhr_api/src/mhr_api/models/mhr_registration.py @@ -700,6 +700,26 @@ def create_change_from_json(base_reg, registration.documents = [doc] return registration + @staticmethod + def is_exre_transfer(base_reg, json_data: dict) -> bool: + """Determine if last owner change was from an EXRE.""" + if not model_utils.is_legacy(): + return False + if len(json_data.get('deleteOwnerGroups')) != 1 or not base_reg.change_registrations: + return False + group_id: int = json_data['deleteOwnerGroups'][0].get('groupId') + ten_type: str = json_data['deleteOwnerGroups'][0].get('type') + for reg in base_reg.change_registrations: + if reg.owner_groups: + group = reg.owner_groups[0] + current_app.logger.info(f'Checking group {group.status_type} {group.group_id} {group.tenancy_type}') + if reg.owner_groups and reg.documents[0].document_type == MhrDocumentTypes.EXRE and \ + len(reg.owner_groups) == 1 and reg.owner_groups[0].status_type == MhrOwnerStatusTypes.ACTIVE: + if reg.owner_groups[0].group_id == group_id and reg.owner_groups[0].tenancy_type == ten_type: + current_app.logger.info(f'Found matching group {group_id} and tenatncy type {ten_type}') + return True + return False + @staticmethod def create_transfer_from_json(base_reg, json_data, @@ -716,6 +736,10 @@ def create_transfer_from_json(base_reg, user_group) if base_reg.owner_groups: registration.add_new_groups(json_data, reg_utils.get_owner_group_count(base_reg)) + # If modern EXRE with no modern MHREG but group id's match, then add new groups. + elif MhrRegistration.is_exre_transfer(base_reg, json_data): + current_app.logger.info('create_transfer_from_json found EXRE transfer') + registration.add_new_groups(json_data, reg_utils.get_owner_group_count(base_reg)) if base_reg: registration.manuhome = base_reg.manuhome return registration @@ -927,32 +951,30 @@ def add_new_groups(self, json_data, existing_count: int): self.owner_groups.append(new_group) # self.adjust_group_interest(False) - def remove_groups(self, json_data, new_reg_id): + @staticmethod + def remove_group(delete_json: dict, existing: MhrOwnerGroup, new_reg_id: int, reg_type: str): + """Conditionally set status on owner group and owners.""" + if existing.group_id == delete_json.get('groupId') or \ + (model_utils.is_legacy() and not existing.interest and # modern out of sync with legacy + existing.status_type in (MhrOwnerStatusTypes.ACTIVE, MhrOwnerStatusTypes.EXEMPT)): + existing.status_type = MhrOwnerStatusTypes.PREVIOUS + existing.change_registration_id = new_reg_id + existing.modified = True + current_app.logger.info(f'Removing exsting owner group id={existing.id}, reg id={existing.registration_id}') + for owner in existing.owners: + owner.status_type = MhrOwnerStatusTypes.PREVIOUS + owner.change_registration_id = new_reg_id + if reg_utils.is_transfer_due_to_death(reg_type): + reg_utils.update_deceased(delete_json.get('owners'), owner) + + def remove_groups(self, json_data, new_reg_id: int): """Set change registration id for removed owner groups and owners for a transfer registration.""" - for group in json_data.get('deleteOwnerGroups'): # pylint: disable=too-many-nested-blocks + for group in json_data.get('deleteOwnerGroups'): for existing in self.owner_groups: # Updating a base registration owner group. - if existing.group_id == group.get('groupId'): - existing.status_type = MhrOwnerStatusTypes.PREVIOUS - existing.change_registration_id = new_reg_id - existing.modified = True - current_app.logger.info(f'Removing base owner group id={existing.id}, reg id={self.id}') - for owner in existing.owners: - owner.status_type = MhrOwnerStatusTypes.PREVIOUS - owner.change_registration_id = new_reg_id - if reg_utils.is_transfer_due_to_death(json_data.get('registrationType')): - reg_utils.update_deceased(group.get('owners'), owner) + MhrRegistration.remove_group(group, existing, new_reg_id, json_data.get('registrationType')) for reg in self.change_registrations: # Updating a change registration (previous transfer) group. for existing in reg.owner_groups: - if existing.group_id == group.get('groupId'): - existing.status_type = MhrOwnerStatusTypes.PREVIOUS - existing.change_registration_id = new_reg_id - existing.modified = True - current_app.logger.info(f'Removing base owner group id={existing.id}, reg id={self.id}') - for owner in existing.owners: - owner.status_type = MhrOwnerStatusTypes.PREVIOUS - owner.change_registration_id = new_reg_id - if reg_utils.is_transfer_due_to_death(json_data.get('registrationType')): - reg_utils.update_deceased(group.get('owners'), owner) + MhrRegistration.remove_group(group, existing, new_reg_id, json_data.get('registrationType')) @staticmethod def get_sections(json_data, registration_id: int): diff --git a/mhr_api/src/mhr_api/models/registration_json_utils.py b/mhr_api/src/mhr_api/models/registration_json_utils.py index ddb820d02..edae089bd 100644 --- a/mhr_api/src/mhr_api/models/registration_json_utils.py +++ b/mhr_api/src/mhr_api/models/registration_json_utils.py @@ -335,7 +335,7 @@ def set_group_json(registration, reg_json, current: bool, cleanup: bool = False) return reg_json -def set_transfer_group_json(registration, reg_json, doc_type: str) -> dict: +def set_transfer_group_json(registration, reg_json, doc_type: str) -> dict: # pylint: disable=too-many-branches; +1 """Build the transfer registration owner groups JSON.""" if not registration.is_transfer() and registration.registration_type != MhrRegistrationTypes.REG_STAFF_ADMIN: return reg_json @@ -343,24 +343,27 @@ def set_transfer_group_json(registration, reg_json, doc_type: str) -> dict: doc_type not in (MhrDocumentTypes.REGC_CLIENT, MhrDocumentTypes.REGC_STAFF, MhrDocumentTypes.PUBA, MhrDocumentTypes.EXRE): return reg_json - add_groups = [] - delete_groups = [] - if reg_json and registration.owner_groups: - for group in registration.owner_groups: - if group.registration_id == registration.id: - add_groups.append(group.json) - elif group.change_registration_id == registration.id: - delete_groups.append(group.json) - reg_json['addOwnerGroups'] = add_groups - if registration.change_registrations: - for reg in registration.change_registrations: - for existing in reg.owner_groups: - if existing.registration_id != registration.id and existing.change_registration_id == registration.id: - delete_groups.append(existing.json) - reg_json['deleteOwnerGroups'] = delete_groups - if not delete_groups and not add_groups and model_utils.is_legacy(): # Legacy MH home - current_app.logger.debug(f'Transfer legacy MHR {registration.mhr_number} using legacy owner groups.') + + if model_utils.is_legacy(): # Use legacy as source, modern could be out of sequence. + current_app.logger.debug(f'Transfer MHR {registration.mhr_number} using legacy owner groups.') reg_json = legacy_reg_utils.set_transfer_group_json(registration, reg_json) + else: + add_groups = [] + delete_groups = [] + if reg_json and registration.owner_groups: + for group in registration.owner_groups: + if group.registration_id == registration.id: + add_groups.append(group.json) + elif group.change_registration_id == registration.id: + delete_groups.append(group.json) + reg_json['addOwnerGroups'] = add_groups + if registration.change_registrations: + for reg in registration.change_registrations: + for existing in reg.owner_groups: + if existing.registration_id != registration.id and \ + existing.change_registration_id == registration.id: + delete_groups.append(existing.json) + reg_json['deleteOwnerGroups'] = delete_groups if reg_json.get('addOwnerGroups'): reg_json['addOwnerGroups'] = sort_owner_groups(reg_json.get('addOwnerGroups'), False) return reg_json diff --git a/mhr_api/src/mhr_api/models/registration_utils.py b/mhr_api/src/mhr_api/models/registration_utils.py index 134e34db3..8623fc2d9 100644 --- a/mhr_api/src/mhr_api/models/registration_utils.py +++ b/mhr_api/src/mhr_api/models/registration_utils.py @@ -246,11 +246,15 @@ def get_owner_group_count(base_reg) -> int: for reg in base_reg.change_registrations: if reg.owner_groups: count += len(reg.owner_groups) + if model_utils.is_legacy() and base_reg.manuhome: + legacy_count: int = len(base_reg.manuhome.reg_owner_groups) + if legacy_count > count: + return legacy_count return count def get_group_sequence_num(base_reg, add_count: int, group_id: int) -> int: - """Derive the group sequence number from the group id of an existing group with a default of 1.""" + """Derive the group sequence number from the group id of an added group with a default of 1.""" sequence_num: int = add_count if not group_id: return sequence_num @@ -329,7 +333,6 @@ def get_change_generated_values(registration, draft, user_group: str = None): query_text += DOC_ID_QUALIFIED_CLAUSE elif user_group and user_group == MANUFACTURER_GROUP: query_text += DOC_ID_MANUFACTURER_CLAUSE - # elif user_group and user_group == GOV_ACCOUNT_ROLE: else: query_text += DOC_ID_GOV_AGENT_CLAUSE query = text(query_text) diff --git a/mhr_api/src/mhr_api/resources/registration_utils.py b/mhr_api/src/mhr_api/resources/registration_utils.py index 3b3a5b7b6..43d10cfb2 100644 --- a/mhr_api/src/mhr_api/resources/registration_utils.py +++ b/mhr_api/src/mhr_api/resources/registration_utils.py @@ -195,6 +195,8 @@ def pay_and_save_transfer(req: request, # pylint: disable=too-many-arguments registration.save() if current_reg.id and current_reg.id > 0 and current_reg.owner_groups: current_reg.save_transfer(request_json, registration.id) + elif MhrRegistration.is_exre_transfer(current_reg, request_json): + current_reg.save_transfer(request_json, registration.id) return registration except Exception as db_exception: # noqa: B902; handle all db related errors. current_app.logger.error(SAVE_ERROR_MESSAGE.format(account_id, 'registration', str(db_exception))) diff --git a/mhr_api/src/mhr_api/resources/v1/transfers.py b/mhr_api/src/mhr_api/resources/v1/transfers.py index 42c8e52c6..d32c6d816 100644 --- a/mhr_api/src/mhr_api/resources/v1/transfers.py +++ b/mhr_api/src/mhr_api/resources/v1/transfers.py @@ -117,32 +117,37 @@ def setup_report(registration: MhrRegistration, # pylint: disable=too-many-loca account_id: str, current_owners): """Include all active owners in the transfer report request data and add it to the queue.""" - add_groups = response_json.get('addOwnerGroups') current_reg.current_view = True current_json = current_reg.new_registration_json current_json['ownerGroups'] = current_owners - new_groups = [] - if not response_json.get('deleteOwnerGroups'): - delete_groups = [] - for group in current_reg.owner_groups: - if group.change_registration_id == registration.id and group.status_type == MhrOwnerStatusTypes.PREVIOUS: - delete_groups.append(group.json) - response_json['deleteOwnerGroups'] = delete_groups - for group in current_json.get('ownerGroups'): - deleted: bool = False - for delete_group in response_json.get('deleteOwnerGroups'): - if delete_group.get('groupId') == group.get('groupId'): - deleted = True - if not deleted: - new_groups.append(group) - for add_group in add_groups: - added: bool = False - for new_group in new_groups: - if add_group.get('groupId') == new_group.get('groupId'): - added = True - if not added: - new_groups.append(add_group) - response_json['addOwnerGroups'] = sort_owner_groups(new_groups) + add_groups = response_json.get('addOwnerGroups') + if model_utils.is_legacy(): + current_app.logger.info('setup_report legacy configuration using response owners.') + # current_app.logger.debug(response_json.get('addOwnerGroups')) + else: + new_groups = [] + if not response_json.get('deleteOwnerGroups'): + delete_groups = [] + for group in current_reg.owner_groups: + if group.change_registration_id == registration.id and \ + group.status_type == MhrOwnerStatusTypes.PREVIOUS: + delete_groups.append(group.json) + response_json['deleteOwnerGroups'] = delete_groups + for group in current_json.get('ownerGroups'): + deleted: bool = False + for delete_group in response_json.get('deleteOwnerGroups'): + if delete_group.get('groupId') == group.get('groupId'): + deleted = True + if not deleted: + new_groups.append(group) + for add_group in add_groups: + added: bool = False + for new_group in new_groups: + if add_group.get('groupId') == new_group.get('groupId'): + added = True + if not added: + new_groups.append(add_group) + response_json['addOwnerGroups'] = sort_owner_groups(new_groups) # Report setup is current view except for FROZEN status: update report data. status: str = response_json.get('status') if status == model_utils.STATUS_FROZEN: @@ -161,11 +166,12 @@ def setup_report(registration: MhrRegistration, # pylint: disable=too-many-loca response_json, ReportTypes.MHR_TRANSFER, current_json) - response_add_groups = [] - for add_group in add_groups: - if not add_group.get('existing'): - response_add_groups.append(add_group) - response_json['addOwnerGroups'] = response_add_groups + if not model_utils.is_legacy(): + response_add_groups = [] + for add_group in add_groups: + if not add_group.get('existing'): + response_add_groups.append(add_group) + response_json['addOwnerGroups'] = response_add_groups response_json['status'] = status response_json = cleanup_owner_groups(response_json) diff --git a/mhr_api/src/mhr_api/version.py b/mhr_api/src/mhr_api/version.py index 72f5f022c..61cd3bf28 100644 --- a/mhr_api/src/mhr_api/version.py +++ b/mhr_api/src/mhr_api/version.py @@ -22,4 +22,4 @@ Development release segment: .devN """ -__version__ = '1.8.19' # pylint: disable=invalid-name +__version__ = '1.8.20' # pylint: disable=invalid-name