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

Skip to content

Commit 1f5a765

Browse files
authored
34496 - Update min year validation for AGM Location Change (#4691)
1 parent 357b20a commit 1f5a765

2 files changed

Lines changed: 71 additions & 15 deletions

File tree

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,16 @@ def validate(business: Business, filing: dict) -> Error | None:
4141
agm_year_path: Final = "/filing/agmLocationChange/year"
4242
year = get_int(filing, agm_year_path)
4343
if year:
44-
expected_min = LegislationDatetime.now().year - 2
45-
expected_max = LegislationDatetime.now().year + 1
44+
current_year = LegislationDatetime.now().year
45+
# AGM year can never be before the year the business was founded, even if that is
46+
# more recent than the default 2-year lookback window.
47+
founding_year = LegislationDatetime.as_legislation_timezone(business.founding_date).year \
48+
if business.founding_date else current_year - 2
49+
expected_min = max(current_year - 2, founding_year)
50+
expected_max = current_year + 1
4651
if expected_min > year or year > expected_max:
47-
msg.append({"error": "AGM year must be between -2 or +1 year from current year.", "path": agm_year_path})
52+
msg.append({"error": f"AGM year must be between {expected_min} and {expected_max}.",
53+
"path": agm_year_path})
4854

4955
# A non-empty reason (at least one non-whitespace character) is enforced by the schema
5056
# (business-schemas agm_location_change reason pattern).

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

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,41 +28,48 @@
2828
# rejected by schema validation (HTTP 422) instead of the legal-api business check (HTTP 400).
2929
SCHEMA_REJECTED = 'SCHEMA_REJECTED'
3030

31+
# Set far enough in the past that founding date never becomes the binding floor
32+
OLD_FOUNDING_DATE = datetime.utcnow().replace(year=datetime.utcnow().year - 10)
33+
3134

3235
@pytest.mark.parametrize(
3336
'test_name, expected_code, message',
3437
[
3538
('INVALID_YEAR', HTTPStatus.UNPROCESSABLE_ENTITY, SCHEMA_REJECTED),
36-
('FAIL_YEAR-3', HTTPStatus.BAD_REQUEST, 'AGM year must be between -2 or +1 year from current year.'),
37-
('FAIL_YEAR+2', HTTPStatus.BAD_REQUEST, 'AGM year must be between -2 or +1 year from current year.'),
39+
('FAIL_YEAR-3', HTTPStatus.BAD_REQUEST, None),
40+
('FAIL_YEAR+2', HTTPStatus.BAD_REQUEST, None),
3841
('SUCCESS-2', None, None),
3942
('SUCCESS+1', None, None),
4043
('SUCCESS', None, None)
4144
]
4245
)
4346
def test_validate_agm_year(session, mocker, test_name, expected_code, message, monkeypatch):
44-
"""Assert validate agm year."""
47+
"""Assert validate agm year for an established business (founding date well outside the lookback window)."""
4548
monkeypatch.setattr(
4649
'legal_api.services.flags.value',
4750
lambda flag, default=None: "BC BEN CC ULC C CBEN CCC CUL" if flag == 'supported-agm-location-change-entities' else default
4851
)
49-
business = factory_business(identifier='BC1234567', entity_type='BC', founding_date=datetime.utcnow())
52+
business = factory_business(identifier='BC1234567', entity_type='BC', founding_date=OLD_FOUNDING_DATE)
5053
filing = copy.deepcopy(FILING_HEADER)
5154
filing['filing']['agmLocationChange'] = copy.deepcopy(AGM_LOCATION_CHANGE)
5255
filing['filing']['header']['name'] = 'agmLocationChange'
5356

57+
current_year = LegislationDatetime.now().year
58+
expected_min = current_year - 2
59+
expected_max = current_year + 1
60+
5461
if test_name == 'INVALID_YEAR':
5562
filing['filing']['agmLocationChange']['year'] = 'invalid'
5663
elif test_name == 'FAIL_YEAR-3':
57-
filing['filing']['agmLocationChange']['year'] = str(LegislationDatetime.now().year - 3)
64+
filing['filing']['agmLocationChange']['year'] = str(current_year - 3)
5865
elif test_name == 'FAIL_YEAR+2':
59-
filing['filing']['agmLocationChange']['year'] = str(LegislationDatetime.now().year + 2)
66+
filing['filing']['agmLocationChange']['year'] = str(current_year + 2)
6067
elif test_name == 'SUCCESS-2':
61-
filing['filing']['agmLocationChange']['year'] = str(LegislationDatetime.now().year - 2)
68+
filing['filing']['agmLocationChange']['year'] = str(current_year - 2)
6269
elif test_name == 'SUCCESS+1':
63-
filing['filing']['agmLocationChange']['year'] = str(LegislationDatetime.now().year + 1)
70+
filing['filing']['agmLocationChange']['year'] = str(current_year + 1)
6471
elif test_name == 'SUCCESS':
65-
filing['filing']['agmLocationChange']['year'] = str(LegislationDatetime.now().year)
72+
filing['filing']['agmLocationChange']['year'] = str(current_year)
6673
err = validate(business, filing)
6774

6875
# validate outcomes
@@ -71,11 +78,54 @@ def test_validate_agm_year(session, mocker, test_name, expected_code, message, m
7178
assert err.code == HTTPStatus.UNPROCESSABLE_ENTITY
7279
elif not test_name.startswith('SUCCESS'):
7380
assert expected_code == err.code
74-
if message:
75-
assert message == err.msg[0]['error']
81+
assert f'AGM year must be between {expected_min} and {expected_max}.' == err.msg[0]['error']
82+
else:
83+
assert not err
84+
85+
86+
@pytest.mark.parametrize(
87+
'test_name, founding_years_ago, year_offset_from_now',
88+
[
89+
# business founded less than 2 years ago: founding year should raise the floor
90+
# above the default lookback year
91+
('FAIL_BEFORE_FOUNDING_YEAR', 1, -2),
92+
('SUCCESS_AT_FOUNDING_YEAR', 1, -1),
93+
# business founded this year: floor should equal the current year
94+
('FAIL_BEFORE_FOUNDING_THIS_YEAR', 0, -1),
95+
('SUCCESS_FOUNDING_THIS_YEAR', 0, 0),
96+
]
97+
)
98+
def test_validate_agm_year_founding_date_floor(
99+
session, mocker, test_name, founding_years_ago, year_offset_from_now, monkeypatch
100+
):
101+
"""Assert AGM year cannot be set to a year before the business's founding year."""
102+
monkeypatch.setattr(
103+
'legal_api.services.flags.value',
104+
lambda flag, default=None: "BC BEN CC ULC C CBEN CCC CUL" if flag == 'supported-agm-location-change-entities' else default
105+
)
106+
current_year = LegislationDatetime.now().year
107+
founding_date = datetime.utcnow().replace(year=current_year - founding_years_ago)
108+
business = factory_business(identifier='BC1234567', entity_type='BC', founding_date=founding_date)
109+
110+
filing = copy.deepcopy(FILING_HEADER)
111+
filing['filing']['agmLocationChange'] = copy.deepcopy(AGM_LOCATION_CHANGE)
112+
filing['filing']['header']['name'] = 'agmLocationChange'
113+
filing['filing']['agmLocationChange']['year'] = str(current_year + year_offset_from_now)
114+
115+
err = validate(business, filing)
116+
117+
founding_year = current_year - founding_years_ago
118+
expected_min = max(current_year - 2, founding_year)
119+
expected_max = current_year + 1
120+
121+
if test_name.startswith('FAIL'):
122+
assert err is not None
123+
assert err.code == HTTPStatus.BAD_REQUEST
124+
assert f'AGM year must be between {expected_min} and {expected_max}.' == err.msg[0]['error']
76125
else:
77126
assert not err
78127

128+
79129
@pytest.mark.parametrize(
80130
'test_name, reason, expected_code, message',
81131
[
@@ -91,7 +141,7 @@ def test_validate_agm_reason(session, mocker, test_name, reason, expected_code,
91141
'legal_api.services.flags.value',
92142
lambda flag, default=None: "BC BEN CC ULC C CBEN CCC CUL" if flag == 'supported-agm-location-change-entities' else default
93143
)
94-
business = factory_business(identifier='BC1234567', entity_type='BC', founding_date=datetime.utcnow())
144+
business = factory_business(identifier='BC1234567', entity_type='BC', founding_date=OLD_FOUNDING_DATE)
95145
filing = copy.deepcopy(FILING_HEADER)
96146
filing['filing']['agmLocationChange'] = copy.deepcopy(AGM_LOCATION_CHANGE)
97147
filing['filing']['header']['name'] = 'agmLocationChange'

0 commit comments

Comments
 (0)