Skip to content

Commit

Permalink
24987 24989 - Update to enable NoW for temporary businesses (#3155)
Browse files Browse the repository at this point in the history
* add now for temporary businesses in basic checks
* update error code for not found withdrawn filing from 400 to 404
* update code in save_filing and complete_filing to enable NoW for T businesses
* add unit tests NoW filing for regular businesses and T businesses
* fix 2 old unit tests to deal with the last day of a year issue
  • Loading branch information
eason-pan-bc authored Dec 31, 2024
1 parent ddb0337 commit 110797b
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ def put_basic_checks(identifier, filing, client_request, business) -> Tuple[dict
if not filing_type:
return ({'message': 'filing/header/name is a required property'}, HTTPStatus.BAD_REQUEST)

if filing_type not in CoreFiling.NEW_BUSINESS_FILING_TYPES and business is None:
if filing_type not in CoreFiling.NEW_BUSINESS_FILING_TYPES + [CoreFiling.FilingTypes.NOTICEOFWITHDRAWAL] \
and business is None:
return ({'message': 'A valid business is required.'}, HTTPStatus.BAD_REQUEST)

if client_request.method == 'PUT' and not filing:
Expand All @@ -497,9 +498,14 @@ def check_authorization(identifier, filing_json: dict,

# While filing IA business object will be None. Setting default values in that case.
state = business.state if business else Business.State.ACTIVE
if business:
legal_type = business.legal_type
# for temporary business notice of withdraw, get legalType from filing json
elif filing_type == CoreFiling.FilingTypes.NOTICEOFWITHDRAWAL.value:
legal_type = filing_json['filing'].get('business', None).get('legalType')
# for incorporationApplication and registration, get legalType from nameRequest
legal_type = business.legal_type if business else \
filing_json['filing'][filing_type]['nameRequest'].get('legalType')
else:
legal_type = filing_json['filing'][filing_type]['nameRequest'].get('legalType')

if not authorized(identifier, jwt, action=['edit']) or \
not is_allowed(business, state, filing_type, legal_type, jwt, filing_sub_type, filing):
Expand Down Expand Up @@ -680,6 +686,9 @@ def get_filing_types(business: Business, filing_json: dict): # pylint: disable=

if filing_type in CoreFiling.NEW_BUSINESS_FILING_TYPES:
legal_type = filing_json['filing'][filing_type]['nameRequest']['legalType']
elif business.identifier.startswith('T') and \
filing_type == CoreFiling.FilingTypes.NOTICEOFWITHDRAWAL:
legal_type = filing_json['filing'].get('business', None).get('legalType')
else:
legal_type = business.legal_type

Expand Down Expand Up @@ -839,6 +848,12 @@ def create_invoice(business: Business, # pylint: disable=too-many-locals,too-ma
mailing_address = business.mailing_address.one_or_none()
corp_type = business.legal_type if business.legal_type else \
filing.json['filing']['business'].get('legalType')
# deal with withdrawing a new business filing
elif business.identifier.startswith('T') and \
filing.filing_type == Filing.FILINGS['noticeOfWithdrawal']['name']:
mailing_address, corp_type, legal_name = \
ListFilingResource._get_address_from_withdrawn_new_business_filing(business, filing)
business.legal_name = legal_name
else:
mailing_address = business.mailing_address.one_or_none()
corp_type = business.legal_type if business.legal_type else \
Expand Down Expand Up @@ -1057,3 +1072,27 @@ def submit_filing_for_review(filing: Filing):
{'email': {'filingId': filing.id, 'type': filing.filing_type, 'option': review.status}},
current_app.config.get('NATS_EMAILER_SUBJECT')
)

@staticmethod
def _get_address_from_withdrawn_new_business_filing(business: Business, filing: Filing):
if filing.filing_type != CoreFiling.FilingTypes.NOTICEOFWITHDRAWAL.value:
return None, None, None
withdrawn_filing_id = filing.filing_json['filing']['noticeOfWithdrawal']['filingId']
withdrawn_filing = Filing.find_by_id(withdrawn_filing_id)
if withdrawn_filing.filing_type in CoreFiling.NEW_BUSINESS_FILING_TYPES:
office_type = OfficeType.REGISTERED
if withdrawn_filing.filing_type == Filing.FILINGS['registration']['name']:
office_type = OfficeType.BUSINESS

mailing_address = Address.create_address(
withdrawn_filing.json['filing'][withdrawn_filing.filing_type]['offices'][office_type]['mailingAddress'])
corp_type = withdrawn_filing.json['filing'][withdrawn_filing.filing_type]['nameRequest'].get(
'legalType', Business.LegalTypes.BCOMP.value)

try:
legal_name = withdrawn_filing.json['filing'][withdrawn_filing.filing_type]['nameRequest']['legalName']
except KeyError:
legal_name = business.identifier

return mailing_address, corp_type, legal_name
return None, None, None
3 changes: 2 additions & 1 deletion legal-api/src/legal_api/services/authz.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ def get_allowable_filings_dict():
'legalTypes': ['BC', 'BEN', 'CC', 'ULC', 'C', 'CBEN', 'CUL', 'CCC'],
'blockerChecks': {
'business': [BusinessBlocker.FILING_WITHDRAWAL]
}
},
'businessRequirement': BusinessRequirement.NO_RESTRICTION
}
},
Business.State.HISTORICAL: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ def validate(filing: Dict) -> Optional[Error]:
msg.append({'error': babel('Filing Id is required.'), 'path': withdrawn_filing_id_path})
return msg # cannot continue validation without the to be withdrawn filing id

