Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b97921b

Browse files
34888 separate resolution date validation for alteration and correction (#4779)
1 parent 7b745c0 commit b97921b

10 files changed

Lines changed: 80 additions & 52 deletions

File tree

legal-api/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "legal-api"
3-
version = "3.1.29"
3+
version = "3.1.30"
44
description = ""
55
authors = [
66
{name = "thor",email = "[email protected]"}

legal-api/src/legal_api/services/filings/validations/common_validations.py

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,12 @@ def _nr_in_pending_filing(nr_number: str, exclude_filing_id: int | None = None)
146146
return False
147147

148148

149-
150-
151149
def validate_resolution_date_in_share_structure(filing_json, filing_type, business) -> list[dict]:
152150
"""Validate the resolution date of a share structure.
153151
154152
Rules:
155153
- If hasRightsOrRestrictions is true in any share class or series, resolution date is required.
156-
- Only one resolution date is permitted (alteration and old correction).
154+
- Only one resolution date is permitted (alteration).
157155
- Resolution date cannot be in the future.
158156
- Resolution date cannot be before the business founding date.
159157
"""
@@ -176,15 +174,50 @@ def validate_resolution_date_in_share_structure(filing_json, filing_type, busine
176174
"path": err_path
177175
})
178176

177+
if not resolution_dates:
178+
return msg
179+
180+
if len(resolution_dates) > 1:
181+
msg.append({
182+
"error": "Only one resolution date is permitted.",
183+
"path": err_path
184+
})
185+
186+
if isinstance(resolution_dates[0], str):
187+
# Kept for backward compatibility (existing alteration)
188+
msg.extend(_validate_resolution_dates_old_format(resolution_dates, business, err_path))
189+
else:
190+
resolution_date = resolution_dates[0]
191+
if resolution_date.get("id"):
192+
msg.append({
193+
"error": "Resolution Id is not allowed when providing the new resolution date.",
194+
"path": f"{err_path}/0"
195+
})
196+
else:
197+
msg.extend(_validate_resolution_date(resolution_date["date"], business, f"{err_path}/0"))
198+
199+
return msg
200+
201+
202+
def validate_resolution_date_in_share_structure_correction(filing_json, filing_type, business) -> list[dict]:
203+
"""Validate the resolution date of a share structure for corrections.
204+
205+
Rules:
206+
- Resolution date cannot be in the future.
207+
- Resolution date cannot be before the business founding date.
208+
"""
209+
resolution_dates = filing_json["filing"][filing_type].get("shareStructure", {}).get("resolutionDates", [])
210+
211+
err_path = f"/filing/{filing_type}/shareStructure/resolutionDates"
212+
msg = []
213+
179214
if not resolution_dates:
180215
return msg
181216

182217
if isinstance(resolution_dates[0], str):
183-
# Kept for backward compatibility (existing alteration and correction filings)
218+
# Kept for backward compatibility (existing correction filing)
184219
msg.extend(_validate_resolution_dates_old_format(resolution_dates, business, err_path))
185220
else:
186-
# Did not include "Only one resolution date is permitted.", not required for correction
187-
# If its required for alteration add while updating alteration filing
188221
existing_ids = {resolution.id for resolution in business.resolutions.all()}
189222
for idx, resolution_date in enumerate(resolution_dates):
190223
if (resolution_id := resolution_date.get("id")) and (resolution_id not in existing_ids):
@@ -197,19 +230,15 @@ def validate_resolution_date_in_share_structure(filing_json, filing_type, busine
197230

198231
return msg
199232

233+
200234
def _validate_resolution_dates_old_format(resolution_dates, business, err_path):
201235
msg = []
202-
if len(resolution_dates) > 1:
203-
msg.append({
204-
"error": "Only one resolution date is permitted.",
205-
"path": err_path
206-
})
207-
208-
elif len(resolution_dates) == 1:
209-
msg.extend(_validate_resolution_date(resolution_dates[0], business, err_path))
236+
for idx, resolution_date in enumerate(resolution_dates):
237+
msg.extend(_validate_resolution_date(resolution_date, business, f"{err_path}/{idx}"))
210238

211239
return msg
212240

241+
213242
def _validate_resolution_date(resolution_date_str: str, business, err_path: str) -> list[dict]:
214243
resolution_date = date.fromisoformat(resolution_date_str)
215244
founding_date = LegislationDatetime.as_legislation_timezone(business.founding_date).date()
@@ -626,7 +655,7 @@ def check_good_standing_permission(business: Business) -> Error | None:
626655
return PermissionService.check_user_permission(required_permission, message=message)
627656

628657

629-
def validate_pdf(file_key: str, file_key_path: str, verify_paper_size: bool = True) -> list | None:
658+
def validate_pdf(file_key: str, file_key_path: str, verify_paper_size: bool = True) -> list:
630659
"""Validate the PDF file."""
631660
msg = []
632661
try:

legal-api/src/legal_api/services/filings/validations/correction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
validate_parties_names,
3838
validate_pdf,
3939
validate_relationships,
40-
validate_resolution_date_in_share_structure,
40+
validate_resolution_date_in_share_structure_correction,
4141
validate_share_currency,
4242
validate_share_structure,
4343
)
@@ -247,7 +247,7 @@ def _validate_corps_correction_active(business: Business, filing_dict, legal_typ
247247
msg.extend(err)
248248

249249
msg.extend(validate_share_currency(filing_dict, filing_type, business))
250-
msg.extend(validate_resolution_date_in_share_structure(filing_dict, filing_type, business))
250+
msg.extend(validate_resolution_date_in_share_structure_correction(filing_dict, filing_type, business))
251251

252252
msg.extend(_validate_continuation_in_correction(filing_dict, filing_type, legal_type, business))
253253
msg.extend(_validate_amalgamation_correction(filing_dict, filing_type, business))

legal-api/tests/unit/services/filings/validations/test_alteration.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,12 +421,12 @@ def test_validate_nr_type(mock_get_parties, session, new_name, legal_type, nr_le
421421
422422
('FAILURE_future_date', True, False, [(NOW + datedelta.DAY).date().isoformat()], HTTPStatus.BAD_REQUEST, [
423423
{'error': 'Resolution date cannot be in the future.',
424-
'path': '/filing/alteration/shareStructure/resolutionDates'}
424+
'path': '/filing/alteration/shareStructure/resolutionDates/0'}
425425
]),
426426
427427
('FAILURE_before_founding', True, False, [(FOUNDING_DATE - datedelta.DAY).date().isoformat()], HTTPStatus.BAD_REQUEST, [
428428
{'error': 'Resolution date cannot be before the business founding date.',
429-
'path': '/filing/alteration/shareStructure/resolutionDates'}
429+
'path': '/filing/alteration/shareStructure/resolutionDates/0'}
430430
]),
431431
]
432432
)

