diff --git a/src/registry_schemas/example_data/mhr/__init__.py b/src/registry_schemas/example_data/mhr/__init__.py index 64209c0..695012f 100644 --- a/src/registry_schemas/example_data/mhr/__init__.py +++ b/src/registry_schemas/example_data/mhr/__init__.py @@ -33,6 +33,7 @@ SEARCH_QUERY_RESULT, SEARCH_SUMMARY, SECTION_INFORMATION, + TRANSFER, ) @@ -53,5 +54,6 @@ 'SEARCH_QUERY', 'SEARCH_QUERY_RESULT', 'SEARCH_SUMMARY', - 'SECTION_INFORMATION' + 'SECTION_INFORMATION', + 'TRANSFER' ] diff --git a/src/registry_schemas/example_data/mhr/schema_data.py b/src/registry_schemas/example_data/mhr/schema_data.py index c0812a5..1cd0398 100644 --- a/src/registry_schemas/example_data/mhr/schema_data.py +++ b/src/registry_schemas/example_data/mhr/schema_data.py @@ -53,6 +53,8 @@ } LOCATION = { + 'locationType': 'MH_PARK', + 'status': 'ACTIVE', 'parkName': 'HIDDEN VALLEY TRAILER COURT', 'pad': '20', 'address': { @@ -181,6 +183,7 @@ REGISTRATION = { 'mhrNumber': '001234', 'documentId': '42800656', + 'documentDescription': 'REGISTER NEW UNIT', 'status': 'ACTIVE', 'clientReferenceId': 'EX-MH001234', 'declaredValue': '120000.00', @@ -248,6 +251,8 @@ } ], 'location': { + 'locationType': 'OTHER', + 'status': 'ACTIVE', 'parkName': 'HIDDEN VALLEY TRAILER COURT', 'pad': '20', 'address': { @@ -410,6 +415,7 @@ } ], 'location': { + 'locationType': 'OTHER', 'parkName': 'HIDDEN VALLEY TRAILER COURT', 'pad': '20', 'address': { @@ -537,3 +543,74 @@ 'widthFeet': 12, 'widthInches': 0 } + +TRANSFER = { + 'mhrNumber': '125234', + 'documentId': '10104535', + 'documentDescription': 'SALE OR GIFT', + 'clientReferenceId': 'EX-TRANS-001', + 'submittingParty': { + 'businessName': 'ABC SEARCHING COMPANY', + 'address': { + 'street': '222 SUMMER STREET', + 'city': 'VICTORIA', + 'region': 'BC', + 'country': 'CA', + 'postalCode': 'V8W 2V8' + }, + 'emailAddress': 'bsmith@abc-search.com', + 'phoneNumber': '6041234567', + 'phoneExtension': '546' + }, + 'deleteOwnerGroups': [ + { + 'groupId': 1, + 'owners': [ + { + 'individualName': { + 'first': 'Jane', + 'last': 'Smith' + }, + 'address': { + 'street': '3122B LYNNLARK PLACE', + 'city': 'VICTORIA', + 'region': 'BC', + 'postalCode': ' ', + 'country': 'CA' + }, + 'phoneNumber': '6041234567' + } + ], + 'type': 'SOLE' + } + ], + 'addOwnerGroups': [ + { + 'groupId': 2, + 'owners': [ + { + 'individualName': { + 'first': 'James', + 'last': 'Smith' + }, + 'address': { + 'street': '3122B LYNNLARK PLACE', + 'city': 'VICTORIA', + 'region': 'BC', + 'postalCode': ' ', + 'country': 'CA' + }, + 'phoneNumber': '6041234567' + } + ], + 'type': 'SOLE', + 'status': 'ACTIVE' + } + ], + 'createDateTime': '2020-02-21T18:56:20+00:00', + 'deathOfOwner': False, + 'payment': { + 'receipt': '/pay/api/v1/payment-requests/2199900/receipts', + 'invoiceId': '2199900' + } +} diff --git a/src/registry_schemas/schemas/mhr/location.json b/src/registry_schemas/schemas/mhr/location.json index 0004437..65e1e51 100644 --- a/src/registry_schemas/schemas/mhr/location.json +++ b/src/registry_schemas/schemas/mhr/location.json @@ -4,6 +4,18 @@ "type": "object", "title": "The MHR Location Schema", "properties": { + "locationType": { + "type": "string", + "maxLength": 20, + "enum": ["MANUFACTURER", "MH_PARK", "RESERVE", "STRATA", "OTHER"], + "description": "The location type. Use OTHER if type is unknown." + }, + "status": { + "type": [ "string", "null" ], + "maxLength": 20, + "enum": ["ACTIVE", "DRAFT", "HISTORICAL"], + "description": "The status of the location information." + }, "parkName": { "type": [ "string", "null" ], "maxLength": 40, @@ -52,7 +64,7 @@ }, "legalDescription": { "type": [ "string", "null" ], - "maxLength": 512, + "maxLength": 1000, "description": "LTSA parcel identifier legal description. May be submitted with new registrations requests. In the future it may be included in search results." }, "lot": { @@ -112,6 +124,7 @@ } }, "required": [ + "locationType", "address" ] } diff --git a/src/registry_schemas/schemas/mhr/registration.json b/src/registry_schemas/schemas/mhr/registration.json index 0bc1df7..d2018d7 100644 --- a/src/registry_schemas/schemas/mhr/registration.json +++ b/src/registry_schemas/schemas/mhr/registration.json @@ -16,6 +16,11 @@ "minLength": 8, "description": "Unique registration document ID/number required for new registrations as a reference to the decal; assigned by the Manufactured Home Registry." }, + "documentDescription": { + "type": [ "string", "null" ], + "maxLength": 100, + "description": "Included in a response as a description of the registration report document." + }, "status": { "type": [ "string", "null" ], "maxLength": 20, diff --git a/src/registry_schemas/schemas/mhr/transfer.json b/src/registry_schemas/schemas/mhr/transfer.json new file mode 100644 index 0000000..aff2bed --- /dev/null +++ b/src/registry_schemas/schemas/mhr/transfer.json @@ -0,0 +1,64 @@ +{ + "definitions": {}, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://bcrs.gov.bc.ca/.well_known/schemas/mhr/transfer", + "type": "object", + "title": "The MHR Manufactured Home Transfer of Sale/Owner Schema", + "properties": { + "mhrNumber": { + "type": [ "string", "null" ], + "maxLength": 6, + "description": "Unique manufactured home registration number assigned by the Manufactured Home Registry when a registration is created." + }, + "documentId": { + "type": [ "string", "null" ], + "maxLength": 8, + "minLength": 8, + "description": "Unique registration document ID/number assigned by the Manufactured Home Registry." + }, + "documentDescription": { + "type": [ "string", "null" ], + "maxLength": 100, + "description": "Included in a response as a description of the registration report document." + }, + "clientReferenceId": { + "type": [ "string", "null" ], + "maxLength": 40, + "description": "An optional client reference identifier associated with a change. Provided to facilitate client tracking of MHR activity." + }, + "submittingParty": { + "$ref": "https://bcrs.gov.bc.ca/.well_known/schemas/common/party" + }, + "deleteOwnerGroups": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "https://bcrs.gov.bc.ca/.well_known/schemas/mhr/ownerGroup" + } + }, + "addOwnerGroups": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "https://bcrs.gov.bc.ca/.well_known/schemas/mhr/ownerGroup" + } + }, + "createDateTime": { + "type": [ "string", "null" ], + "format": "date-time", + "description": "Generated by the MHR system and included in a response, the date and time a record is created in the system in the ISO 8601 format YYYY-MM-DDThh:mm:ssTZD." + }, + "deathOfOwner": { + "type": "boolean", + "description": "Set to true when transferfing fractional interest in a home because a partner in a joint tenancy has died." + }, + "payment": { + "$ref": "https://bcrs.gov.bc.ca/.well_known/schemas/common/paymentReference" + } + }, + "required": [ + "submittingParty", + "deleteOwnerGroups", + "addOwnerGroups" + ] +} \ No newline at end of file diff --git a/src/registry_schemas/version.py b/src/registry_schemas/version.py index fb5dee6..c9d9a95 100644 --- a/src/registry_schemas/version.py +++ b/src/registry_schemas/version.py @@ -22,4 +22,4 @@ Development release segment: .devN """ -__version__ = '1.2.0' # pylint: disable=invalid-name +__version__ = '1.6.2' # pylint: disable=invalid-name diff --git a/tests/unit/mhr/test_location.py b/tests/unit/mhr/test_location.py index 6f71750..13aa3c0 100644 --- a/tests/unit/mhr/test_location.py +++ b/tests/unit/mhr/test_location.py @@ -79,12 +79,23 @@ ('Invalid plan too long', False, LTSA_MAX, LTSA_MAX, LTSA_MAX, LTSA_DISTRICT_MAX, LTSA_MAX, LTSA_MAX, '12', '12', '123', LTSA_LAND_DISTRICT_MAX, LTSA_PLAN_MAX + 'X') ] +# testdata pattern is ({desc}, {valid}, {type}) +TEST_DATA_LOCATION_TYPE = [ + ('Valid MANUFACTURER', True, 'MANUFACTURER'), + ('Valid MH_PARK', True, 'MH_PARK'), + ('Valid RESERVE', True, 'RESERVE'), + ('Valid STRATA', True, 'STRATA'), + ('Valid OTHER', True, 'OTHER'), + ('Invalid', False, 'DEALER'), + ('Invalid missing', False, None) +] @pytest.mark.parametrize('desc,valid,park_name,pad,address,pid,tax_date,dealer', TEST_DATA_LOCATION) def test_location(desc, valid, park_name, pad, address, pid, tax_date, dealer): """Assert that the schema is performing as expected.""" data = { + 'locationType': 'OTHER', 'address': address } if park_name: @@ -156,3 +167,23 @@ def test_location_ltsa(desc, valid, lot, parcel, block, dlot, part, section, tow assert is_valid else: assert not is_valid + + +@pytest.mark.parametrize('desc,valid,type', TEST_DATA_LOCATION_TYPE) +def test_location_type(desc, valid, type): + """Assert that the schema locationType field valiation is performing as expected.""" + data = copy.deepcopy(LOCATION) + if type: + data['locationType'] = type + else: + del data['locationType'] + is_valid, errors = validate(data, 'location', 'mhr') + + if errors: + for err in errors: + print(err.message) + + if valid: + assert is_valid + else: + assert not is_valid diff --git a/tests/unit/mhr/test_transfer.py b/tests/unit/mhr/test_transfer.py new file mode 100644 index 0000000..15d76b5 --- /dev/null +++ b/tests/unit/mhr/test_transfer.py @@ -0,0 +1,102 @@ +# Copyright © 2020 Province of British Columbia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Test Suite to ensure the MHR transfer (tranfer of sale) schema is valid.""" +import copy + +import pytest + +from registry_schemas import validate +from registry_schemas.example_data.mhr import TRANSFER + + +PARTY_VALID = { + 'personName': { + 'first': 'Michael', + 'middle': 'J', + 'last': 'Smith' + }, + 'address': { + 'street': '520 Johnson St', + 'city': 'Victoria', + 'region': 'BC', + 'country': 'CA', + 'postalCode': 'V8S 2V4' + }, + 'emailAddress': 'msmith@gmail.com', + 'phoneNumber': '6042314598', + 'phoneExtension': '546' +} +PARTY_INVALID = { + 'personName': { + 'first': 'Michael', + 'middle': 'J', + 'last': 'Smith' + }, + 'address': { + 'street': '520 Johnson St', + 'city': 'Victoria', + 'region': 'BC', + 'country': 'CA', + 'postalCode': 'V8S 2V4' + }, + 'emailAddress': 'msmith@gmail.com', + 'phoneNumber': '2314598' +} +LONG_CLIENT_REF = '01234567890123456789012345678901234567890' + +# testdata pattern is ({desc},{valid},{sub_party},{add},{delete},{is_request},{client_ref}) +TEST_DATA = [ + ('Valid request', True, PARTY_VALID, True, True, True, None), + ('Valid response', True, PARTY_VALID, True, True, False, '1234'), + ('Invalid client ref', False, PARTY_VALID, True, True, True, LONG_CLIENT_REF), + ('Invalid sub party', False, PARTY_INVALID, True, True, True, '1234'), + ('Missing sub party', False, None, True, True, True, '1234'), + ('Invalid missing add', False, PARTY_VALID, False, True, True, '1234'), + ('Invalid missing delete', False, PARTY_VALID, True, False, True, ''), +] + + +@pytest.mark.parametrize('desc,valid,sub_party,add,delete,is_request,client_ref', TEST_DATA) +def test_transfer(desc, valid, sub_party, add, delete, is_request, client_ref): + """Assert that the schema is performing as expected.""" + data = copy.deepcopy(TRANSFER) + if sub_party: + data['submittingParty'] = sub_party + else: + del data['submittingParty'] + if client_ref: + data['clientReferenceId'] = client_ref + else: + del data['clientReferenceId'] + if is_request: + del data['createDateTime'] + del data['payment'] + del data['mhrNumber'] + del data['documentId'] + del data['documentDescription'] + if not add: + del data['addOwnerGroups'] + if not delete: + del data['deleteOwnerGroups'] + + is_valid, errors = validate(data, 'transfer', 'mhr') + + if errors: + for err in errors: + print(err.message) + + if valid: + assert is_valid + else: + assert not is_valid