Skip to content

Commit

Permalink
New reg add legacy db limitation validation rules. (#938)
Browse files Browse the repository at this point in the history
Signed-off-by: Doug Lovett <[email protected]>

Signed-off-by: Doug Lovett <[email protected]>
  • Loading branch information
doug-lovett authored Sep 12, 2022
1 parent ff914b5 commit 0e6cecf
Show file tree
Hide file tree
Showing 6 changed files with 295 additions and 59 deletions.
16 changes: 13 additions & 3 deletions mhr_api/src/mhr_api/models/db2/location.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,15 @@ def json(self):
@property
def registration_json(self):
"""Return a search registration dict of this object, with keys in JSON format."""
street = self.street_number + ' ' + self.street_name
if len(self.street_number) == 6:
street = self.street_number + self.street_name
location = {
'parkName': self.park_name,
'pad': self.park_pad,
'status': LEGACY_STATUS_NEW.get(self.status),
'address': {
'street': self.street_number + ' ' + self.street_name,
'street': street,
'city': self.town_city,
'region': self.province,
'country': 'CA',
Expand Down Expand Up @@ -218,12 +221,15 @@ def registration_json(self):
def new_registration_json(self):
"""Return a dict of this object, with keys in JSON format."""
self.strip()
street = self.street_number + ' ' + self.street_name
if len(self.street_number) == 6:
street = self.street_number + self.street_name
location = {
'parkName': self.park_name,
'pad': self.park_pad,
'status': LEGACY_STATUS_NEW.get(self.status),
'address': {
'street': self.street_number + ' ' + self.street_name,
'street': street,
'city': self.town_city,
'region': self.province,
'country': 'CA',
Expand Down Expand Up @@ -303,7 +309,11 @@ def create_from_registration(registration, reg_json):
street = str(address['street'])
street_info = street.split(' ')
street_num = street_info[0]
street_name = street[len(street_num):]
if len(street_num) < 7:
street_name = street[len(street_num):].strip()
else: # Adjust; db table column length is 6.
street_num = street[0:6]
street_name = street[6:]
location = Db2Location(manuhome_id=registration.id,
location_id=1,
status=Db2Location.StatusTypes.ACTIVE,
Expand Down
Empty file modified mhr_api/src/mhr_api/models/db2/utils.py
100644 → 100755
Empty file.
5 changes: 5 additions & 0 deletions mhr_api/src/mhr_api/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""This module holds general utility functions and helpers for the main package."""


def valid_charset(word: str) -> bool:
"""Verify word characters adhere to a supported set."""
return word == word.encode('ascii', 'ignore').decode('utf-8')
109 changes: 95 additions & 14 deletions mhr_api/src/mhr_api/utils/registration_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@
from flask import current_app

from mhr_api.models import MhrRegistration
from mhr_api.models.utils import is_legacy
from mhr_api.utils import valid_charset


OWNERS_NOT_ALLOWED = 'Owners not allowed with new registrations: use ownerGroups instead.'
DOC_ID_REQUIRED = 'Document ID is required for staff registrations.'
SUBMITTING_REQUIRED = 'Submitting Party is required for MH registrations.'
OWNER_GROUPS_REQUIRED = 'At least one owner group is required for staff registrations.'
OWNER_GROUPS_REQUIRED = 'At least one owner group is required for staff registrations.'
DOC_ID_EXISTS = 'Document ID must be unique: provided value already exists.'
DOC_ID_INVALID_CHECKSUM = 'Document ID is invalid: checksum failed.'
OWNERS_NOT_ALLOWED = 'Owners not allowed with new registrations: use ownerGroups instead. '
DOC_ID_REQUIRED = 'Document ID is required for staff registrations. '
SUBMITTING_REQUIRED = 'Submitting Party is required for MH registrations. '
OWNER_GROUPS_REQUIRED = 'At least one owner group is required for staff registrations. '
DOC_ID_EXISTS = 'Document ID must be unique: provided value already exists. '
DOC_ID_INVALID_CHECKSUM = 'Document ID is invalid: checksum failed. '
LEGACY_ADDRESS_STREET_TOO_LONG = '{add_desc} address street length is too long: maximum length 31 characters. '
LEGACY_ADDRESS_CITY_TOO_LONG = '{add_desc} address city length is too long: maximum length 20 characters. '
CHARACTER_SET_UNSUPPORTED = 'The character set is not supported for {desc} value {value}. '


def validate_registration(json_data, is_staff: bool = False):
Expand All @@ -36,22 +40,27 @@ def validate_registration(json_data, is_staff: bool = False):
error_msg += validate_doc_id(json_data)
if not json_data.get('ownerGroups'):
error_msg += OWNER_GROUPS_REQUIRED
if json_data.get('owners'):
error_msg += OWNERS_NOT_ALLOWED
if not json_data.get('submittingParty'):
error_msg += SUBMITTING_REQUIRED
error_msg += validate_submitting_party(json_data)
if json_data.get('ownerGroups'):
for group in json_data.get('ownerGroups'):
for owner in group.get('owners'):
error_msg += validate_owner(owner)
error_msg += validate_location(json_data)
error_msg += validate_registration_legacy(json_data)
return error_msg


def validate_doc_id(json_data):
"""Validate the registration document id."""
doc_id = json_data.get('documentId')
current_app.logger.debug(f'Validating doc_id={doc_id}.')
error_msg = ''
if not json_data.get('documentId'):
if not doc_id:
error_msg += DOC_ID_REQUIRED
elif not checksum_valid(json_data.get('documentId')):
elif not checksum_valid(doc_id):
error_msg += DOC_ID_INVALID_CHECKSUM
else:
exists_count = MhrRegistration.get_doc_id_count(json_data.get('documentId'))
exists_count = MhrRegistration.get_doc_id_count(doc_id)
if exists_count > 0:
error_msg += DOC_ID_EXISTS
return error_msg
Expand Down Expand Up @@ -91,3 +100,75 @@ def checksum_valid(doc_id: str) -> bool:
if mod_sum == 0:
return mod_sum == check_digit
return (10 - mod_sum) == check_digit


def validate_registration_legacy(json_data):
"""Perform new registration legacy specifc extra validation here."""
error_msg = ''
if not is_legacy():
return error_msg
location = json_data.get('location')
if location and location.get('address'):
address = location.get('address')
if address.get('street') and len(address.get('street')) > 31:
error_msg = LEGACY_ADDRESS_STREET_TOO_LONG.format(add_desc='Location')
if address.get('city') and len(address.get('city')) > 20:
error_msg += LEGACY_ADDRESS_CITY_TOO_LONG.format(add_desc='Location')

return error_msg


def validate_submitting_party(json_data):
"""Verify submitting party names are valid."""
error_msg = ''
if not json_data.get('submittingParty'):
return SUBMITTING_REQUIRED
party = json_data.get('submittingParty')
desc: str = 'submitting party'
if party.get('businessName'):
error_msg += validate_text(party.get('businessName'), desc + ' business name')
elif party.get('personName'):
error_msg += validate_individual_name(party.get('personName'), desc)
return error_msg


def validate_owner(owner):
"""Verify owner names are valid."""
error_msg = ''
if not owner:
return error_msg
desc: str = 'owner'
if owner.get('organizationName'):
error_msg += validate_text(owner.get('organizationName'), desc + ' organization name')
elif owner.get('individualName'):
error_msg += validate_individual_name(owner.get('individualName'), desc)
return error_msg


def validate_location(json_data):
"""Verify location values are valid."""
error_msg = ''
if not json_data.get('location'):
return error_msg
location = json_data.get('location')
desc: str = 'location'
error_msg += validate_text(location.get('parkName'), desc + ' park name')
error_msg += validate_text(location.get('dealerName'), desc + ' dealer name')
error_msg += validate_text(location.get('additionalDescription'), desc + ' additional description')
error_msg += validate_text(location.get('exceptionPlan'), desc + ' exception plan')
return error_msg


def validate_individual_name(name_json, desc: str = ''):
"""Verify individual name is valid."""
error_msg = validate_text(name_json.get('first'), desc + ' first')
error_msg += validate_text(name_json.get('last'), desc + ' last')
error_msg += validate_text(name_json.get('middle'), desc + ' middle')
return error_msg


def validate_text(value: str, desc: str = ''):
"""Verify text characters are valid."""
if value and not valid_charset(value):
return CHARACTER_SET_UNSUPPORTED.format(desc=desc, value=value)
return ''
108 changes: 74 additions & 34 deletions mhr_api/tests/unit/models/db2/test_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,56 @@
Test-Suite to ensure that the legacy DB2 Location Model is working as expected.
"""
import copy

import pytest

from flask import current_app
from registry_schemas.example_data.mhr import REGISTRATION

from mhr_api.models import Db2Location
from mhr_api.models import Db2Location, MhrRegistration


TEST_LOCATION = Db2Location(location_id=1,
status='A',
reg_document_id='1234',
can_document_id='5678',
street_number='1234',
street_name='street name',
town_city='town',
province='BC',
area='',
jurisdiction='',
roll_number='',
park_name='LAZY WHEEL MOBILE HOME PARK',
park_pad='37',
pid_number='012777846',
lot='54',
parcel='A 1',
block='',
district_lot='1535',
part_of='',
section='N.E. 6',
township='9',
range='',
meridian='',
land_district='PEACE RIVER',
plan='25262',
tax_certificate='Y',
leave_bc='N',
except_plan='except',
dealer_name='dealer',
additional_description='additional')
# testdata pattern is ({exists}, {manuhome_id}, {park_name}, {pad}, {street_num}, {street}, {city}. {count})
TEST_DATA = [
(True, 1, '', '', '4004', 'POPLAR AVENUE', 'FORT NELSON', 2),
(False, 0, None, None, None, None, None, 0)
]
# testdata pattern is ({street_num}, {street_name}, {street_json})
TEST_ADDRESS_DATA = [
('4004', 'POPLAR AVENUE', '4004 POPLAR AVENUE'),
('101-40', '04 POPLAR AVENUE', '101-4004 POPLAR AVENUE')
]


@pytest.mark.parametrize('exists,manuhome_id,park_name,pad,street_num,street,city,count', TEST_DATA)
Expand Down Expand Up @@ -64,8 +101,8 @@ def test_find_by_manuhome_id(session, exists, manuhome_id, park_name, pad, stree


@pytest.mark.parametrize('exists,manuhome_id,park_name,pad,street_num,street,city,count', TEST_DATA)
def test_find_by_manuhome_id_active(session, exists, manuhome_id, park_name, pad, street_num, street, city, count):
"""Assert that find the active location by manuhome id contains all expected elements."""
def test_find_by_manuhome_id(session, exists, manuhome_id, park_name, pad, street_num, street, city, count):
"""Assert that find locations by manuhome id contains all expected elements."""
location: Db2Location = Db2Location.find_by_manuhome_id_active(manuhome_id)
if exists:
assert location.manuhome_id == manuhome_id
Expand Down Expand Up @@ -114,39 +151,42 @@ def test_find_by_manuhome_id_active(session, exists, manuhome_id, park_name, pad
assert not location


@pytest.mark.parametrize('street_num,street_name,street_json', TEST_ADDRESS_DATA)
def test_create_from_registration(session, street_num, street_name, street_json):
"""Assert that creating location address data from json works as expected."""
json_data = copy.deepcopy(REGISTRATION)
json_data['location']['address']['street'] = street_json
registration: MhrRegistration = MhrRegistration(id=1)
location: Db2Location = Db2Location.create_from_registration(registration, json_data)
assert location.street_number == street_num
assert location.street_name == street_name


@pytest.mark.parametrize('street_num,street_name,street_json', TEST_ADDRESS_DATA)
def test_registration_json(session, street_num, street_name, street_json):
"""Assert that creating location json for search from address data works as expected."""
location = TEST_LOCATION
location.street_number = street_num
location.street_name = street_name
json_data = location.registration_json
assert json_data.get('address')
assert json_data['address']['street'] == street_json


@pytest.mark.parametrize('street_num,street_name,street_json', TEST_ADDRESS_DATA)
def test_new_registration_json(session, street_num, street_name, street_json):
"""Assert that creating location json for new registrations from address data works as expected."""
location = TEST_LOCATION
location.street_number = street_num
location.street_name = street_name
json_data = location.new_registration_json
assert json_data.get('address')
assert json_data['address']['street'] == street_json


def test_location_json(session):
"""Assert that the location renders to a json format correctly."""
location = Db2Location(location_id=1,
status='A',
reg_document_id='1234',
can_document_id='5678',
street_number='1234',
street_name='street name',
town_city='town',
province='BC',
area='',
jurisdiction='',
roll_number='',
park_name='LAZY WHEEL MOBILE HOME PARK',
park_pad='37',
pid_number='012777846',
lot='54',
parcel='A 1',
block='',
district_lot='1535',
part_of='',
section='N.E. 6',
township='9',
range='',
meridian='',
land_district='PEACE RIVER',
plan='25262',
tax_certificate='Y',
leave_bc='N',
except_plan='except',
dealer_name='dealer',
additional_description='additional')

location = TEST_LOCATION
test_json = {
'locationId': location.location_id,
'status': location.status,
Expand Down
Loading

0 comments on commit 0e6cecf

Please sign in to comment.