err = validate_withdrawn_filing(withdrawn_filing_id)
if err:
msg.extend(err)
is_not_found, err_msg = validate_withdrawn_filing(withdrawn_filing_id)
if is_not_found:
return Error(HTTPStatus.NOT_FOUND, err_msg)
if err_msg and not is_not_found:
msg.extend(err_msg)

if msg:
return Error(HTTPStatus.BAD_REQUEST, msg)
Expand All @@ -49,12 +51,14 @@ def validate(filing: Dict) -> Optional[Error]:
def validate_withdrawn_filing(withdrawn_filing_id: int):
"""Validate the to be withdrawn filing id exists, the filing has a FED, the filing status is PAID."""
msg = []
is_not_found = False
# check whether the filing ID exists
withdrawn_filing = db.session.query(Filing). \
filter(Filing.id == withdrawn_filing_id).one_or_none()
if not withdrawn_filing:
msg.append({'error': babel('The filing to be withdrawn cannot be found.')})
return msg # cannot continue if the withdrawn filing doesn't exist
is_not_found = True
return is_not_found, msg # cannot continue if the withdrawn filing doesn't exist

# check whether the filing has a Future Effective Date(FED)
now = dt.utcnow()
Expand All @@ -68,5 +72,5 @@ def validate_withdrawn_filing(withdrawn_filing_id: int):
msg.append({'error': babel('Only paid filings with a future effective date can be withdrawn.')})

if msg:
return msg
return None
return is_not_found, msg
return None, None
4 changes: 2 additions & 2 deletions legal-api/tests/unit/resources/v1/test_business_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ def test_get_tasks_no_filings(session, client, jwt):
def test_get_tasks_next_year(session, client, jwt):
"""Assert that one todo item is returned in the calendar year following incorporation."""
identifier = 'CP7654321'
founding_date = datetime.today() + datedelta.datedelta(days=1) - datedelta.datedelta(years=1)
factory_business(identifier, founding_date=founding_date) # incorporation 1 year - 1 day ago
founding_date = datetime.today() - datedelta.datedelta(years=1)
factory_business(identifier, founding_date=founding_date) # incorporation 1 year

