Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion legal-api/report-templates/appointReceiver.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,5 @@
</div>

[[receivers/receivers.html]]
[[certification.html]]
</body>
</html>
1 change: 0 additions & 1 deletion legal-api/report-templates/bcAddressChange.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
<div class="container">
<div class="separator"></div>
[[bc-address-change/addresses.html]]
[[certification.html]]
</div>
</body>
</html>
1 change: 0 additions & 1 deletion legal-api/report-templates/bcAnnualReport.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
<div class="container">
<div class="separator"></div>
[[bc-annual-report/legalObligations.html]]
[[certification.html]]
</div>
</body>
</html>
1 change: 0 additions & 1 deletion legal-api/report-templates/bcDirectorChange.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
<div class="container">
<div class="separator"></div>
[[bc-director-change/directors.html]]
[[certification.html]]
</div>
</body>
</html>
1 change: 0 additions & 1 deletion legal-api/report-templates/ceaseReceiver.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,5 @@
<div class="container"><div class="separator"></div></div>

[[receivers/receivers.html]]
[[certification.html]]
</body>
</html>
4 changes: 3 additions & 1 deletion legal-api/report-templates/dissolution.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
[[common/effectiveDate.html]]
[[dissolution/custodianOfRecords.html]]
[[dissolution/dissolutionStatement.html]]
[[certification.html]]
{% if not business.isCorp %}
[[certification.html]]
{% endif %}
{% endif %}
</div>
</body>
Expand Down
2 changes: 0 additions & 2 deletions legal-api/report-templates/template-parts/certification.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{% if not business.isCorp %}
<div class="no-page-break">
<div class="separator mt-4"></div>
<div class="section-title mt-4">Certification</div>
Expand All @@ -13,4 +12,3 @@
{% endif %}
</div>
</div>
{% endif %}
12 changes: 7 additions & 5 deletions legal-api/src/legal_api/reports/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,12 +477,14 @@ def _set_directors(self, filing):
filing["listOfDirectors"] = filing["changeOfDirectors"]
else:
filing["listOfDirectors"] = {
"directors": filing["annualReport"]["directors"]
"directors": filing["annualReport"].get("directors", [])
}
# create helper lists of appointed and ceased directors
directors = self._format_directors(filing["listOfDirectors"]["directors"])
filing["listOfDirectors"]["directorsAppointed"] = [el for el in directors if "appointed" in el["actions"]]
filing["listOfDirectors"]["directorsCeased"] = [el for el in directors if "ceased" in el["actions"]]

if filing["listOfDirectors"]["directors"]:
# create helper lists of appointed and ceased directors
directors = self._format_directors(filing["listOfDirectors"]["directors"])
filing["listOfDirectors"]["directorsAppointed"] = [el for el in directors if "appointed" in el["actions"]]
filing["listOfDirectors"]["directorsCeased"] = [el for el in directors if "ceased" in el["actions"]]

def _format_directors(self, directors):
for director in directors:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@
# limitations under the License.
"""Validation for the Annual Report filing."""
from http import HTTPStatus
from typing import Optional

from flask_babel import _

from legal_api.errors import Error
from legal_api.models import Address, Business
from legal_api.services.filings.validations.common_validations import _validate_postal_code
from legal_api.models import Business
from legal_api.services.utils import get_date
from legal_api.utils.datetime import datetime

Expand All @@ -45,11 +43,6 @@ def validate(business: Business, annual_report: dict) -> Error:
err = validate_agm_year(business=business,
annual_report=annual_report)

if err:
return err

err = validate_directors_addresses(annual_report, business.legal_type)

if err:
return err

