From 2451a773a347a43bee0e70132628fe027402048d Mon Sep 17 00:00:00 2001 From: Doug Lovett Date: Wed, 25 Oct 2023 15:14:37 -0700 Subject: [PATCH] 18224 18225 mhr new transfer types (#1602) * Add new transfer document types. Signed-off-by: Doug Lovett * Bump version, update report template. Signed-off-by: Doug Lovett --------- Signed-off-by: Doug Lovett --- mhr_api/report-templates/transferV2.html | 44 ++++++++++--------- mhr_api/requirements.txt | 2 +- mhr_api/requirements/bcregistry-libraries.txt | 2 +- mhr_api/src/mhr_api/models/db2/manuhome.py | 2 +- .../mhr_api/models/db2/registration_utils.py | 12 +++++ mhr_api/src/mhr_api/models/db2/utils.py | 5 ++- .../mhr_api/models/registration_json_utils.py | 3 +- .../src/mhr_api/models/registration_utils.py | 2 + mhr_api/src/mhr_api/models/type_tables.py | 3 +- mhr_api/src/mhr_api/version.py | 2 +- mhr_api/tests/unit/api/test_transfers.py | 43 +++++++++++++++++- .../tests/unit/models/db2/test_db2_utils.py | 34 +++++++++++++- .../unit/models/test_mhr_registration.py | 2 +- mhr_api/tests/unit/models/test_types.py | 31 ++++++++++++- .../unit/utils/test_transfer_validator.py | 13 +++++- 15 files changed, 165 insertions(+), 35 deletions(-) diff --git a/mhr_api/report-templates/transferV2.html b/mhr_api/report-templates/transferV2.html index 89ac7302b..c88d8bfaa 100644 --- a/mhr_api/report-templates/transferV2.html +++ b/mhr_api/report-templates/transferV2.html @@ -33,26 +33,30 @@ {{createDateTime}} {% if registrationType == 'TRANS' %} - - Bill of Sale Date of Execution: - - {% if transferDate is defined and transferDate != '' %} - {{transferDate}} - {% else %} - N/A - {% endif %} - - - - Consideration: - - {% if consideration is defined and consideration != '' %} - {{consideration}} - {% else %} - N/A - {% endif %} - - + {% if transferDocumentType is not defined or + transferDocumentType in ('TRANS_FAMILY_ACT', 'TRANS_INFORMAL_SALE', 'TRANS_QUIT_CLAIM', + 'TRANS_RECEIVERSHIP', 'TRANS_SEVER_GRANT', 'TRANS_WRIT_SEIZURE') %} + + Bill of Sale Date of Execution: + + {% if transferDate is defined and transferDate != '' %} + {{transferDate}} + {% else %} + N/A + {% endif %} + + + + Consideration: + + {% if consideration is defined and consideration != '' %} + {{consideration}} + {% else %} + N/A + {% endif %} + + + {% endif %} {% endif %} Folio Number: diff --git a/mhr_api/requirements.txt b/mhr_api/requirements.txt index 18fcb0f90..35ca16f7a 100644 --- a/mhr_api/requirements.txt +++ b/mhr_api/requirements.txt @@ -59,4 +59,4 @@ sentry-sdk==1.20.0 six==1.16.0 strict-rfc3339==0.7 urllib3==1.26.11 -git+https://github.com/bcgov/registry-schemas.git@1.8.4#egg=registry_schemas +git+https://github.com/bcgov/registry-schemas.git@1.8.5#egg=registry_schemas diff --git a/mhr_api/requirements/bcregistry-libraries.txt b/mhr_api/requirements/bcregistry-libraries.txt index ac0fcfd7e..e57bcc0f5 100644 --- a/mhr_api/requirements/bcregistry-libraries.txt +++ b/mhr_api/requirements/bcregistry-libraries.txt @@ -1 +1 @@ -git+https://github.com/bcgov/registry-schemas.git@1.8.4#egg=registry_schemas +git+https://github.com/bcgov/registry-schemas.git@1.8.5#egg=registry_schemas diff --git a/mhr_api/src/mhr_api/models/db2/manuhome.py b/mhr_api/src/mhr_api/models/db2/manuhome.py index d0b867ca2..a06271f37 100755 --- a/mhr_api/src/mhr_api/models/db2/manuhome.py +++ b/mhr_api/src/mhr_api/models/db2/manuhome.py @@ -670,7 +670,7 @@ def create_from_transfer(registration, reg_json): elif reg_type == MhrRegistrationTypes.TRAND: doc_type = Db2Document.DocumentTypes.TRAND else: - doc_type = Db2Document.DocumentTypes.TRANS + doc_type = legacy_reg_utils.get_transfer_doc_type(reg_json) # Create document doc: Db2Document = Db2Document.create_from_registration(registration, reg_json, diff --git a/mhr_api/src/mhr_api/models/db2/registration_utils.py b/mhr_api/src/mhr_api/models/db2/registration_utils.py index a8d2c5964..47a4b110f 100644 --- a/mhr_api/src/mhr_api/models/db2/registration_utils.py +++ b/mhr_api/src/mhr_api/models/db2/registration_utils.py @@ -258,3 +258,15 @@ def get_notes_json(reg_notes, reg_documents): notes.append(note_json) # Now sort in descending timestamp order. return sort_notes(notes) + + +def get_transfer_doc_type(reg_json) -> str: + """Get the legacy mapping of a transfer sale or gift document type.""" + doc_type = Db2Document.DocumentTypes.TRANS + if reg_json.get('transferDocumentType'): + tran_doc_type = reg_json.get('transferDocumentType') + if len(tran_doc_type) < 5: + doc_type = tran_doc_type + if len(doc_type) == 3: + doc_type += ' ' + return doc_type diff --git a/mhr_api/src/mhr_api/models/db2/utils.py b/mhr_api/src/mhr_api/models/db2/utils.py index f1d98cd11..d7878b32b 100755 --- a/mhr_api/src/mhr_api/models/db2/utils.py +++ b/mhr_api/src/mhr_api/models/db2/utils.py @@ -673,6 +673,8 @@ def __get_cancel_info(summary: dict, row) -> dict: def __set_frozen_status(summary: dict, row) -> dict: """Conditionally set FROZEN status based on active note document types or last registration doc type.""" + if summary.get('statusType', '') != MhrRegistrationStatusTypes.ACTIVE: + return summary last_doc_type: str = str(row[10]) if last_doc_type == DOCUMENT_TYPE_AFFIDAVIT: summary['statusType'] = model_utils.STATUS_FROZEN @@ -926,7 +928,8 @@ def get_non_staff_notes(reg_json): minimal_note = { 'createDateTime': note.get('createDateTime'), 'documentType': doc_type, - 'documentDescription': reg_utils.get_document_description(doc_type) + 'documentDescription': reg_utils.get_document_description(doc_type), + 'status': note.get('status', '') } if note.get('expiryDateTime') and doc_type in (MhrDocumentTypes.REG_103, MhrDocumentTypes.REG_103E): minimal_note['expiryDateTime'] = note.get('expiryDateTime') 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 746045506..1c2af7925 100644 --- a/mhr_api/src/mhr_api/models/registration_json_utils.py +++ b/mhr_api/src/mhr_api/models/registration_json_utils.py @@ -247,7 +247,8 @@ def get_non_staff_notes_json(registration, search: bool): minimal_note = { 'createDateTime': note.get('createDateTime'), 'documentType': doc_type, - 'documentDescription': note.get('documentDescription') + 'documentDescription': note.get('documentDescription'), + 'status': note.get('status', '') } if doc_type in ('REG_103', 'REG_103E') and note.get('expiryDateTime'): minimal_note['expiryDateTime'] = note.get('expiryDateTime') diff --git a/mhr_api/src/mhr_api/models/registration_utils.py b/mhr_api/src/mhr_api/models/registration_utils.py index fe72912d3..d93210c72 100644 --- a/mhr_api/src/mhr_api/models/registration_utils.py +++ b/mhr_api/src/mhr_api/models/registration_utils.py @@ -722,6 +722,8 @@ def __get_cancel_info(summary: dict, row) -> dict: def __set_frozen_status(summary: dict, row, staff: bool) -> dict: """Conditionally set FROZEN status based on active note document types or last registration doc type.""" + if summary.get('statusType', '') != MhrRegistrationStatusTypes.ACTIVE: + return summary last_doc_type: str = str(row[10]) if last_doc_type == MhrDocumentTypes.AFFE: summary['statusType'] = model_utils.STATUS_FROZEN diff --git a/mhr_api/src/mhr_api/models/type_tables.py b/mhr_api/src/mhr_api/models/type_tables.py index b436131ec..84b4e4d1d 100755 --- a/mhr_api/src/mhr_api/models/type_tables.py +++ b/mhr_api/src/mhr_api/models/type_tables.py @@ -215,8 +215,7 @@ class MhrDocumentTypes(BaseEnum): TRANS_QUIT_CLAIM = 'TRANS_QUIT_CLAIM' TRANS_SEVER_GRANT = 'TRANS_SEVER_GRANT' TRANS_RECEIVERSHIP = 'TRANS_RECEIVERSHIP' - TRANS_TRUST = 'TRANS_TRUST' - TRANS_LANDLORD = 'TRANS_LANDLORD' + TRANS_WRIT_SEIZURE = 'TRANS_WRIT_SEIZURE' class MhrLocationTypes(BaseEnum): diff --git a/mhr_api/src/mhr_api/version.py b/mhr_api/src/mhr_api/version.py index d7eb53bae..c9d9a957d 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.6.1' # pylint: disable=invalid-name +__version__ = '1.6.2' # pylint: disable=invalid-name diff --git a/mhr_api/tests/unit/api/test_transfers.py b/mhr_api/tests/unit/api/test_transfers.py index f29116f6d..601806545 100644 --- a/mhr_api/tests/unit/api/test_transfers.py +++ b/mhr_api/tests/unit/api/test_transfers.py @@ -82,7 +82,14 @@ ('Valid TRANS_WILL staff', '000921', [MHR_ROLE, STAFF_ROLE, TRANSFER_DEATH_JT], HTTPStatus.CREATED, 'PS12345', MhrRegistrationTypes.TRANS_WILL) ] - +# testdata pattern is ({description}, {mhr_num}, {roles}, {status}, {account}, {tran_doc_type}) +TEST_CREATE_DATA_TRANSFER = [ + ('Valid ABAN', '000919', [MHR_ROLE, STAFF_ROLE, TRANSFER_SALE_BENEFICIARY], HTTPStatus.CREATED, 'PS12345', 'ABAN'), + ('Valid TRANS_WRIT_SEIZURE', '000919', [MHR_ROLE, STAFF_ROLE, TRANSFER_SALE_BENEFICIARY], HTTPStatus.CREATED, + 'PS12345', 'TRANS_WRIT_SEIZURE'), + ('Invalid schema validation WILL', '000900', [MHR_ROLE, TRANSFER_SALE_BENEFICIARY], + HTTPStatus.BAD_REQUEST, 'PS12345', 'WILL'), +] @pytest.mark.parametrize('desc,mhr_num,roles,status,account', TEST_CREATE_DATA) def test_create(session, client, jwt, desc, mhr_num, roles, status, account): @@ -176,3 +183,37 @@ def test_create_transfer_death(session, client, jwt, desc, mhr_num, roles, statu # check # current_app.logger.info(response.json) assert response.status_code == status + + +@pytest.mark.parametrize('desc,mhr_num,roles,status,account,tran_doc_type', TEST_CREATE_DATA_TRANSFER) +def test_create_tran_doc(session, client, jwt, desc, mhr_num, roles, status, account, tran_doc_type): + """Assert that a post MH registration works as expected.""" + # setup + current_app.config.update(PAYMENT_SVC_URL=MOCK_PAY_URL) + current_app.config.update(AUTH_SVC_URL=MOCK_AUTH_URL) + headers = None + json_data = copy.deepcopy(TRANSFER) + if STAFF_ROLE in roles: + json_data['documentId'] = DOC_ID_VALID + else: + del json_data['documentId'] + del json_data['documentDescription'] + del json_data['createDateTime'] + del json_data['payment'] + json_data['mhrNumber'] = mhr_num + json_data['deleteOwnerGroups'][0]['groupId'] = 1 + json_data['deleteOwnerGroups'][0]['type'] = 'SOLE' + if tran_doc_type: + json_data['transferDocumentType'] = tran_doc_type + if account: + headers = create_header_account(jwt, roles, 'UT-TEST', account) + else: + headers = create_header(jwt, roles) + # test + response = client.post('/api/v1/transfers/' + mhr_num, + json=json_data, + headers=headers, + content_type='application/json') + + # check + assert response.status_code == status diff --git a/mhr_api/tests/unit/models/db2/test_db2_utils.py b/mhr_api/tests/unit/models/db2/test_db2_utils.py index ddf88835c..07588a7fb 100644 --- a/mhr_api/tests/unit/models/db2/test_db2_utils.py +++ b/mhr_api/tests/unit/models/db2/test_db2_utils.py @@ -26,7 +26,7 @@ from mhr_api.models import registration_utils as reg_utils, MhrRegistration, Db2Manuhome, utils as model_utils from mhr_api.models.registration_utils import AccountRegistrationParams -from mhr_api.models.db2 import utils as db2_utils +from mhr_api.models.db2 import utils as db2_utils, registration_utils as legacy_reg_utils from mhr_api.models.type_tables import MhrDocumentType, MhrRegistrationTypes @@ -147,6 +147,26 @@ TEST_DATA_NEW_REG = [ (LOCATION, DESCRIPTION) ] +# testdata pattern is ({tran_doc_type}, {doc_type}) +TEST_TRAN_DOC_TYPE = [ + (None, 'TRAN'), + ('TRANS_FAMILY_ACT', 'TRAN'), + ('TRANS_INFORMAL_SALE', 'TRAN'), + ('TRANS_QUIT_CLAIM', 'TRAN'), + ('TRANS_RECEIVERSHIP', 'TRAN'), + ('TRANS_SEVER_GRANT', 'TRAN'), + ('TRANS_WRIT_SEIZURE', 'TRAN'), + ('ABAN', 'ABAN'), + ('BANK', 'BANK'), + ('COU', 'COU '), + ('FORE', 'FORE'), + ('GENT', 'GENT'), + ('REIV', 'REIV'), + ('REPV', 'REPV'), + ('SZL', 'SZL '), + ('TAXS', 'TAXS'), + ('VEST', 'VEST') +] @pytest.mark.parametrize('account_id, has_results', TEST_ACCOUNT_REG_DATA) @@ -438,9 +458,9 @@ def test_get_new_reg_json_note(session, mhr_num, staff, current, has_notes, ncan assert note.get('documentType') assert note.get('documentDescription') assert note.get('createDateTime') + assert note.get('status') assert 'remarks' not in note assert 'documentRegistrationNumber' not in note - assert 'status' not in note assert 'documentId' not in note assert 'givingNoticeParty' not in note if ncan_doc_id and staff: @@ -538,3 +558,13 @@ def test_save_new_search(session, loc_data, desc_data): desc = reg_json.get('description') assert desc.get('make') == desc_data.get('make') assert desc.get('model') == desc_data.get('model') + + +@pytest.mark.parametrize('tran_doc_type,doc_type', TEST_TRAN_DOC_TYPE) +def test_tran_doc_type(session, tran_doc_type, doc_type): + """Assert that transfer sale or gift mapping of doc types works as expected.""" + reg_json = {} + if tran_doc_type: + reg_json['transferDocumentType'] = tran_doc_type + test_doc_type = legacy_reg_utils.get_transfer_doc_type(reg_json) + assert test_doc_type == doc_type diff --git a/mhr_api/tests/unit/models/test_mhr_registration.py b/mhr_api/tests/unit/models/test_mhr_registration.py index 26e39264f..9f7a465ae 100755 --- a/mhr_api/tests/unit/models/test_mhr_registration.py +++ b/mhr_api/tests/unit/models/test_mhr_registration.py @@ -572,9 +572,9 @@ def test_find_by_mhr_number_note(session, mhr_num, staff, current, has_notes, ac assert note.get('documentType') assert note.get('documentDescription') assert note.get('createDateTime') + assert note.get('status') assert 'remarks' not in note assert 'documentRegistrationNumber' not in note - assert 'status' not in note assert 'documentId' not in note assert 'givingNoticeParty' not in note if ncan_doc_id and staff: diff --git a/mhr_api/tests/unit/models/test_types.py b/mhr_api/tests/unit/models/test_types.py index f01f32dc2..88a89f12d 100755 --- a/mhr_api/tests/unit/models/test_types.py +++ b/mhr_api/tests/unit/models/test_types.py @@ -18,6 +18,7 @@ """ from mhr_api.models import type_tables +from mhr_api.models.type_tables import MhrDocumentTypes import pytest @@ -29,6 +30,22 @@ (5, type_tables.MhrRegistrationStatusType, type_tables.MhrRegistrationStatusTypes), (3, type_tables.MhrStatusType, type_tables.MhrStatusTypes) ] +# testdata pattern is ({doc_type}, {exists}) +TEST_DOC_TYPES = [ + ('XXX', False), + ('TRANS_TRUST', False), + ('TRANS_LANDLORD', False), + (MhrDocumentTypes.REG_101.value, True), + (MhrDocumentTypes.TRANS_LAND_TITLE.value, True), + (MhrDocumentTypes.TRANS_FAMILY_ACT.value, True), + (MhrDocumentTypes.TRANS_INFORMAL_SALE.value, True), + (MhrDocumentTypes.TRANS_QUIT_CLAIM.value, True), + (MhrDocumentTypes.TRANS_SEVER_GRANT.value, True), + (MhrDocumentTypes.TRANS_RECEIVERSHIP.value, True), + (MhrDocumentTypes.TRANS_WRIT_SEIZURE.value, True), + (MhrDocumentTypes.ABAN.value, True), + (MhrDocumentTypes.COU.value, True) +] @pytest.mark.parametrize('result_count, model_class, enum_class', TEST_TYPE_TABLES) @@ -77,7 +94,7 @@ def test_mhr_party_type(session): def test_mhr_document_type(session): - """Assert that MhrDocumentType.find_all() and find_by_doc_type() contains all expected elements.""" + """Assert that MhrDocumentType.find_all() contains all expected elements.""" results = type_tables.MhrDocumentType.find_all() assert results assert len(results) >= 55 @@ -94,6 +111,18 @@ def test_mhr_document_type(session): assert not doc_result +@pytest.mark.parametrize('doc_type, exists', TEST_DOC_TYPES) +def test_mhr_document_type_find(session, doc_type, exists): + """Assert that MhrDocumentType.find_by_doc_type() works as expected.""" + doc_result = type_tables.MhrDocumentType.find_by_doc_type(doc_type) + if exists: + assert doc_result + assert doc_result.document_type + assert doc_result.document_type_desc + else: + assert not doc_result + + def test_mhr_location_type(session): """Assert that MhrLocationType.find_all() contains all expected elements.""" results = type_tables.MhrLocationType.find_all() diff --git a/mhr_api/tests/unit/utils/test_transfer_validator.py b/mhr_api/tests/unit/utils/test_transfer_validator.py index 18f5f6f88..ae1b62959 100644 --- a/mhr_api/tests/unit/utils/test_transfer_validator.py +++ b/mhr_api/tests/unit/utils/test_transfer_validator.py @@ -253,8 +253,17 @@ ('Valid TRANS_QUIT_CLAIM', True, 'TRANS_QUIT_CLAIM', MhrRegistrationTypes.TRANS, None), ('Valid TRANS_SEVER_GRANT', True, 'TRANS_SEVER_GRANT', MhrRegistrationTypes.TRANS, None), ('Valid TRANS_RECEIVERSHIP', True, 'TRANS_RECEIVERSHIP', MhrRegistrationTypes.TRANS, None), - ('Valid TRANS_TRUST', True, 'TRANS_TRUST', MhrRegistrationTypes.TRANS, None), - ('Valid TRANS_LANDLORD', True, 'TRANS_LANDLORD', MhrRegistrationTypes.TRANS, None), + ('Valid TRANS_WRIT_SEIZURE', True, 'TRANS_WRIT_SEIZURE', MhrRegistrationTypes.TRANS, None), + ('Valid ABAN', True, 'ABAN', MhrRegistrationTypes.TRANS, None), + ('Valid BANK', True, 'BANK', MhrRegistrationTypes.TRANS, None), + ('Valid COU', True, 'COU', MhrRegistrationTypes.TRANS, None), + ('Valid FORE', True, 'FORE', MhrRegistrationTypes.TRANS, None), + ('Valid GENT', True, 'GENT', MhrRegistrationTypes.TRANS, None), + ('Valid REIV', True, 'REIV', MhrRegistrationTypes.TRANS, None), + ('Valid REPV', True, 'REPV', MhrRegistrationTypes.TRANS, None), + ('Valid SZL', True, 'SZL', MhrRegistrationTypes.TRANS, None), + ('Valid TAXS', True, 'TAXS', MhrRegistrationTypes.TRANS, None), + ('Valid VEST', True, 'VEST', MhrRegistrationTypes.TRANS, None), ('Invalid doc type', False, 'WILL', MhrRegistrationTypes.TRANS, 'data validation errors'), ('Invalid reg type', False, 'TRANS_TRUST', MhrRegistrationTypes.TRAND, validator.TRANS_DOC_TYPE_INVALID) ]