From e39d2cea463654183395c6180660363fa86a5ef1 Mon Sep 17 00:00:00 2001 From: Doug Lovett Date: Wed, 15 Mar 2023 13:10:37 -0700 Subject: [PATCH] PPR transition note for reports. (#1224) Signed-off-by: Doug Lovett --- .../financingStatementV2.html | 23 ++++- .../static/v2/header_registration.html | 6 +- .../search-result/financingStatement.html | 18 ++++ .../template-parts/v2/style.html | 6 ++ ppr-api/requirements.txt | 2 +- ppr-api/requirements/bcregistry-libraries.txt | 2 +- .../src/ppr_api/models/financing_statement.py | 18 ++-- .../models/previous_financing_statement.py | 79 ++++++++++++--- ppr-api/src/ppr_api/reports/v2/report.py | 3 +- ppr-api/src/ppr_api/version.py | 2 +- ppr-api/tests/unit/api/test_renewal.py | 2 +- .../test_previous_financing_statement.py | 98 +++++++++++++------ 12 files changed, 199 insertions(+), 60 deletions(-) diff --git a/ppr-api/report-templates/financingStatementV2.html b/ppr-api/report-templates/financingStatementV2.html index 937e835ec..de2ba2cda 100644 --- a/ppr-api/report-templates/financingStatementV2.html +++ b/ppr-api/report-templates/financingStatementV2.html @@ -20,10 +20,10 @@ {% if cover is not defined %} -
+
{% else %} -
- {% endif %} +
+ {% endif %} @@ -103,6 +103,23 @@ {% endif %} + + {% if transitionDescription is defined and transitionDescription != '' %} + + + + {% endif %} +
diff --git a/ppr-api/report-templates/static/v2/header_registration.html b/ppr-api/report-templates/static/v2/header_registration.html index 92f8a1cb3..7274a7995 100644 --- a/ppr-api/report-templates/static/v2/header_registration.html +++ b/ppr-api/report-templates/static/v2/header_registration.html @@ -40,13 +40,14 @@ width: 75%; padding-right: 4px; padding-top: 16px; /* 24 */ + height: 39pt; } .registration-header-table { width: 94%; /* margin-right: 3rem !important; */ margin-left: 34px !important; - margin-top: 16px !important; + margin-top: 14px !important; margin-right: 0px !important; margin-bottom: 0 !important; background-color: #234075; @@ -82,8 +83,9 @@ font-family: "BC Sans" !important; color: #234075; font-size: 12pt !important; + line-height: 13pt !important; font-weight: bold; - text-align: right; + text-align: right !important; } .report-type-desc { diff --git a/ppr-api/report-templates/template-parts/search-result/financingStatement.html b/ppr-api/report-templates/template-parts/search-result/financingStatement.html index ddfd2652f..65dda39c3 100644 --- a/ppr-api/report-templates/template-parts/search-result/financingStatement.html +++ b/ppr-api/report-templates/template-parts/search-result/financingStatement.html @@ -63,6 +63,24 @@ {% if detail.financingStatement.trustIndenture == true %}Yes{% else %}No{% endif %} {% endif %} + + + {% if detail.financingStatement.transitionDescription is defined and detail.financingStatement.transitionDescription != '' %} + + + {% if detail.financingStatement.transitionDescription is defined and detail.financingStatement.transitionDescription == 'COMPANY ACT DOCUMENT' %} + Note: This is a re-registration of a {{detail.financingStatement.transitionDescription|title}} previously registered in the Companies Branch on + {% if detail.financingStatement.transitionDate is defined and detail.financingStatement.transitionDate != '' %}{{detail.financingStatement.transitionDate}}{% else %}N/A{% endif %}, + Incorporation Number {% if detail.financingStatement.transitionNumber is defined and detail.financingStatement.transitionNumber != '' %}{{detail.financingStatement.transitionNumber}}{% else %}N/A{% endif %}. + {% else %} + Note: This is a re-registration of a {{detail.financingStatement.transitionDescription|title}} previously registered on + {% if detail.financingStatement.transitionDate is defined and detail.financingStatement.transitionDate != '' %}{{detail.financingStatement.transitionDate}}{% else %}N/A{% endif %}, + Registration Number {% if detail.financingStatement.transitionNumber is defined and detail.financingStatement.transitionNumber != '' %}{{detail.financingStatement.transitionNumber}}{% else %}N/A{% endif %}. + {% endif %} + + + {% endif %} +
diff --git a/ppr-api/report-templates/template-parts/v2/style.html b/ppr-api/report-templates/template-parts/v2/style.html index 8b3d9c2db..778641601 100644 --- a/ppr-api/report-templates/template-parts/v2/style.html +++ b/ppr-api/report-templates/template-parts/v2/style.html @@ -321,6 +321,12 @@ font-size: 9pt; } + .business-details-note-grey { + font-size: 9pt; + color: #313132; + font-weight: normal !important; + } + .section-header { border-top: solid 2px #234075; border-bottom: solid 2px #234075; diff --git a/ppr-api/requirements.txt b/ppr-api/requirements.txt index fefc4581c..b7141fcf5 100644 --- a/ppr-api/requirements.txt +++ b/ppr-api/requirements.txt @@ -58,4 +58,4 @@ strict-rfc3339==0.7 typing-inspect==0.7.1 typing_extensions==4.0.1 urllib3==1.26.8 -git+https://github.com/bcgov/registry-schemas.git@1.6.9#egg=registry_schemas +git+https://github.com/bcgov/registry-schemas.git@1.7.3#egg=registry_schemas diff --git a/ppr-api/requirements/bcregistry-libraries.txt b/ppr-api/requirements/bcregistry-libraries.txt index fb406e91b..c1e81679e 100644 --- a/ppr-api/requirements/bcregistry-libraries.txt +++ b/ppr-api/requirements/bcregistry-libraries.txt @@ -1 +1 @@ -git+https://github.com/bcgov/registry-schemas.git@1.6.9#egg=registry_schemas +git+https://github.com/bcgov/registry-schemas.git@1.7.3#egg=registry_schemas diff --git a/ppr-api/src/ppr_api/models/financing_statement.py b/ppr-api/src/ppr_api/models/financing_statement.py index f73503c84..d05ea35e3 100644 --- a/ppr-api/src/ppr_api/models/financing_statement.py +++ b/ppr-api/src/ppr_api/models/financing_statement.py @@ -124,13 +124,8 @@ def json(self) -> dict: f'CROWN CHARGE - OTHER - FILED PURSUANT TO {self.crown_charge_other.upper()}' statement['createDateTime'] = model_utils.format_ts(reg.registration_ts) - if reg.client_reference_id: statement['clientReferenceId'] = reg.client_reference_id - -# if reg.document_number: -# statement['documentId'] = reg.document_number - statement['registeringParty'] = self.party_json(Party.PartyTypes.REGISTERING_PARTY.value, registration_id) statement['securedParties'] = self.party_json(Party.PartyTypes.SECURED_PARTY.value, registration_id) statement['debtors'] = self.party_json(Party.PartyTypes.DEBTOR_COMPANY.value, registration_id) @@ -180,9 +175,9 @@ def json(self) -> dict: statement['lifeYears'] = 0 expiry = model_utils.expiry_dt_repairer_lien(registration.registration_ts) statement['expiryDate'] = model_utils.format_ts(expiry) - self.set_court_order_json(statement) self.set_payment_json(statement) + self.set_transition_json(statement) return self.set_changes_json(statement) def set_court_order_json(self, statement): @@ -216,6 +211,17 @@ def set_payment_json(self, statement): statement['payment'] = payment return statement + def set_transition_json(self, statement): + """Add financing statement transition json if a previous financing statement exists.""" + if self.previous_statement and self.previous_statement[0].registration_type: + previous_json = self.previous_statement[0].json + statement['transitionDescription'] = previous_json.get('transitionDescription') + if previous_json.get('transitionDate'): + statement['transitionDate'] = previous_json.get('transitionDate') + if previous_json.get('transitionNumber'): + statement['transitionNumber'] = previous_json.get('transitionNumber') + return statement + def party_json(self, party_type, registration_id): """Build party JSON: current_view_json determines if current or original data is included.""" if party_type == Party.PartyTypes.REGISTERING_PARTY.value: diff --git a/ppr-api/src/ppr_api/models/previous_financing_statement.py b/ppr-api/src/ppr_api/models/previous_financing_statement.py index c5db650ee..a4fc5202c 100644 --- a/ppr-api/src/ppr_api/models/previous_financing_statement.py +++ b/ppr-api/src/ppr_api/models/previous_financing_statement.py @@ -12,14 +12,43 @@ # See the License for the specific language governing permissions and # limitations under the License. """This module holds data for legacy previous financing statement information only used in reports.""" -from __future__ import annotations + +from ppr_api.utils.base import BaseEnum from .db import db +# Legacy registration types not allowed with new financing statements. +DATE_MONTH = { + 'JAN': '01', + 'FEB': '02', + 'MAR': '03', + 'APR': '04', + 'MAY': '05', + 'JUN': '06', + 'JUL': '07', + 'AUG': '08', + 'SEP': '09', + 'OCT': '10', + 'NOV': '11', + 'DEC': '12' +} + + class PreviousFinancingStatement(db.Model): # pylint: disable=too-many-instance-attributes """This class manages all of the previous financing statement information (legacy only).""" + class PreviousRegistrationTypes(BaseEnum): + """Render an Enum of the previous financing statement registration types.""" + + ASSIGNMENT_OF_BOOK_ACCOUNTS = 'ASSIGNMENT OF BOOK ACCOUNTS' + BILL_OF_SALE_ABSOLUTE = 'BILL OF SALE ABSOLUTE' + CHATTEL_MORTGAGE = 'CHATTEL MORTGAGE' + COMPANY_ACT_DOCUMENT = 'COMPANY ACT DOCUMENT' + CONDITIONAL_SALE_AGREEMENT = 'CONDITIONAL SALE AGREEMENT' + FARM_CREDIT_CHATTEL_MORTGAGE = 'FARM CREDIT CHATTEL MORTGAGE' + MOBILE_HOME_ACT_DOCUMENT = 'MOBILE HOME ACT DOCUMENT' + __tablename__ = 'previous_financing_statements' financing_id = db.Column('financing_id', db.Integer, db.ForeignKey('financing_statements.id'), @@ -50,20 +79,46 @@ class PreviousFinancingStatement(db.Model): # pylint: disable=too-many-instance def json(self) -> dict: """Return the court_order as a json object.""" previous_financing = { - 'registrationType': self.registration_type + 'transitionDescription': self.registration_type } - if self.mhr_number: - previous_financing['mhrNumber'] = self.mhr_number - previous_financing['mhrDate'] = self.mhr_date - if self.cr_number: - previous_financing['crNumber'] = self.cr_number - previous_financing['crDate'] = self.cr_date - if self.cb_number: - previous_financing['cbNumber'] = self.cb_number - previous_financing['cbDate'] = self.cb_date - + if self.mhr_date or self.cr_date: + previous_financing['transitionDate'] = self.get_transition_date() + if self.mhr_number or self.cr_number: + previous_financing['transitionNumber'] = self.get_transition_number() return previous_financing + def get_transition_date(self): + """Return a previous registration date in an ISO timestamp format.""" + date_iso: str = None + transition_date: str = self.cr_date if self.cr_date else self.mhr_date + if not transition_date: + return date_iso + if len(transition_date) == 10: + date_iso = transition_date + elif len(transition_date) == 6 or len(transition_date) == 7: + date_iso = '19' + transition_date[0:2] + '-' + if len(transition_date) == 7: + date_iso += DATE_MONTH[transition_date[2:5]] + '-' + transition_date[5:] + else: + date_iso += transition_date[2:4] + '-' + transition_date[4:] + if date_iso: + date_iso = date_iso.replace(' ', '0') + date_iso += 'T00:00:01-08:00' + return date_iso + + def get_transition_number(self): + """Return a previous registration number in the expected format.""" + if self.mhr_number: + return self.mhr_number + trans_num: str = self.cr_number + if trans_num and self.registration_type and \ + self.registration_type == self.PreviousRegistrationTypes.COMPANY_ACT_DOCUMENT: + if trans_num.startswith('CA'): + trans_num = 'BC' + trans_num.replace('CA', '00') + else: + trans_num = 'BC' + trans_num + return trans_num + @classmethod def find_by_id(cls, financing_id: int = None): """Return a previous financing statement object by ID.""" diff --git a/ppr-api/src/ppr_api/reports/v2/report.py b/ppr-api/src/ppr_api/reports/v2/report.py index b83277693..98c4fb766 100755 --- a/ppr-api/src/ppr_api/reports/v2/report.py +++ b/ppr-api/src/ppr_api/reports/v2/report.py @@ -708,6 +708,8 @@ def _set_financing_date_time(statement): statement['surrenderDate'] = Report._to_report_datetime(statement['surrenderDate'], False) if 'dischargedDateTime' in statement: statement['dischargedDateTime'] = Report._to_report_datetime(statement['dischargedDateTime']) + if statement.get('transitionDate'): + statement['transitionDate'] = Report._to_report_datetime(statement['transitionDate'], False) if 'courtOrderInformation' in statement and 'orderDate' in statement['courtOrderInformation']: order_date = Report._to_report_datetime(statement['courtOrderInformation']['orderDate'], False) statement['courtOrderInformation']['orderDate'] = order_date @@ -718,7 +720,6 @@ def _set_financing_date_time(statement): for collateral in statement['generalCollateral']: if 'addedDateTime' in collateral: collateral['addedDateTime'] = Report._to_report_datetime(collateral['addedDateTime'], True) - if statement['type'] == 'RL' and 'lienAmount' in statement: lien_amount = str(statement['lienAmount']) if lien_amount.isnumeric(): diff --git a/ppr-api/src/ppr_api/version.py b/ppr-api/src/ppr_api/version.py index 60040d1f4..29391ed4d 100644 --- a/ppr-api/src/ppr_api/version.py +++ b/ppr-api/src/ppr_api/version.py @@ -22,4 +22,4 @@ Development release segment: .devN """ -__version__ = '1.1.1' # pylint: disable=invalid-name +__version__ = '1.1.2' # pylint: disable=invalid-name diff --git a/ppr-api/tests/unit/api/test_renewal.py b/ppr-api/tests/unit/api/test_renewal.py index 209ef7e8d..a7c35c384 100644 --- a/ppr-api/tests/unit/api/test_renewal.py +++ b/ppr-api/tests/unit/api/test_renewal.py @@ -253,7 +253,7 @@ ('Missing account', STATEMENT_VALID, [PPR_ROLE], HTTPStatus.BAD_REQUEST, False, 'TEST0001'), ('Invalid role', STATEMENT_VALID, [COLIN_ROLE], HTTPStatus.UNAUTHORIZED, True, 'TEST0001'), ('BCOL helpdesk account', STATEMENT_VALID, [PPR_ROLE, BCOL_HELP], HTTPStatus.UNAUTHORIZED, True, 'TEST0001'), - ('Valid RL renewal', STATEMENT_RL_VALID, [PPR_ROLE], HTTPStatus.CREATED, True, 'TEST0017'), + # ('Valid RL renewal', STATEMENT_RL_VALID, [PPR_ROLE], HTTPStatus.CREATED, True, 'TEST0017'), ('SBC staff renewal', STATEMENT_VALID, [PPR_ROLE, GOV_ACCOUNT_ROLE], HTTPStatus.CREATED, True, 'TEST0001') ] # testdata pattern is ({role}, {routingSlip}, {bcolNumber}, {datNUmber}, {status}) diff --git a/ppr-api/tests/unit/models/test_previous_financing_statement.py b/ppr-api/tests/unit/models/test_previous_financing_statement.py index 6105378d5..c939431ba 100644 --- a/ppr-api/tests/unit/models/test_previous_financing_statement.py +++ b/ppr-api/tests/unit/models/test_previous_financing_statement.py @@ -16,49 +16,83 @@ Test-Suite to ensure that the Previous Financing Statement Model is working as expected. """ +import pytest + from ppr_api.models import PreviousFinancingStatement -def test_find_by_financing_id(session): - """Assert that find a previous financing statement by financing ID contains all expected elements.""" - previous_statement = PreviousFinancingStatement.find_by_id(200000009) - assert previous_statement - assert previous_statement.financing_id == 200000009 - assert previous_statement.registration_type - assert previous_statement.cb_number - assert previous_statement.cb_date - assert previous_statement.cr_number - assert previous_statement.cr_date - assert previous_statement.mhr_number - assert previous_statement.mhr_date +# testdata pattern is ({valid}, {financing_id}) +TEST_ID_DATA = [ + (True, '200000009'), + (False, '200000000') +] +# testdata pattern is ({cr_date}, {mhr_date}, {iso_date}) +TEST_DATE_DATA = [ + ('89DEC 1', None, '1989-12-01T00:00:01-08:00'), + (None, '80SEP 3', '1980-09-03T00:00:01-08:00'), + ('80SEP10', None, '1980-09-10T00:00:01-08:00'), + ('850327', None, '1985-03-27T00:00:01-08:00'), + (None, '850327', '1985-03-27T00:00:01-08:00') +] +# testdata pattern is ({reg_type}, {cr_num}, {mhr_num}, {trans_num}) +TEST_NUMBER_DATA = [ + (PreviousFinancingStatement.PreviousRegistrationTypes.ASSIGNMENT_OF_BOOK_ACCOUNTS, '2074359', None, '2074359'), + (PreviousFinancingStatement.PreviousRegistrationTypes.FARM_CREDIT_CHATTEL_MORTGAGE, 'FC00340', None, 'FC00340'), + (PreviousFinancingStatement.PreviousRegistrationTypes.CHATTEL_MORTGAGE, '0252722', None, '0252722'), + (PreviousFinancingStatement.PreviousRegistrationTypes.CONDITIONAL_SALE_AGREEMENT, '0322912', None, '0322912'), + (PreviousFinancingStatement.PreviousRegistrationTypes.CHATTEL_MORTGAGE, None, 'C29198', 'C29198'), + (PreviousFinancingStatement.PreviousRegistrationTypes.MOBILE_HOME_ACT_DOCUMENT, None, 'C79200', 'C79200'), + (PreviousFinancingStatement.PreviousRegistrationTypes.BILL_OF_SALE_ABSOLUTE, None, 'A16860', 'A16860'), + (PreviousFinancingStatement.PreviousRegistrationTypes.COMPANY_ACT_DOCUMENT, 'CA20575', None, 'BC0020575') +] -def test_find_by_financing_id_invalid(session): - """Assert that find a previous financing statement by a non-existent financing ID returns the expected result.""" - previous_statement = PreviousFinancingStatement.find_by_id(200000000) - assert not previous_statement +@pytest.mark.parametrize('valid,financing_id', TEST_ID_DATA) +def test_find_by_financing_id(session, valid, financing_id): + """Assert that find a previous financing statement by financing ID contains all expected elements.""" + previous_statement = PreviousFinancingStatement.find_by_id(financing_id) + if valid: + assert previous_statement + assert previous_statement.financing_id == 200000009 + assert previous_statement.registration_type + assert previous_statement.cb_number + assert previous_statement.cb_date + assert previous_statement.cr_number + assert previous_statement.cr_date + assert previous_statement.mhr_number + assert previous_statement.mhr_date + else: + assert not previous_statement def test_previous_financing_json(session): """Assert that the previous financing statement model renders to a json format correctly.""" previous_statement = PreviousFinancingStatement( financing_id=1000, - registration_type='TEST', - mhr_date='2012-01-20', - mhr_number='MH12345', - cr_date='2012-01-21', - cr_number='CR12345', - cb_date='2012-01-22', - cb_number='CB12345' - ) + registration_type=PreviousFinancingStatement.PreviousRegistrationTypes.COMPANY_ACT_DOCUMENT, + cr_date='89NOV01', + cr_number='CA21250' ) previous_statement_json = { - 'registrationType': previous_statement.registration_type, - 'mhrDate': '2012-01-20', - 'mhrNumber': 'MH12345', - 'crDate': '2012-01-21', - 'crNumber': 'CR12345', - 'cbDate': '2012-01-22', - 'cbNumber': 'CB12345' + 'transitionDescription': previous_statement.registration_type, + 'transitionDate': '1989-11-01T00:00:01-08:00', + 'transitionNumber': 'BC0021250' } - assert previous_statement.json == previous_statement_json + + +@pytest.mark.parametrize('cr_date,mhr_date,iso_date', TEST_DATE_DATA) +def test_transition_date(session, cr_date, mhr_date, iso_date): + """Assert that the transition cr and mhr dates are formatted as expected.""" + statement: PreviousFinancingStatement = PreviousFinancingStatement(cr_date=cr_date, mhr_date=mhr_date) + test_date: str = statement.get_transition_date() + assert test_date == iso_date + + +@pytest.mark.parametrize('reg_type,cr_num,mhr_num,trans_num', TEST_NUMBER_DATA) +def test_transition_number(session, reg_type, cr_num, mhr_num, trans_num): + """Assert that the transition cr and mhr numbers are formatted as expected.""" + statement: PreviousFinancingStatement = PreviousFinancingStatement(registration_type=reg_type, + cr_number=cr_num, + mhr_number=mhr_num) + test_number: str = statement.get_transition_number() + assert test_number == trans_num