Expand Down Expand Up @@ -139,50 +132,3 @@ def validate_agm_year(*, business: Business, annual_report: dict) -> tuple[int,
# 'path': 'filing/annualReport/annualGeneralMeetingDate'}])
#
return None


def validate_directors_addresses(annual_report: dict, legal_type: str) -> Optional[Error]:
"""Validate directors contain both deliveryAddress and mailingAddress."""
if legal_type not in Business.CORPS:
return None

if not annual_report["filing"]["annualReport"].get("offices", {}).get("recordsOffice", {}):
return Error(HTTPStatus.BAD_REQUEST,
[{"error": "recordsOffice is required",
"path": "/filing/annualReport/offices/recordsOffice"}])

msg = []
directors = annual_report["filing"]["annualReport"].get("directors", [])

# Required fields for mailingAddress
mailing_required_fields = [
"streetAddress",
"addressCity",
"addressCountry"
]

for idx, director in enumerate(directors):
for address_type in Address.JSON_ADDRESS_TYPES:
address = director.get(address_type)

if not address:
msg.append({
"error": f"missing {address_type}",
"path": f"/filing/annualReport/directors/{idx}/{address_type}"
})
elif address_type == Address.JSON_MAILING:
for field in mailing_required_fields:
if not address.get(field):
msg.append({
"error": f"Mailing address must include {field}.",
"path": f"/filing/annualReport/directors/{idx}/{address_type}/{field}"
})

postal_error = _validate_postal_code(address,f"/filing/annualReport/directors/{idx}/{address_type}")
if postal_error:
msg.append(postal_error)

if msg:
return Error(HTTPStatus.BAD_REQUEST, msg)

return None
15 changes: 15 additions & 0 deletions legal-api/src/legal_api/services/pdf_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ def create_registrars_stamp(cls, data: RegistrarStampData):
return buffer


@classmethod
def create_certified_copy(cls, _bytes: bytes, data: RegistrarStampData):
"""Create a certified copy"""
open_pdf_file = io.BytesIO(_bytes)
pdf_reader = PdfReader(open_pdf_file)
pdf_writer = PdfWriter()
pdf_writer.append_pages_from_reader(pdf_reader)
output_original_pdf = io.BytesIO()
pdf_writer.write(output_original_pdf)
output_original_pdf.seek(0)
registrars_stamp = cls.create_registrars_stamp(data)
certified_copy = cls.stamp_pdf(output_original_pdf, registrars_stamp, only_first_page=True)
return certified_copy


def _write_text(can, text, line_height, x_margin, y_margin):
"""Write text lines into a canvas."""
for line in text.splitlines():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"""Test suite to ensure the Annual Report is validated correctly."""
import copy
from datetime import date, datetime
from unittest.mock import patch

import datedelta
import pytest
Expand Down Expand Up @@ -50,139 +49,3 @@ def test_validate(session, test_name, now, ar_date, agm_date,

# validate outcomes
assert not err


@pytest.mark.parametrize(
"test_name, delivery_address, mailing_address, expected_errors",
[
(
"SUCCESS",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
None
),
(
"missing_mailingAddress_streetAddress",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
{"streetAddress": "", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
[
{
"error": "Mailing address must include streetAddress.",
"path": "/filing/annualReport/directors/0/mailingAddress/streetAddress"
}
]
),
(
"missing_mailingAddress_addressCity",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
{"streetAddress": "123 A St", "addressCity": "", "addressCountry": "CA", "postalCode": "V5K0A1"},
[
{
"error": "Mailing address must include addressCity.",
"path": "/filing/annualReport/directors/0/mailingAddress/addressCity"
}
]
),
(
"missing_mailingAddress_addressCountry",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "", "postalCode": "V5K0A1"},
[
{
"error": "Mailing address must include addressCountry.",
"path": "/filing/annualReport/directors/0/mailingAddress/addressCountry"
}
]
),
(
"missing_mailingAddress_postalCode_required",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": ""},
[
{
"error": "Postal code is required.",
"path": "/filing/annualReport/directors/0/mailingAddress/postalCode"
}
]
),
(
"SUCCESS_missing_mailingAddress_postalCode_not_required",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "HK", "postalCode": ""},
None
),
(
"SUCCESS_no_validation_on_postalCode_for_deliveryAddress",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": ""},
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
None
),
(
"missing_mailing_address",
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
None,
[
{
"error": "missing mailingAddress",
"path": "/filing/annualReport/directors/0/mailingAddress"
}
]
),
(
"missing_delivery_address",
None,
{"streetAddress": "123 A St", "addressCity": "Vancouver", "addressCountry": "CA", "postalCode": "V5K0A1"},
[
{
"error": "missing deliveryAddress",
"path": "/filing/annualReport/directors/0/deliveryAddress"
}
]
),
(
"missing_both_addresses",
None,
None,
[
{
"error": "missing mailingAddress",
"path": "/filing/annualReport/directors/0/mailingAddress"
},
{
"error": "missing deliveryAddress",
"path": "/filing/annualReport/directors/0/deliveryAddress"
}
]
),
]
)
def test_validate_director_addresses(session, test_name, delivery_address, mailing_address, expected_errors):
identifier = "BC0000001"
founding_date = datetime(2000, 1, 1)
business = Business(identifier=identifier, founding_date=founding_date, legal_type='BC')

ar = copy.deepcopy(ANNUAL_REPORT)
ar["filing"]["business"]["identifier"] = identifier
director = ar["filing"]["annualReport"]["directors"][0]

if delivery_address is not None:
director["deliveryAddress"] = delivery_address
else:
director.pop("deliveryAddress", None)

if mailing_address is not None:
director["mailingAddress"] = mailing_address
else:
director.pop("mailingAddress", None)

# perform test
with patch("legal_api.services.filings.validations.annual_report.validate_ar_year", return_value=None), \
patch("legal_api.services.filings.validations.annual_report.validate_agm_year", return_value=None):
err = validate(business, ar)

# validate outcomes
if expected_errors:
assert err is not None
assert err.msg == expected_errors
else:
assert err is None