legal-api/tests/unit/services/filings/validations/test_correction_ia.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -340,20 +340,6 @@ def test_correction_share_class_series_validation(session, app, jwt, legal_type,
340340
('SUCCESS_series_has_rights', True, True, ['2024-01-01'], None, None),
341341
('SUCCESS_series_no_rights', False, False, [], None, None),
342342
343-
('FAILURE_class_missing_date', True, False, [], HTTPStatus.BAD_REQUEST, [
344-
{'error': 'Resolution date is required when hasRightsOrRestrictions is true.',
345-
'path': '/filing/correction/shareStructure/resolutionDates'}
346-
]),
347-
('FAILURE_series_missing_date', False, True, [], HTTPStatus.BAD_REQUEST, [
348-
{'error': 'Resolution date is required when hasRightsOrRestrictions is true.',
349-
'path': '/filing/correction/shareStructure/resolutionDates'}
350-
]),
351-
352-
('FAILURE_too_many_dates', True, False, ['2024-01-01', '2024-02-01'], HTTPStatus.BAD_REQUEST, [
353-
{'error': 'Only one resolution date is permitted.',
354-
'path': '/filing/correction/shareStructure/resolutionDates'}
355-
]),
356-
357343
('FAILURE_future_date', True, False, [(NOW + datedelta.DAY).date().isoformat()], HTTPStatus.BAD_REQUEST, [
358344
{'error': 'Resolution date cannot be in the future.',
359345
'path': '/filing/correction/shareStructure/resolutionDates'}
@@ -421,15 +407,6 @@ def test_correction_resolution_date_old(session, app, jwt, test_name, has_rights
421407
('SUCCESS_series_no_rights', False, False, [], None, None),
422408
('SUCCESS_existing_resolution', True, False, [{'date':'2024-01-01'}], None, None),
423409
424-
('FAILURE_class_missing_date', True, False, [], HTTPStatus.BAD_REQUEST, [
425-
{'error': 'Resolution date is required when hasRightsOrRestrictions is true.',
426-
'path': '/filing/correction/shareStructure/resolutionDates'}
427-
]),
428-
('FAILURE_series_missing_date', False, True, [], HTTPStatus.BAD_REQUEST, [
429-
{'error': 'Resolution date is required when hasRightsOrRestrictions is true.',
430-
'path': '/filing/correction/shareStructure/resolutionDates'}
431-
]),
432-
433410
('FAILURE_future_date', True, False, [{'date': (NOW + datedelta.DAY).date().isoformat()}], HTTPStatus.BAD_REQUEST, [
434411
{'error': 'Resolution date cannot be in the future.',
435412
'path': '/filing/correction/shareStructure/resolutionDates'}

queue_services/business-filer/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "business-filer"
3-
version = "3.0.32"
3+
version = "3.0.33"
44
description = "Business Registry Filer Service"
55
authors = [
66
{name = "thor",email = "[email protected]"}

queue_services/business-filer/src/business_filer/filing_processors/alteration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def process(
101101
# update share structure and resolutions, if any
102102
with suppress(IndexError, KeyError, TypeError):
103103
share_structure = dpath.get(filing, "/alteration/shareStructure")
104-
shares.update_share_structure(business, share_structure)
104+
shares.update_share_structure(business, share_structure, True)
105105

106106
# update provisionsRemoved, if any
107107
with suppress(IndexError, KeyError, TypeError):

queue_services/business-filer/src/business_filer/filing_processors/amalgamation_application.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,11 @@ def process(business: Business, # noqa: PLR0912
127127
update_parties(business, parties, filing_rec)
128128

129129
if share_structure := amalgamation_filing.get("shareStructure"):
130-
shares.update_share_structure(business, share_structure)
130+
shares.update_share_structure(
131+
business,
132+
share_structure,
133+
True # for amalgamation, the primary/holding business must carry forward all resolution dates
134+
)
131135

132136
if name_translations := amalgamation_filing.get("nameTranslations"):
133137
aliases.update_aliases(business, name_translations)

queue_services/business-filer/src/business_filer/filing_processors/filing_components/shares.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,27 @@ def update_resolution_dates(business: Business, share_structure: dict) -> None:
4545
# if nothing is passed in, we don't care and it's not an error
4646
return
4747

48+
resolution_dates = share_structure.get("resolutionDates", [])
49+
for resolution_date in resolution_dates:
50+
# Kept for backward compatibility with existing alteration filings
51+
resolution_dt = resolution_date["date"] if isinstance(resolution_date, dict) else resolution_date
52+
resolution = Resolution(
53+
resolution_date=date.fromisoformat(resolution_dt),
54+
resolution_type=Resolution.ResolutionType.SPECIAL.value
55+
)
56+
business.resolutions.append(resolution)
57+
58+
59+
def update_resolution_dates_correction(business: Business, share_structure: dict) -> None:
60+
"""Update the business resolution dates from a share structure."""
61+
if not business or not share_structure:
62+
# if nothing is passed in, we don't care and it's not an error
63+
return
64+
4865
if "resolutionDates" in share_structure:
4966
resolution_dates = share_structure.get("resolutionDates", [])
5067
# This will fail to remove resolutions if the resolutionDates list is empty
51-
# TODO: Update alteration and move to new correction to use new format, then update this code
68+
# TODO: Update existing correction to use new format, then remove isinstance check below
5269
# Ticket: https://app.zenhub.com/workspaces/colin-egress-team-6904d552be2bb0000fa13ad6/issues/gh/bcgov/entity/34841
5370
if len(resolution_dates) > 0 and isinstance(resolution_dates[0], dict):
5471
for current_resolution in business.resolutions.all():
@@ -69,7 +86,7 @@ def update_resolution_dates(business: Business, share_structure: dict) -> None:
6986
)
7087
business.resolutions.append(resolution)
7188
else:
72-
# Kept for backward compatibility (existing alteration and correction filings)
89+
# Kept for backward compatibility (existing correction filings)
7390
for resolution_dt in resolution_dates:
7491
resolution = Resolution(
7592
resolution_date=date.fromisoformat(resolution_dt),
@@ -78,14 +95,15 @@ def update_resolution_dates(business: Business, share_structure: dict) -> None:
7895
business.resolutions.append(resolution)
7996

8097

81-
def update_share_structure(business: Business, share_structure: dict) -> None:
98+
def update_share_structure(business: Business, share_structure: dict, has_resolution_dates: bool = False) -> None:
8299
"""Manage the share structure for a business.
83100
84101
Assumption: The structure has already been validated, upon submission.
85102
86103
Other errors are recorded and will be managed out of band.
87104
"""
88-
update_resolution_dates(business, share_structure)
105+
if has_resolution_dates:
106+
update_resolution_dates(business, share_structure)
89107

90108
if share_classes := share_structure.get("shareClasses"):
91109
delete_existing_shares(business)
@@ -105,7 +123,7 @@ def update_share_structure_correction(business: Business, share_structure: dict)
105123
# if nothing is passed in, we don't care and it's not an error
106124
return
107125

108-
update_resolution_dates(business, share_structure)
126+
update_resolution_dates_correction(business, share_structure)
109127

110128
if share_classes := share_structure.get("shareClasses"):
111129
# Entries in json and not in db

queue_services/business-filer/tests/unit/filing_processors/filing_components/test_shares.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def test_manage_share_structure__resolution_dates(
7575
business.save()
7676
resolution_dates[0]['id'] = resolution.id
7777
try:
78-
shares.update_share_structure(business, new_data['shareStructure'])
78+
shares.update_share_structure(business, new_data['shareStructure'], True)
7979
business.save()
8080
if 'id' in resolution_dates[0]:
8181
del resolution_dates[0]['id']

0 commit comments

Comments
 (0)