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

Skip to content

Commit 88ad1fb

Browse files
authored
34085 34087 Legal API - Amalg colin business output and colin sync flow (#4730)
* 34085 34087 Legal API - Amalg colin business output and colin sync flow Signed-off-by: Kial Jinnah <[email protected]> * colin api - amalg expro flow change Signed-off-by: Kial Jinnah <[email protected]> * legal-api - amalg expro flow changes Signed-off-by: Kial Jinnah <[email protected]> * chore: colin api lint Signed-off-by: Kial Jinnah <[email protected]> * chore: sonarcloud line dupe in tests Signed-off-by: Kial Jinnah <[email protected]> * chore: fix tests Signed-off-by: Kial Jinnah <[email protected]> * chore: address sonarcloud Signed-off-by: Kial Jinnah <[email protected]> --------- Signed-off-by: Kial Jinnah <[email protected]>
1 parent b471c00 commit 88ad1fb

23 files changed

Lines changed: 1027 additions & 347 deletions

colin-api/src/colin_api/models/business_snapshot.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ def _business_dict(cls, business: Business, orig_identifier: str, cursor) -> Dic
8686
'foundingDate': cls._to_iso_datetime(business.founding_date),
8787
'taxId': business.business_number,
8888
'hasFutureEffectiveFiling': cls._has_future_effective_filing(cursor, business.corp_num),
89+
'jurisdiction': business.jurisdiction,
90+
'homeJurisdictionNumber': business.home_juris_num,
91+
'homeCompanyName': business.home_company_nme,
92+
'homeRecognitionDate': cls._to_iso_datetime(business.home_recogn_dt),
8993
}
9094

9195
@staticmethod

colin-api/src/colin_api/models/filing.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,10 +1805,7 @@ def _process_amalgamating_businesses(cls, cursor, filing):
18051805

18061806
identifier = amalgamating_business.get('identifier')
18071807

1808-
if ((foreign_jurisdiction := amalgamating_business.get('foreignJurisdiction', {})) and
1809-
not (identifier.startswith('A') and # is expro
1810-
foreign_jurisdiction.get('country') == 'CA' and
1811-
foreign_jurisdiction.get('region') == 'BC')):
1808+
if foreign_jurisdiction := amalgamating_business.get('foreignJurisdiction'):
18121809
corp_involved.home_juri_num = identifier
18131810
corp_involved.foreign_nme = amalgamating_business.get('legalName')
18141811

