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
6 changes: 4 additions & 2 deletions legal-api/src/legal_api/resources/v2/business/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

Provides all the search and retrieval from the business entity datastore.
"""
import re
from contextlib import suppress
from http import HTTPStatus

Expand Down Expand Up @@ -63,7 +64,8 @@ def get_businesses(identifier: str):
# - (i.e. business/person search updates)
return get_businesses_public(identifier, True)

if identifier.startswith("T"):
# Temp bootstrap ids start with "T". Real tramways are TMY + 7 digits (e.g. TMY0000008).
if identifier.startswith("T") and not re.fullmatch(r"TMY\d{7}", identifier):
return {"message": babel("No information on temp registrations.")}, 200

business = Business.find_by_identifier(identifier)
Expand Down Expand Up @@ -135,7 +137,7 @@ def get_businesses(identifier: str):
@jwt.requires_auth
def get_businesses_public(identifier: str, slim = False):
"""Return a JSON object with public meta information about the business."""
if identifier.startswith("T"):
if identifier.startswith("T") and not re.fullmatch(r"TMY\d{7}", identifier):
return {"message": babel("No information on temp registrations.")}, 200

business = Business.find_by_identifier(identifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

Provides all the search and retrieval from the business entity datastore.
"""
import re
from datetime import UTC, datetime
from http import HTTPStatus

Expand All @@ -38,7 +39,8 @@
def get_comments(identifier, comment_id=None):
"""Return a JSON object with meta information about the Service."""
# basic checks
if identifier.startswith("T"):
# Temp bootstrap ids start with "T". Real tramways are TMY + 7 digits (e.g. TMY0000008).
if identifier.startswith("T") and not re.fullmatch(r"TMY\d{7}", identifier):
filing_model = FilingModel.get_temp_reg_filing(identifier)
business = Business.find_by_internal_id(filing_model.business_id)
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ class FilingModel(BaseModel, Generic[FilingT]):
@pydantic_validate(query=QueryModel)
def get_filings(identifier: str, filing_id: int | None = None):
"""Return a JSON object with meta information about the Filing Submission."""
if filing_id or identifier.startswith("T"):
# Temp bootstrap ids start with "T" (e.g. Tabc12XyZ9). Real tramways are TMY + 7 digits
# (e.g. TMY0000008) — exclude only that shape so random temps like TMYHLpcaq7 stay temp.
if filing_id or (identifier.startswith("T") and not re.fullmatch(r"TMY\d{7}", identifier)):
if str(request.args.get("public", None)).lower() == "true":
return ListFilingResource.get_single_filing_public_json(filing_id)

Expand Down
32 changes: 32 additions & 0 deletions legal-api/tests/unit/resources/v2/test_business.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,38 @@ def test_get_temp_business_info(session, client, jwt):
headers=create_header(jwt, [STAFF_ROLE], identifier))

assert rv.status_code == HTTPStatus.OK
assert rv.json['message'] == 'No information on temp registrations.'


@pytest.mark.parametrize('identifier, is_temp_message', [
('TMYHLpcaq7', True), # random temp that happens to start with TMY
('TMY0000008', False), # real tramway number
])
def test_get_business_info_tramway_vs_temp_tmy_prefix(session, client, jwt, identifier, is_temp_message):
"""Assert TMY+7digits is a real business; other TMY… temps stay temp."""
if not is_temp_message:
# TMY identifiers don't pass the standard CP/BC/FM validate_identifier check.
# Set _identifier directly, same pattern as bootstrap temp_reg tests.
b = factory_business_model(legal_name=f'{identifier} legal name',
identifier='CP0000001', # valid placeholder to pass constructor
founding_date=datetime.fromtimestamp(0, UTC),
last_ledger_timestamp=datetime.fromtimestamp(0, UTC),
last_modified=datetime.fromtimestamp(0, UTC),
fiscal_year_end_date=None,
tax_id=None,
dissolution_date=None,
legal_type='TMY')
b._identifier = identifier
b.save()

rv = client.get('/api/v2/businesses/' + identifier,
headers=create_header(jwt, [STAFF_ROLE], identifier))

assert rv.status_code == HTTPStatus.OK
if is_temp_message:
assert rv.json['message'] == 'No information on temp registrations.'
else:
assert rv.json['business']['identifier'] == identifier


@pytest.mark.parametrize('test_name,role,calls_auth', [
Expand Down
16 changes: 16 additions & 0 deletions legal-api/tests/unit/resources/v2/test_business_comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ def test_get_all_business_comments_no_results(session, client, jwt):
assert 0 == len(rv.json.get('comments'))


def test_get_tramway_business_comments(session, client, jwt):
"""Assert tramway identifiers use normal business lookup (not temp-reg path)."""
identifier = 'TMY0000008'
# TMY identifiers don't pass the standard CP/BC/FM validate_identifier check.
# Use a valid placeholder then set _identifier directly.
b = factory_business('CP0000002', entity_type='TMY')
b._identifier = identifier
b.save()

rv = client.get(f'/api/v2/businesses/{identifier}/comments',
headers=create_header(jwt, [STAFF_ROLE]))

assert HTTPStatus.OK == rv.status_code
assert [] == rv.json.get('comments')


def test_get_all_business_comments_only_one(session, client, jwt):
"""Assert that a list of comments with a single comment is returned correctly."""
identifier = 'CP7654321'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,45 @@ def test_get_temp_business_filing(session, client, jwt, legal_type, filing_type,
assert rv.json['filing'][filing_type] == filing_json


def test_get_filings_tramway_uses_ledger_listing(session, client, jwt, mocker):
"""Assert real tramway numbers use ledger listing, not the temp-reg path."""
identifier = 'TMY0000008'
# TMY identifiers don't pass the standard CP/BC/FM validate_identifier check.
# Use a valid placeholder then set _identifier directly.
b = factory_business('CP0000003', entity_type='TMY')
b._identifier = identifier
b.save()
mock_ledger = mocker.patch(
'legal_api.resources.v2.business.business_filings.business_filings.ListFilingResource.get_ledger_listing',
return_value=({'filings': []}, HTTPStatus.OK))
mock_single = mocker.patch(
'legal_api.resources.v2.business.business_filings.business_filings.ListFilingResource.get_single_filing')

rv = client.get(f'/api/v2/businesses/{identifier}/filings',
headers=create_header(jwt, [STAFF_ROLE], identifier))

assert rv.status_code == HTTPStatus.OK
mock_ledger.assert_called_once()
mock_single.assert_not_called()


def test_get_filings_temp_tmy_prefix_uses_single_filing(session, client, jwt, mocker):
"""Assert temps that start with TMY still use the temp-reg filing path."""
identifier = 'TMYHLpcaq7'
mock_ledger = mocker.patch(
'legal_api.resources.v2.business.business_filings.business_filings.ListFilingResource.get_ledger_listing')
mock_single = mocker.patch(
'legal_api.resources.v2.business.business_filings.business_filings.ListFilingResource.get_single_filing',
return_value=({'filing': {}}, HTTPStatus.OK))

rv = client.get(f'/api/v2/businesses/{identifier}/filings',
headers=create_header(jwt, [STAFF_ROLE], identifier))

assert rv.status_code == HTTPStatus.OK
mock_single.assert_called_once_with(identifier, None)
mock_ledger.assert_not_called()


@pytest.mark.parametrize(
'jwt_role, expected',
[
Expand Down
Loading