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
28 changes: 28 additions & 0 deletions legal-api/migrations/versions/b5ded56cab5b_filing_lear_only.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""empty message

Revision ID: b5ded56cab5b
Revises: 2467e09986f2
Create Date: 2026-03-13 09:27:35.973908

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = 'b5ded56cab5b'
down_revision = '2467e09986f2'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('filings', sa.Column('lear_only', sa.Boolean(), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('filings', 'lear_only')
# ### end Alembic commands ###
16 changes: 8 additions & 8 deletions legal-api/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion legal-api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ dependencies = [
"blinker (==1.4)",
"pyjwt (==2.8.0)",

"registry_schemas @ git+https://github.com/bcgov/business-schemas.git@2.18.63#egg=registry_schemas",
"registry_schemas @ git+https://github.com/bcgov/business-schemas.git@2.18.64#egg=registry_schemas",
"sql-versioning @ git+https://github.com/bcgov/lear.git@main#subdirectory=python/common/sql-versioning",
"gcp-queue @ git+https://github.com/bcgov/sbc-connect-common.git@main#subdirectory=python/gcp-queue",
"structured-logging @ git+https://github.com/bcgov/sbc-connect-common.git@main#subdirectory=python/structured-logging"
Expand Down
3 changes: 3 additions & 0 deletions legal-api/src/legal_api/models/filing.py
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ class Source(Enum):
"court_order_file_number",
"deletion_locked",
"hide_in_ledger",
"lear_only",
"effective_date",
"order_details",
"paper_only",
Expand Down Expand Up @@ -805,6 +806,7 @@ class Source(Enum):
_source = db.Column("source", db.String(15), default=Source.LEAR.value)
paper_only = db.Column("paper_only", db.Boolean, unique=False, default=False)
colin_only = db.Column("colin_only", db.Boolean, unique=False, default=False)
lear_only = db.Column("lear_only", db.Boolean, unique=False, default=False)
payment_account = db.Column("payment_account", db.String(30))
effective_date = db.Column("effective_date", db.DateTime(timezone=True), default=datetime.utcnow)
submitter_roles = db.Column("submitter_roles", db.String(200))
Expand Down Expand Up @@ -1343,6 +1345,7 @@ def get_completed_filings_for_colin(limit=20, offset=0):
~Business.legal_type.in_(excluded_businesses),
~Filing._filing_type.in_(excluded_filings),
~and_(Filing._filing_type == "dissolution", Filing._filing_sub_type == "delay"),
~Filing.lear_only,
Filing.colin_event_ids == None, # pylint: disable=singleton-comparison # noqa: E711;
Filing._status == Filing.Status.COMPLETED.value,
Filing._source == Filing.Source.LEAR.value,
Expand Down
22 changes: 22 additions & 0 deletions legal-api/src/legal_api/reports/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,10 @@ def _format_office_data(self, filing, prev_completed_filing: Filing):

def _format_party_data(self, filing, prev_completed_filing: Filing):
filing["parties"] = filing.get("correction").get("parties", [])
if relationships := filing.get("correction").get("relationships"):
# map relationships to parties for pdf templates
filing["parties"].extend([self._map_relationship_to_party(relationship) for relationship in relationships])

if filing.get("parties"):
self._format_directors(filing["parties"])
filing["partyChange"] = False
Expand Down Expand Up @@ -1490,6 +1494,24 @@ def _get_environment():
if namespace.endswith("test"):
return "TEST"
return ""

@staticmethod
def _map_relationship_to_party(relationship):
# FUTURE: update pdf templates to expect relationships schema and remove this
organization_name = relationship["entity"].get("businessName")
return {
"officer": {
"id": relationship["entity"].get("identifier"),
"firstName": relationship["entity"].get("givenName"),
"middleName": relationship["entity"].get("middleInitial"),
"lastName": relationship["entity"].get("familyName"),
"organizationName": organization_name,
"partyType": "organization" if organization_name else "person"
},
"deliveryAddress": relationship.get("deliveryAddress"),
"mailingAddress": relationship.get("mailingAddress"),
"roles": relationship.get("roles", [])
}


class ReportMeta: # pylint: disable=too-few-public-methods
Expand Down
107 changes: 75 additions & 32 deletions legal-api/src/legal_api/resources/v2/business/colin_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
@bp.route("/internal/filings", methods=["GET"])
@cross_origin(origin="*")
@jwt.has_one_of_roles([UserRoles.colin])
def get_completed_filings_for_colin(): # noqa: PLR0912
def get_completed_filings_for_colin():

Check failure on line 55 in legal-api/src/legal_api/resources/v2/business/colin_sync.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 23 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=bcgov_lear&issues=AZzjVzRJgSEyx58P14ro&open=AZzjVzRJgSEyx58P14ro&pullRequest=4148
"""Get filings by status formatted in json."""
filings = []

Expand All @@ -62,41 +62,17 @@
for filing in pending_filings:
business = Business.find_by_internal_id(filing.business_id)

filing_json = copy.deepcopy(filing.filing_json)
filing_json["filingId"] = filing.id
filing_json["filing"]["header"]["source"] = Filing.Source.LEAR.value
filing_json["filing"]["header"]["date"] = (filing.payment_completion_date or filing.filing_date).isoformat()
filing_json["filing"]["header"]["learEffectiveDate"] = filing.effective_date.isoformat()
filing_json["filing"]["header"]["isFutureEffective"] = filing.is_future_effective
filing_json["filing"]["header"]["hideInLedger"] = filing.hide_in_ledger

if filing.submitter_roles:
filing_json["filing"]["header"]["isStaff"] = (
UserRoles.staff in filing.submitter_roles or UserRoles.system in filing.submitter_roles
)
if filing.filing_submitter:
filing_json["filing"]["header"]["filedBy"] = {
"userName": filing.filing_submitter.username,
"firstName": filing.filing_submitter.firstname,
"lastName": filing.filing_submitter.lastname,
"email": filing.filing_submitter.email
}

if not filing_json["filing"].get("business"):
if filing.transaction_id:
business_revision = VersionedBusinessDetailsService.get_business_revision_obj(filing, business.id)
filing_json["filing"]["business"] = VersionedBusinessDetailsService.business_revision_json(
business_revision, business.json())
else:
# should never happen unless its a test data created directly in db.
# found some filing in DEV, adding this check to avoid exception
filing_json["filing"]["business"] = business.json()
elif not filing_json["filing"]["business"].get("legalName"):
filing_json["filing"]["business"]["legalName"] = business.legal_name
filing_json = _get_initial_filing_json(filing, business)

if filing.filing_type == "correction" and business.legal_type != Business.LegalTypes.COOP.value:
try:
set_correction_flags(filing_json, filing)
inner_filing_json = filing_json["filing"].get(filing.filing_type, {})
if inner_filing_json.get("relationships"):
# set directors and completing party from the db when filing_json is using relationships schema - ignore other parties
# NOTE: in the case where only non director parties were changed then set_correction_flags will not set partyChanged and parties will not be processed by the colin-api
# if no other colin relevant corrections were made then the lear_only flag will be set during the filer processing and it will not be picked up by 'get_completed_filings_for_colin'
_set_relationship_parties(business, filing, inner_filing_json)
except Exception as ex:
current_app.logger.error(f"correction: filingId={filing.id}, error: {ex!s}")
# to skip this filing and block subsequent filing from syncing in update-colin-filings
Expand Down Expand Up @@ -127,6 +103,43 @@
return jsonify({"filings": filings}), HTTPStatus.OK


def _get_initial_filing_json(filing: Filing, business: Business):
"""Return the initial filing json with common colin sync values set."""
filing_json = copy.deepcopy(filing.filing_json)
filing_json["filingId"] = filing.id
filing_json["filing"]["header"]["source"] = Filing.Source.LEAR.value
filing_json["filing"]["header"]["date"] = (filing.payment_completion_date or filing.filing_date).isoformat()
filing_json["filing"]["header"]["learEffectiveDate"] = filing.effective_date.isoformat()
filing_json["filing"]["header"]["isFutureEffective"] = filing.is_future_effective
filing_json["filing"]["header"]["hideInLedger"] = filing.hide_in_ledger

if filing.submitter_roles:
filing_json["filing"]["header"]["isStaff"] = (
UserRoles.staff in filing.submitter_roles or UserRoles.system in filing.submitter_roles
)
if filing.filing_submitter:
filing_json["filing"]["header"]["filedBy"] = {
"userName": filing.filing_submitter.username,
"firstName": filing.filing_submitter.firstname,
"lastName": filing.filing_submitter.lastname,
"email": filing.filing_submitter.email
}

if not filing_json["filing"].get("business"):
if filing.transaction_id:
business_revision = VersionedBusinessDetailsService.get_business_revision_obj(filing, business.id)
filing_json["filing"]["business"] = VersionedBusinessDetailsService.business_revision_json(
business_revision, business.json())
else:
# should never happen unless its a test data created directly in db.
# found some filing in DEV, adding this check to avoid exception
filing_json["filing"]["business"] = business.json()
elif not filing_json["filing"]["business"].get("legalName"):
filing_json["filing"]["business"]["legalName"] = business.legal_name

return filing_json


def set_correction_flags(filing_json, filing: Filing):
"""Set what section changed in this correction."""
if filing.meta_data.get("commentOnly", False):
Expand Down Expand Up @@ -324,6 +337,36 @@
amalgamation_filing["shareStructure"]["resolutionDates"] = business_dates


def _map_entity_to_officer(entity: dict[str, str]):
return {
"firstName": entity.get("givenName"),
"lastName": entity.get("familyName"),
"middleInitial": entity.get("middleInitial"),
"organizationName": entity.get("businessName"),
"id": entity.get("identifier")
}


def _set_relationship_parties(business: Business, filing: Filing, filing_json: dict):
"""Override filing_json with parties set from the db. Only Directors and Completing Party will be added."""
parties: list = VersionedBusinessDetailsService.get_party_role_revision(filing,
business.id,
role=PartyRole.RoleTypes.DIRECTOR.value)

# copy completing party from filing json
for party_info in filing_json.get("relationships"):
if comp_party_role := next((x for x in party_info.get("roles")
if x["roleType"].lower() == "completing party"), None):
mapped_party_info = {
"officer": _map_entity_to_officer(party_info["entity"]),
"roles": [comp_party_role]
}
parties.append(mapped_party_info)
break

filing_json["parties"] = parties


@bp.route("/internal/filings/<int:filing_id>", methods=["PATCH"])
@cross_origin(origin="*")
@jwt.has_one_of_roles([UserRoles.colin])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,22 @@ def validate(business: Business, filing_json: dict) -> Optional[Error]:
business,
filing_json,
filing_type,
PartyRole.RoleTypes.LIQUIDATOR,
[PartyRole.RoleTypes.LIQUIDATOR],
filing_sub_type in ["appointLiquidator", "intentToLiquidate"],
filing_sub_type in ["ceaseLiquidator", "changeAddressLiquidator"]
))

if filing_json["filing"][filing_type].get("offices"):
allowed_offices = ["liquidationRecordsOffice"] if filing_sub_type in ["intentToLiquidate", "changeAddressLiquidator"] else []
required_offices = ["liquidationRecordsOffice"] if filing_sub_type in ["intentToLiquidate"] else []
allowed_offices = []
required_offices = []
if filing_sub_type in ["intentToLiquidate", "changeAddressLiquidator"]:
allowed_offices = ["liquidationRecordsOffice"]
if filing_sub_type == "intentToLiquidate":
required_offices = ["liquidationRecordsOffice"]
elif filing_sub_type == "appointLiquidator" and not business.in_liquidation:
allowed_offices = ["liquidationRecordsOffice"]
required_offices = ["liquidationRecordsOffice"]

msg.extend(validate_offices(filing_json, filing_type, allowed_offices, required_offices, False))

if msg:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def validate(business: Business, filing_json: dict) -> Optional[Error]:
business,
filing_json,
filing_type,
PartyRole.RoleTypes.RECEIVER,
[PartyRole.RoleTypes.RECEIVER],
filing_sub_type in ["amendReceiver", "appointReceiver"],
filing_sub_type in ["amendReceiver", "ceaseReceiver", "changeAddressReceiver"]
))
Expand Down
Loading