colin-api/src/colin_api/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@
2222
Development release segment: .devN
2323
"""
2424

25-
__version__ = '2.172.0' # pylint: disable=invalid-name
25+
__version__ = '2.172.1' # pylint: disable=invalid-name

colin-api/tests/unit/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ def build_business(**overrides):
7878
# convert_to_json_datetime emits a '-00:00' suffix
7979
business.founding_date = '2000-01-01T08:00:00-00:00'
8080
business.email = '[email protected]'
81+
# find_by_identifier resolves 'BC' for non-XPRO corps; home_* stay None
82+
business.jurisdiction = 'BC'
8183
for key, value in overrides.items():
8284
setattr(business, key, value)
8385
return business

colin-api/tests/unit/api/test_business_snapshot.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ def test_get_snapshot(client, mocker, authorized, mock_db, mock_lookups): # pyl
3636
'adminFreeze': False,
3737
'foundingDate': '2000-01-01T08:00:00+00:00',
3838
'taxId': '791861078BC0001',
39-
'hasFutureEffectiveFiling': False
39+
'hasFutureEffectiveFiling': False,
40+
'jurisdiction': 'BC',
41+
'homeJurisdictionNumber': None,
42+
'homeCompanyName': None,
43+
'homeRecognitionDate': None
4044
},
4145
'parties': [{
4246
'officer': {
@@ -138,6 +142,31 @@ def test_get_snapshot_null_good_standing(client, mocker, authorized, mock_db,
138142
assert rv.json['business']['goodStanding'] is None
139143

140144

145+
def test_get_snapshot_extraprovincial(client, mocker, authorized, mock_db,
146+
mock_lookups): # pylint: disable=unused-argument
147+
"""Assert an extraprovincial (A) corp snapshots with its home jurisdiction data."""
148+
find = mocker.patch.object(Business, 'find_by_identifier', return_value=build_business(
149+
corp_num='A0077777',
150+
corp_type='A',
151+
jurisdiction='ON',
152+
home_juris_num='1234567',
153+
home_company_nme='HOME COMPANY INC.',
154+
home_recogn_dt='1999-01-01T08:00:00-00:00'
155+
))
156+
157+
rv = client.get('/api/v1/businesses/A0077777/snapshot')
158+
159+
assert rv.status_code == 200
160+
# no BC-strip on an A identifier
161+
assert find.call_args.args[0] == 'A0077777'
162+
assert rv.json['business']['identifier'] == 'A0077777'
163+
assert rv.json['business']['legalType'] == 'A'
164+
assert rv.json['business']['jurisdiction'] == 'ON'
165+
assert rv.json['business']['homeJurisdictionNumber'] == '1234567'
166+
assert rv.json['business']['homeCompanyName'] == 'HOME COMPANY INC.'
167+
assert rv.json['business']['homeRecognitionDate'] == '1999-01-01T08:00:00+00:00'
168+
169+
141170
def test_get_snapshot_single_connection_and_scope(client, mocker, authorized, mock_db,
142171
mock_lookups): # pylint: disable=unused-argument
143172
"""Assert one pooled session is used and the lookup is restricted to in-scope corp types."""
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
1-
"""Unit tests for colin-api models."""
1+
# Copyright © 2026 Province of British Columbia
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Unit tests for colin-api model logic that runs against a mocked cursor."""
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Copyright © 2026 Province of British Columbia
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Tests for Filing._process_amalgamating_businesses entry classification."""
15+
from unittest.mock import MagicMock
16+
17+
from colin_api.models import Business
18+
from colin_api.models.corp_involved import CorpInvolved
19+
from colin_api.models.filing import Filing
20+
21+
22+
def _process(mocker, amalgamating_businesses):
23+
"""Run _process_amalgamating_businesses over the entries; return (corp_involved rows, state updates)."""
24+
created = []
25+
mocker.patch.object(CorpInvolved, 'create_corp_involved', side_effect=lambda _cursor, obj: created.append(obj))
26+
update_corp_state = mocker.patch.object(Business, 'update_corp_state')
27+
28+
filing = Filing()
29+
filing.event_id = 1234567
30+
filing.body = {'amalgamatingBusinesses': amalgamating_businesses}
31+
Filing._process_amalgamating_businesses(MagicMock(), filing) # pylint: disable=protected-access
32+
33+
return created, update_corp_state
34+
35+
36+
def test_identifier_entry_bc_corp(mocker):
37+
"""Assert a BC identifier entry is HAM'd under its bare corp num."""
38+
created, update_corp_state = _process(mocker, [
39+
{'role': 'amalgamating', 'identifier': 'BC0870226'}
40+
])
41+
42+
assert len(created) == 1
43+
assert created[0].corp_num == '0870226'
44+
assert created[0].home_juri_num is None
45+
assert created[0].adopted_corp_ind is None
46+
update_corp_state.assert_called_once()
47+
assert update_corp_state.call_args.args[2] == '0870226'
48+
assert update_corp_state.call_args.args[3] == Business.CorpStateTypes.AMALGAMATED.value
49+
50+
51+
def test_identifier_entry_expro(mocker):
52+
"""Assert an identifier-only extraprovincial (A) entry is HAM'd under its full identifier."""
53+
created, update_corp_state = _process(mocker, [
54+
{'role': 'amalgamating', 'identifier': 'A0077777'}
55+
])
56+
57+
assert len(created) == 1
58+
assert created[0].corp_num == 'A0077777'
59+
assert created[0].home_juri_num is None
60+
assert created[0].foreign_nme is None
61+
update_corp_state.assert_called_once()
62+
assert update_corp_state.call_args.args[2] == 'A0077777'
63+
assert update_corp_state.call_args.args[3] == Business.CorpStateTypes.AMALGAMATED.value
64+
65+
66+
def test_holding_entry_marks_adopted(mocker):
67+
"""Assert a holding/primary identifier entry sets the adopted corp indicator."""
68+
created, _ = _process(mocker, [
69+
{'role': 'holding', 'identifier': 'BC0870226'}
70+
])
71+
72+
assert created[0].adopted_corp_ind == 'Y'
73+
74+
75+
def test_foreign_entry(mocker):
76+
"""Assert a true foreign entry records home jurisdiction data and no corp state change."""
77+
created, update_corp_state = _process(mocker, [
78+
{
79+
'role': 'amalgamating',
80+
'identifier': 'AB-1234567',
81+
'legalName': 'FOREIGN CO.',
82+
'foreignJurisdiction': {'country': 'CA', 'region': 'AB'}
83+
}
84+
])
85+
86+
assert len(created) == 1
87+
assert created[0].corp_num is None
88+
assert created[0].home_juri_num == 'AB-1234567'
89+
assert created[0].foreign_nme == 'FOREIGN CO.'
90+
assert created[0].can_jur_typ_cd == 'AB'
91+
update_corp_state.assert_not_called()
92+
93+
94+
def test_foreign_federal_and_international_entries(mocker):
95+
"""Assert federal and non-Canadian foreign entries map their jurisdiction codes."""
96+
created, _ = _process(mocker, [
97+
{
98+
'role': 'amalgamating',
99+
'identifier': '7654321',
100+
'legalName': 'FEDERAL CO.',
101+
'foreignJurisdiction': {'country': 'CA', 'region': 'FEDERAL'}
102+
},
103+
{
104+
'role': 'amalgamating',
105+
'identifier': 'US-1',
106+
'legalName': 'US CO.',
107+
'foreignJurisdiction': {'country': 'US', 'region': 'DE'}
108+
}
109+
])
110+
111+
assert created[0].can_jur_typ_cd == 'FD'
112+
assert created[1].can_jur_typ_cd == 'OT'
113+
assert created[1].othr_juri_desc == 'US, DE'