# To-do are all years from the year after incorporation until this year

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
Test-Suite to ensure that the /businesses endpoint is working as expected.
"""
import copy
from datetime import datetime, timezone
from datetime import datetime, timedelta, timezone
from http import HTTPStatus
from typing import Final
from unittest.mock import patch
Expand All @@ -44,6 +44,7 @@
FILING_HEADER,
INCORPORATION,
INCORPORATION_FILING_TEMPLATE,
NOTICE_OF_WITHDRAWAL as SCHEMA_NOTICE_OF_WITHDRAWAL,
REGISTRATION,
SPECIAL_RESOLUTION,
TRANSITION_FILING_TEMPLATE
Expand Down Expand Up @@ -1595,3 +1596,87 @@ def test_resubmit_filing_failed(session, client, jwt, filing_status, review_stat
headers=create_header(jwt, [STAFF_ROLE], identifier))

assert rv.status_code == HTTPStatus.UNAUTHORIZED

@pytest.mark.parametrize(
'test_name, legal_type, filing_type, filing_json, is_temp',
[
('T-BUSINESS-IA', 'BC', 'incorporationApplication', INCORPORATION, True),
('T-BUSINESS-CONT-IN', 'BEN', 'continuationIn', CONTINUATION_IN, True),
('T-BUSINESS-AMALGAMATION', 'CBEN', 'amalgamationApplication', AMALGAMATION_APPLICATION, True),
('REGULAR-BUSINESS-COA', 'BC', 'changeOfAddress', CHANGE_OF_ADDRESS, False),
('REGULAR-BUSINESS-CONT-ALTERATION', 'BEN', 'alteration', ALTERATION_FILING_TEMPLATE, False),
('REGULAR-BUSINESS-DISSOLUTION', 'CBEN', 'dissolution', DISSOLUTION, False)
]
)
def test_notice_of_withdraw_filing(session, client, jwt, test_name, legal_type, filing_type, filing_json, is_temp):
"""Assert that notice of withdraw for new business filings can be filed"""
today = datetime.utcnow().date()
future_effective_date = today + timedelta(days=5)
future_effective_date = future_effective_date.isoformat()
# create a FE new business filing
if is_temp:
identifier = 'Tb31yQIuBw'
temp_reg = RegistrationBootstrap()
temp_reg._identifier = identifier
temp_reg.save()
json_data = copy.deepcopy(FILING_HEADER)
json_data['filing']['header']['name'] = filing_type
del json_data['filing']['business']
new_bus_filing_json = copy.deepcopy(filing_json)
new_bus_filing_json['nameRequest']['legalType'] = legal_type
json_data['filing'][filing_type] = new_bus_filing_json
new_business_filing = factory_pending_filing(None, json_data)
new_business_filing.temp_reg = identifier
new_business_filing.effective_date = future_effective_date
new_business_filing.payment_completion_date = datetime.utcnow().isoformat()
new_business_filing.save()
withdrawn_filing_id = new_business_filing.id
# create a regular business and file a FE filing
else:
identifier = 'BC1234567'
founding_date = datetime.utcnow() - timedelta(days=5)
business = factory_business(identifier=identifier, founding_date=founding_date, entity_type=legal_type)
filing_data_reg_business = copy.deepcopy(FILING_HEADER)
filing_data_reg_business['filing']['header']['name'] = filing_type
filing_data_reg_business['filing']['business']['identifier'] = identifier
filing_data_reg_business['filing']['business']['legalType'] = legal_type
fe_filing_json = copy.deepcopy(filing_json)
filing_data_reg_business['filing'][filing_type] = fe_filing_json
fe_filing = factory_pending_filing(business, filing_data_reg_business)
fe_filing.effective_date = future_effective_date
fe_filing.payment_completion_date = datetime.utcnow().isoformat()
fe_filing.save()
withdrawn_filing_id = fe_filing.id

# test filing a notice of withdraw for a temporary business
now_json_data = copy.deepcopy(FILING_HEADER)
now_json_data['filing']['header']['name'] = 'noticeOfWithdrawal'
if is_temp:
del now_json_data['filing']['business']
now_json_data['filing']['business'] = {
"identifier": identifier,
"legalType": legal_type
}
else:
now_json_data['filing']['business']['identifier'] = identifier
now_json_data['filing']['business']['legalType'] = legal_type
now_json_data['filing']['noticeOfWithdrawal'] = copy.deepcopy(SCHEMA_NOTICE_OF_WITHDRAWAL)
now_json_data['filing']['noticeOfWithdrawal']['filingId'] = withdrawn_filing_id
del now_json_data['filing']['header']['filingId']

# Test validation OK
rv_validation = client.post(f'/api/v2/businesses/{identifier}/filings?only_validate=true',
json=now_json_data,
headers=create_header(jwt, [STAFF_ROLE], identifier))

assert rv_validation.status_code == HTTPStatus.OK
assert rv_validation.json['filing']['header']['name'] == 'noticeOfWithdrawal'

# Test can create a draft
rv_draft = client.post(f'/api/v2/businesses/{identifier}/filings?draft=true',
json=now_json_data,
headers=create_header(jwt, [STAFF_ROLE], identifier))

# validate
assert rv_draft.status_code == HTTPStatus.CREATED
assert rv_draft.json['filing']['header']['name'] == 'noticeOfWithdrawal'
4 changes: 2 additions & 2 deletions legal-api/tests/unit/resources/v2/test_business_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ def test_get_tasks_no_filings(session, client, jwt):
def test_get_tasks_next_year(session, client, jwt):
"""Assert that one todo item is returned in the calendar year following incorporation."""
identifier = 'CP7654321'
founding_date = datetime.today() + datedelta.datedelta(days=1) - datedelta.datedelta(years=1)
factory_business(identifier, founding_date=founding_date) # incorporation 1 year - 1 day ago
founding_date = datetime.today() - datedelta.datedelta(years=1)
factory_business(identifier, founding_date=founding_date) # incorporation 1 year

# To-do are all years from the year after incorporation until this year

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
('EXIST_BUSINESS_SUCCESS', True, Filing.Status.PAID, True, True, None, None),
('EXIST_BUSINESS_FAIL_NOT_PAID', True, Filing.Status.PENDING, True, True, HTTPStatus.BAD_REQUEST, [FILING_NOT_PAID_MSG]),
('EXIST_BUSINESS_FAIL_NOT_FED', True, Filing.Status.PAID, False, True, HTTPStatus.BAD_REQUEST, [FILING_NOT_FED_MSG]),
('EXIST_BUSINESS_FAIL_FILING_NOT_EXIST', False, Filing.Status.PAID, True, True, HTTPStatus.BAD_REQUEST, [FILING_NOT_EXIST_MSG]),
('EXIST_BUSINESS_FAIL_FILING_NOT_EXIST', False, Filing.Status.PAID, True, True, HTTPStatus.NOT_FOUND, [FILING_NOT_EXIST_MSG]),
('EXIST_BUSINESS_FAIL_MISS_FILING_ID', True, Filing.Status.PAID, True, False, HTTPStatus.UNPROCESSABLE_ENTITY, ''),
('EXIST_BUSINESS_FAIL_NOT_PAID_NOT_FED', True, Filing.Status.PENDING, False, True, HTTPStatus.BAD_REQUEST, [FILING_NOT_FED_MSG, FILING_NOT_PAID_MSG])
]
Expand Down
24 changes: 16 additions & 8 deletions legal-api/tests/unit/services/test_authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,42 +1116,50 @@ def mock_auth(one, two): # pylint: disable=unused-argument; mocks of library me
expected_lookup([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.IA_BC])),
FilingKey.IA_BC,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_c', False, Business.State.ACTIVE, ['C'], 'staff', [STAFF_ROLE],
expected_lookup_continue_in_corps([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.CONTINUATION_IN_C])),
FilingKey.CONTINUATION_IN_C,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_ben', False, Business.State.ACTIVE, ['BEN'], 'staff', [STAFF_ROLE],
expected_lookup([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.IA_BEN])),
FilingKey.IA_BEN,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_cben', False, Business.State.ACTIVE, ['CBEN'], 'staff', [STAFF_ROLE],
expected_lookup_continue_in_corps([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.CONTINUATION_IN_CBEN])),
FilingKey.CONTINUATION_IN_CBEN,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_cc', False, Business.State.ACTIVE, ['CC'], 'staff', [STAFF_ROLE],
expected_lookup([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.IA_CC])),
FilingKey.IA_CC,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_ccc', False, Business.State.ACTIVE, ['CCC'], 'staff', [STAFF_ROLE],
expected_lookup_continue_in_corps([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.CONTINUATION_IN_CCC])),
FilingKey.CONTINUATION_IN_CCC,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_ulc', False, Business.State.ACTIVE, ['ULC'], 'staff', [STAFF_ROLE],
expected_lookup([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.IA_ULC])),
FilingKey.IA_ULC,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_cul', False, Business.State.ACTIVE, ['CUL'], 'staff', [STAFF_ROLE],
expected_lookup_continue_in_corps([FilingKey.AMALGAMATION_REGULAR,
FilingKey.AMALGAMATION_VERTICAL,
FilingKey.AMALGAMATION_HORIZONTAL,
FilingKey.CONTINUATION_IN_CUL])),
FilingKey.CONTINUATION_IN_CUL,
FilingKey.NOTICE_OF_WITHDRAWAL])),
('staff_no_business_llc', False, Business.State.ACTIVE, ['LLC'], 'staff', [STAFF_ROLE], []),
('staff_no_business_sp', False, Business.State.ACTIVE, ['SP'], 'staff', [STAFF_ROLE],
expected_lookup([FilingKey.REG_SP])),
Expand Down

0 comments on commit 110797b

Please sign in to comment.