legal-api/poetry.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

legal-api/src/legal_api/reports/business_document.py

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -576,35 +576,52 @@ def _set_amalgamation_details(self, business: dict):
576576
if filings:
577577
amalgamation_application = filings[0]
578578
business["business"]["amalgamatedEntity"] = True
579-
if (self._epoch_filing_date and amalgamation_application.effective_date < self._epoch_filing_date) or\
580-
(self._tombstone_filing_date and
581-
amalgamation_application.effective_date < self._tombstone_filing_date):
579+
if self._is_imported_amalgamation(amalgamation_application):
582580
# imported from COLIN
583-
amalgamated_businesses_info = {
581+
amalgamated_businesses.append({
584582
"legalName": "N/A",
585583
"identifier": "N/A",
586584
"jurisdiction": "N/A"
587-
}
588-
amalgamated_businesses.append(amalgamated_businesses_info)
585+
})
589586
else:
590587
amalgamation = Amalgamation.get_revision(amalgamation_application.transaction_id,
591588
amalgamation_application.business_id)
592589
amalgamating_businesses = AmalgamatingBusiness.get_revision(amalgamation_application.transaction_id,
593590
amalgamation.id)
594-
for amalgamating_business in amalgamating_businesses:
595-
ting_business = None
596-
if not (foreign_name := amalgamating_business.foreign_name):
597-
ting_business = VersionedBusinessDetailsService.get_business_revision_obj(amalgamation_application,
598-
amalgamating_business.business_id)
599-
amalgamated_businesses_info = get_formatted_amalg_business_data(amalgamating_business.foreign_identifier,
600-
foreign_name,
601-
amalgamating_business.foreign_jurisdiction,
602-
amalgamating_business.foreign_jurisdiction_region,
603-
ting_business)
604-
amalgamated_businesses.append(amalgamated_businesses_info)
591+
amalgamated_businesses = [
592+
self._amalgamating_business_data(amalgamation_application, amalgamating_business)
593+
for amalgamating_business in amalgamating_businesses
594+
]
605595

606596
business["amalgamatedEntities"] = amalgamated_businesses
607597

598+
def _is_imported_amalgamation(self, amalgamation_application: Filing) -> bool:
599+
"""Return whether the amalgamation predates this business's COLIN import/tombstone migration."""
600+
effective_date = amalgamation_application.effective_date
601+
return bool(
602+
(self._epoch_filing_date and effective_date < self._epoch_filing_date) or
603+
(self._tombstone_filing_date and effective_date < self._tombstone_filing_date)
604+
)
605+
606+
@staticmethod
607+
def _amalgamating_business_data(amalgamation_application: Filing,
608+
amalgamating_business: AmalgamatingBusiness) -> dict:
609+
"""Return one amalgamating business's formatted report data."""
610+
ting_business = None
611+
identifier = amalgamating_business.foreign_identifier
612+
if not (foreign_name := amalgamating_business.foreign_name):
613+
if amalgamating_business.colin_identifier:
614+
# a COLIN business not loaded in LEAR - name is resolved from COLIN
615+
identifier = amalgamating_business.colin_identifier
616+
else:
617+
ting_business = VersionedBusinessDetailsService.get_business_revision_obj(
618+
amalgamation_application, amalgamating_business.business_id)
619+
return get_formatted_amalg_business_data(identifier,
620+
foreign_name,
621+
amalgamating_business.foreign_jurisdiction,
622+
amalgamating_business.foreign_jurisdiction_region,
623+
ting_business)
624+
608625
def _set_amalgamating_details(self, business: dict):
609626
if ("amalgamatedInto" in business["business"]) and business.get("amalgamatedEntities"):
610627
# Amalgamating business can contain amalgamatedEntities when it is created through an amalgamation

0 commit comments

Comments
 (0)