From bb3209f8e8894c9b9f7be95a9fd871c644e2ec69 Mon Sep 17 00:00:00 2001 From: Argus Chiu Date: Mon, 18 Mar 2024 08:40:25 -0700 Subject: [PATCH 001/113] Fix GET filing document list issue & amalgamation related error (#2525) --- legal-api/src/legal_api/models/legal_entity.py | 16 +++++++++------- .../business_filings/business_documents.py | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/legal-api/src/legal_api/models/legal_entity.py b/legal-api/src/legal_api/models/legal_entity.py index b0ffe37a3f..81167ab316 100644 --- a/legal-api/src/legal_api/models/legal_entity.py +++ b/legal-api/src/legal_api/models/legal_entity.py @@ -482,13 +482,15 @@ def _extend_json(self, d): if self.fiscal_year_end_date: d["fiscalYearEndDate"] = datetime.date(self.fiscal_year_end_date).isoformat() if self.state_filing_id: - if self.state == LegalEntity.State.HISTORICAL and ( - amalgamating_business := self.amalgamating_businesses.one_or_none() - ): - amalgamation = Amalgamation.find_by_id(amalgamating_business.amalgamation_id) - d["amalgamatedInto"] = amalgamation.json() - else: - d["stateFiling"] = f"{base_url}/{self.identifier}/filings/{self.state_filing_id}" + # TODO: revert once amalgamation tables and migration scripts have been run + # if self.state == LegalEntity.State.HISTORICAL and ( + # amalgamating_business := self.amalgamating_businesses.one_or_none() + # ): + # amalgamation = Amalgamation.find_by_id(amalgamating_business.amalgamation_id) + # d["amalgamatedInto"] = amalgamation.json() + # else: + # d["stateFiling"] = f"{base_url}/{self.identifier}/filings/{self.state_filing_id}" + d["stateFiling"] = f"{base_url}/{self.identifier}/filings/{self.state_filing_id}" if self.start_date: d["startDate"] = LegislationDatetime.format_as_legislation_date(self.start_date) diff --git a/legal-api/src/legal_api/resources/v2/business/business_filings/business_documents.py b/legal-api/src/legal_api/resources/v2/business/business_filings/business_documents.py index 635fb00d2b..14a48c1aba 100644 --- a/legal-api/src/legal_api/resources/v2/business/business_filings/business_documents.py +++ b/legal-api/src/legal_api/resources/v2/business/business_filings/business_documents.py @@ -73,7 +73,7 @@ def get_documents(identifier: str, filing_id: int, legal_filing_name: str = None HTTPStatus.NOT_FOUND, ) - if not (filing := Filing.get(identifier, filing_id)): + if not (filing := Filing.get(identifier, business, filing_id)): return ( jsonify( message=get_error_message( From 005360af6eb9cdf6814e1a244bd0393ed00a0f77 Mon Sep 17 00:00:00 2001 From: Shaoyun Tong <144159934+tshyun24@users.noreply.github.com> Date: Tue, 19 Mar 2024 15:40:52 -0700 Subject: [PATCH 002/113] 20212 - amalgamation table change (#2527) * amalgamation table change * clean up --- .../transfer_to_new_lear.sql | 112 +++++++++++++++--- 1 file changed, 95 insertions(+), 17 deletions(-) diff --git a/legal-api/scripts/manual_db_scripts/legal_name_change/transfer_to_new_lear.sql b/legal-api/scripts/manual_db_scripts/legal_name_change/transfer_to_new_lear.sql index adce5ab29e..114f6d921d 100644 --- a/legal-api/scripts/manual_db_scripts/legal_name_change/transfer_to_new_lear.sql +++ b/legal-api/scripts/manual_db_scripts/legal_name_change/transfer_to_new_lear.sql @@ -934,33 +934,111 @@ SELECT stg.filing_id, FROM public.sent_to_gazette stg; --- amalgamation -> amalgamations +-- amalgamations -> amalgamations CREATE CAST (varchar AS amalgamation_type) WITH INOUT AS IMPLICIT; transfer public.amalgamations from lear_old using -SELECT id, - business_id as legal_entity_id, - filing_id, - amalgamation_date, - amalgamation_type, - court_approval -FROM public.amalgamation; +SELECT a.id, + a.business_id as legal_entity_id, + a.filing_id, + a.amalgamation_date, + a.amalgamation_type, + a.court_approval, + a.filing_id as change_filing_id, + COALESCE(av.version, 1) as version +FROM public.amalgamations a + left join (select id, max(transaction_id) as transaction_id, count(transaction_id) as version + from public.amalgamations_version + group by id) av on a.id = av.id + left join public.filings f + on av.transaction_id not in (select transaction_id from temp_multiple_filing_transactions) and + f.transaction_id = av.transaction_id + left join temp_multiple_filing_transactions tmft on av.transaction_id = tmft.transaction_id +; + + +-- amalgamations_version -> amalgamations_history +transfer public.amalgamations_history from lear_old using +with subquery as + (SELECT av.id, + av.business_id as legal_entity_id, + av.filing_id, + av.filing_id as change_filing_id, + av.amalgamation_date, + av.amalgamation_type, + av.court_approval, + t.issued_at as changed, + COALESCE(ROW_NUMBER() OVER (PARTITION BY av.id ORDER BY av.transaction_id ASC), 1) as version + from public.amalgamations_version av + left join public.transaction t + on av.transaction_id not in + (select transaction_id from temp_multiple_filing_transactions) and + av.transaction_id = t.id + left join public.filings f on f.transaction_id = t.id + left join temp_multiple_filing_transactions tmft on av.transaction_id = tmft.transaction_id), + max_versions as + (select id, max(version) as max_version + from subquery sq + group by id) +select sq.* +from subquery sq + left join max_versions mv on mv.id = sq.id +where sq.version != mv.max_version; --- amalgamating_business -> amalgamating_businesses +-- amalgamating_businesses -> amalgamating_businesses CREATE CAST (varchar AS amalgamating_business_role) WITH INOUT AS IMPLICIT; transfer public.amalgamating_businesses from lear_old using -SELECT id, - business_id as legal_entity_id, - amalgamation_id, - foreign_jurisdiction, - foreign_jurisdiction_region, - foreign_name, - foreign_corp_num as foreign_identifier, +SELECT a.id, + a.business_id as legal_entity_id, + a.amalgamation_id, + a.foreign_jurisdiction, + a.foreign_jurisdiction_region, + a.foreign_name, + a.foreign_identifier, + f.id as change_filing_id, + COALESCE(av.version, 1) as version, role :: amalgamating_business_role -FROM public.amalgamating_business; +FROM public.amalgamating_businesses a + left join (select id, max(transaction_id) as transaction_id, count(transaction_id) as version + from public.amalgamating_businesses_version + group by id) av on a.id = av.id + left join public.filings f + on av.transaction_id not in (select transaction_id from temp_multiple_filing_transactions) and + f.transaction_id = av.transaction_id + left join temp_multiple_filing_transactions tmft on av.transaction_id = tmft.transaction_id +; +-- amalgamating_businesses_version -> amalgamating_businesses_history +transfer public.amalgamating_businesses_history from lear_old using +with subquery as + (SELECT av.id, + av.amalgamation_id, + av.foreign_jurisdiction, + av.foreign_jurisdiction_region, + av.foreign_name, + av.foreign_identifier, + av.role, + av.business_id as legal_entity_id, + f.id as change_filing_id, + t.issued_at as changed, + COALESCE(ROW_NUMBER() OVER (PARTITION BY av.id ORDER BY av.transaction_id ASC), 1) as version + from public.amalgamating_businesses_version av + left join public.transaction t + on av.transaction_id not in + (select transaction_id from temp_multiple_filing_transactions) and + av.transaction_id = t.id + left join public.filings f on f.transaction_id = t.id + left join temp_multiple_filing_transactions tmft on av.transaction_id = tmft.transaction_id), + max_versions as + (select id, max(version) as max_version + from subquery sq + group by id) +select sq.* +from subquery sq + left join max_versions mv on mv.id = sq.id +where sq.version != mv.max_version; -- ensure sequence numbers are updated so collisions with future data does not happen SELECT setval('users_id_seq', (select coalesce(max(id) + 1, 1) FROM public.users)); From 365919ace62712d11e8dd3d22de4ca6dde14016e Mon Sep 17 00:00:00 2001 From: thor Date: Tue, 19 Mar 2024 21:16:44 -0700 Subject: [PATCH 003/113] oas3 for business --- docs/oas/business.yaml | 4180 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4180 insertions(+) create mode 100644 docs/oas/business.yaml diff --git a/docs/oas/business.yaml b/docs/oas/business.yaml new file mode 100644 index 0000000000..204ca86c43 --- /dev/null +++ b/docs/oas/business.yaml @@ -0,0 +1,4180 @@ +openapi: 3.0.1 +info: + title: businesses + version: '2.0' + description: |- + Businesses provideas all of the services needed to manage legal entities. + This encompasses all types of businesses authorized to do business by the Registrar. + contact: + name: BC Registry + email: admin@daxiom.com + url: 'https://developer.bcregistry.daxiom.ca/' + license: + name: BSD-3-Clause + url: 'https://opensource.org/license/bsd-3-clause' +servers: + - url: 'https://bcregistry-sandbox.apigee.net/business/api/v2' + description: sandbox + - url: 'http://localhost:3000/business/api/v2' + description: local + - url: 'https://bcregistry-dev.apigee.net/business/api/v2' + description: dev + - url: 'https://bcregistry-test.apigee.net/business/api/v2' + description: test + - url: 'https://bcregistry-prod.apigee.net/business/api/v2' + description: prod +paths: + '/businesses/{identifier}': + parameters: + - $ref: '#/components/parameters/identifier' + get: + summary: get_business + responses: + '200': + description: OK + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/json: + schema: + $ref: '#/components/schemas/Business' + application/xml: + schema: + $ref: '#/components/schemas/Business' + '401': + description: Unauthorized + '404': + description: Not Found + operationId: get-business + description: 'Based on the users role, this returns basic information about a business.' + parameters: + - $ref: '#/components/parameters/accountId' + tags: + - business + '/businesses/{identifier}/filings': + parameters: + - $ref: '#/components/parameters/identifier' + get: + summary: get filing ledger + responses: + '200': + description: OK + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/json: + schema: + $ref: '#/components/schemas/Ledger' + operationId: get-businesses-identifier-filings + description: Return the current ledger of filings for a business. + tags: + - business + parameters: + - $ref: '#/components/parameters/accountId' + post: + summary: submit new filing + operationId: post-businesses-identifier-filings + responses: + '200': + description: OK + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/json: + schema: + type: object + properties: {} + description: Submit a filing to alter the state and data of a business. + tags: + - business + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Filing' + parameters: + - schema: + type: boolean + in: query + name: draft + description: 'save draft, no validation' + - schema: + type: boolean + in: query + name: only_validate + description: 'only validate, don''t save' + - $ref: '#/components/parameters/accountId' + '/businesses/{identifier}/filings/{filingId}/documents': + parameters: + - $ref: '#/components/parameters/identifier' + - $ref: '#/components/parameters/filingId' + get: + summary: filing documents list + tags: + - business + responses: + '200': + description: OK + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/json: + schema: + $ref: '#/components/schemas/Filing_documents' + operationId: get-businesses-identifier-filings-filingId-documents + description: Returns the list of documents available for a filing. + parameters: + - $ref: '#/components/parameters/accountId' + '/businesses/{identifier}/addresses': + parameters: + - $ref: '#/components/parameters/identifier' + get: + summary: get business addresses + responses: + '200': + description: OK + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/json: + schema: + $ref: '#/components/schemas/Office' + '401': + description: Unauthorized + '404': + description: Not Found + operationId: get-businesses-identifier-addresses + description: Returns the current addresses for the businesses. The number of addresses are based on the legal type. + tags: + - business + parameters: + - $ref: '#/components/parameters/accountId' + '/businesses/{identifier}/filings/{filingId}/documents/{documentName}': + parameters: + - $ref: '#/components/parameters/identifier' + - $ref: '#/components/parameters/filingId' + - $ref: '#/components/parameters/documentName' + get: + summary: filing document + tags: + - business + responses: + '200': + description: Created + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/pdf: + schema: + type: string + format: byte + description: PDF Document + readOnly: true + application/json: + schema: + type: object + properties: {} + operationId: get-businesses-identifier-filings-filingId-document + description: Return the requested document. + parameters: + - schema: + type: string + default: application/pdf + enum: + - application/pdf + - application/json + in: header + description: The mimetype of the object + name: Content-type + - $ref: '#/components/parameters/accountId' + '/businesses/{identifier}/documents/{documentName}': + parameters: + - name: identifier + in: path + required: true + description: The unique identifier for the business or organization. + schema: + type: string + example: BC1234567 + - schema: + type: string + enum: + - summary + - cogs + - cstat + - lseal + name: documentName + in: path + required: true + description: The name of the document being requested + get: + summary: business document + tags: + - business + responses: + '200': + description: Created + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/pdf: + schema: + type: string + format: byte + description: PDF Document + readOnly: true + application/json: + schema: + x-examples: + example-1: + alterations: [] + amalgamatedEntities: [] + business: + adminFreeze: false + arMaxDate: '2022-08-05' + arMinDate: '2022-12-15' + associationType: null + complianceWarnings: [] + coopType: Not Available + dissolutionDate: '2022-01-11T20:03:33.857887+00:00' + fiscalYearEndDate: '2021-12-15' + foundingDate: '2021-12-15T19:54:10.809174+00:00' + goodStanding: false + hasCorrections: false + hasRestrictions: false + identifier: BC0870884 + lastAddressChangeDate: '2021-12-15' + lastAnnualGeneralMeetingDate: '' + lastAnnualReportDate: '' + lastDirectorChangeDate: '2021-12-15' + lastLedgerTimestamp: '2021-12-15T19:54:33.898570+00:00' + lastModified: '2021-12-15T19:54:33.898532+00:00' + legalName: 0870884 B.C. LTD. + legalType: BEN + naicsCode: null + naicsDescription: null + naicsKey: null + nextAnnualReport: '2022-12-15T08:00:00+00:00' + state: HISTORICAL + stateFiling: 'https://LEGAL_API_BASE_URL/api/v1/businesses/BC0870884/filings/113730' + warnings: [] + entityAct: Business Corporations Act + entityDescription: BC Benefit Company + liquidation: {} + listOfTranslations: + - id: '319' + name: TEST TRANSLATION A + type: TRANSLATION + - id: '320' + name: TEST TRANSLATION B + type: TRANSLATION + nameChanges: + - filingDateTime: '2021-12-28T21:40:16.696239+00:00' + fromLegalName: LM LOGISTICS INC. + toLegalName: 0870884 B.C. LTD. + - filingDateTime: '2021-12-23T00:34:34.520725+00:00' + fromLegalName: 0870884 B.C. LTD. + toLegalName: LM LOGISTICS INC. + offices: + custodialOffice: + deliveryAddress: + addressCity: Victoria + addressCountry: CA + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 2334725 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: CA + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 2334724 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + recordsOffice: + deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 2317157 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 2317156 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + registeredOffice: + deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 2317159 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 2317158 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + parties: + - deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: '' + id: 2334722 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: '' + id: 2334723 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + officer: + email: null + firstName: LEKSHMI + id: 474411 + lastName: MALLIKA + partyType: person + roles: + - appointmentDate: '2022-01-11' + cessationDate: null + roleType: Custodian + - deliveryAddress: + addressCity: AB1 + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317160 + postalCode: V8X 5J8 + streetAddress: '#400A - 4000 SEYMOUR PLACE' + streetAddressAdditional: PENTHOUSE + mailingAddress: + addressCity: AB1 + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317161 + postalCode: V8X 5J8 + streetAddress: '#400A - 4000 SEYMOUR PLACE' + streetAddressAdditional: PENTHOUSE + officer: + email: null + firstName: BCREGTEST DALIA + id: 468575 + lastName: ONE + partyType: person + roles: + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Completing Party + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Incorporator + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Director + - deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317162 + postalCode: V8Z 5C5 + streetAddress: 3948 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317163 + postalCode: V8Z 5C5 + streetAddress: 3948 Helen Rd + streetAddressAdditional: '' + officer: + email: null + firstName: LEKSHMI + id: 468576 + lastName: GOKUL + partyType: person + roles: + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Director + registrarInfo: + endDate: null + name: T.K. SPARKS + startDate: '2022-06-01T00:00:00' + title: Registrar of Companies + reportDateTime: '2022-08-05T18:30:42.147556+00:00' + reportType: summary + stateFilings: + - effectiveDateTime: '2022-01-11T20:03:51.343818+00:00' + filingDateTime: '2022-01-11T20:03:33.857807+00:00' + filingName: Voluntary Dissolution + type: object + properties: + alterations: + type: array + items: + type: object + properties: + filingDateTime: + type: string + format: date-time + fromLegalType: + type: string + toLegalType: + type: string + amalgamatedEntities: + type: array + items: + type: object + properties: + identifier: + type: string + name: + type: string + required: + - identifier + - name + business: + $ref: '#/components/schemas/Business' + entityAct: + type: string + entityDescription: + type: string + liquidation: + type: object + properties: + filingDateTime: + type: string + format: date-time + listOfTranslations: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + type: + type: string + enum: + - DBA + - TRANSLATION + required: + - name + - type + nameChanges: + type: array + items: + type: object + properties: + filingDateTime: + type: string + format: date-time + fromLegalName: + type: string + toLegalName: + type: string + required: + - filingDateTime + - fromLegalName + - toLegalName + offices: + oneOf: + - properties: + recordsOffice: + $ref: '#/components/schemas/Office' + registeredOffice: + $ref: '#/components/schemas/Office' + custodialOffice: + $ref: '#/components/schemas/Office' + required: + - registeredOffice + - properties: + businessOffice: + $ref: '#/components/schemas/Office' + required: + - businessOffice + type: object + parties: + type: array + items: + $ref: '#/components/schemas/party' + registrarInfo: + type: object + required: + - startDate + - name + properties: + startDate: + type: string + format: date-time + example: '2022-06-01T00:00:00' + endDate: + type: string + format: date-time + example: '2022-06-01T00:00:00' + nullable: true + name: + type: string + title: + type: string + example: Registrar of Companies + reportDateTime: + type: string + format: date-time + example: '2022-08-05T19:50:04.960880+00:00' + reportType: + type: string + enum: + - summary + - cogs + - cstat + - lseal + stateFilings: + type: array + items: + type: object + properties: + effectiveDateTime: + type: string + format: date-time + filingDateTime: + type: string + format: date-time + filingName: + type: string + example: Voluntary Dissolution + required: + - business + - entityAct + - entityDescription + - registrarInfo + - reportDateTime + - reportType + examples: + summary-json: + value: + alterations: [] + amalgamatedEntities: [] + business: + adminFreeze: false + arMaxDate: '2022-08-05' + arMinDate: '2022-12-15' + associationType: null + complianceWarnings: [] + coopType: Not Available + dissolutionDate: '2022-01-11T20:03:33.857887+00:00' + fiscalYearEndDate: '2021-12-15' + foundingDate: '2021-12-15T19:54:10.809174+00:00' + goodStanding: false + hasCorrections: false + hasRestrictions: false + identifier: BC0870884 + lastAddressChangeDate: '2021-12-15' + lastAnnualGeneralMeetingDate: '' + lastAnnualReportDate: '' + lastDirectorChangeDate: '2021-12-15' + lastLedgerTimestamp: '2021-12-15T19:54:33.898570+00:00' + lastModified: '2021-12-15T19:54:33.898532+00:00' + legalName: 0870884 B.C. LTD. + legalType: BEN + naicsCode: null + naicsDescription: null + naicsKey: null + nextAnnualReport: '2022-12-15T08:00:00+00:00' + state: HISTORICAL + stateFiling: 'https://LEGAL_API_BASE_URL/api/v1/businesses/BC0870884/filings/113730' + warnings: [] + entityAct: Business Corporations Act + entityDescription: BC Benefit Company + liquidation: {} + listOfTranslations: + - id: '319' + name: TEST TRANSLATION A + type: TRANSLATION + - id: '320' + name: TEST TRANSLATION B + type: TRANSLATION + nameChanges: + - filingDateTime: '2021-12-28T21:40:16.696239+00:00' + fromLegalName: LM LOGISTICS INC. + toLegalName: 0870884 B.C. LTD. + - filingDateTime: '2021-12-23T00:34:34.520725+00:00' + fromLegalName: 0870884 B.C. LTD. + toLegalName: LM LOGISTICS INC. + offices: + custodialOffice: + deliveryAddress: + addressCity: Victoria + addressCountry: CA + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 2334725 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: CA + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 2334724 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + recordsOffice: + deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 2317157 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 2317156 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + registeredOffice: + deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 2317159 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 2317158 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + parties: + - deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: '' + id: 2334722 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: '' + id: 2334723 + postalCode: V8Z 5C5 + streetAddress: 3950 Helen Rd + streetAddressAdditional: '' + officer: + email: null + firstName: LEKSHMI + id: 474411 + lastName: MALLIKA + partyType: person + roles: + - appointmentDate: '2022-01-11' + cessationDate: null + roleType: Custodian + - deliveryAddress: + addressCity: AB1 + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317160 + postalCode: V8X 5J8 + streetAddress: '#400A - 4000 SEYMOUR PLACE' + streetAddressAdditional: PENTHOUSE + mailingAddress: + addressCity: AB1 + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317161 + postalCode: V8X 5J8 + streetAddress: '#400A - 4000 SEYMOUR PLACE' + streetAddressAdditional: PENTHOUSE + officer: + email: null + firstName: BCREGTEST DALIA + id: 468575 + lastName: ONE + partyType: person + roles: + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Completing Party + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Incorporator + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Director + - deliveryAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317162 + postalCode: V8Z 5C5 + streetAddress: 3948 Helen Rd + streetAddressAdditional: '' + mailingAddress: + addressCity: Victoria + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + deliveryInstructions: null + id: 2317163 + postalCode: V8Z 5C5 + streetAddress: 3948 Helen Rd + streetAddressAdditional: '' + officer: + email: null + firstName: LEKSHMI + id: 468576 + lastName: GOKUL + partyType: person + roles: + - appointmentDate: '2021-12-15' + cessationDate: null + roleType: Director + registrarInfo: + endDate: null + name: T.K. SPARKS + startDate: '2022-06-01T00:00:00' + title: Registrar of Companies + reportDateTime: '2022-08-05T18:30:42.147556+00:00' + reportType: summary + stateFilings: + - effectiveDateTime: '2022-01-11T20:03:51.343818+00:00' + filingDateTime: '2022-01-11T20:03:33.857807+00:00' + filingName: Voluntary Dissolution + cogs-json: + value: + business: + adminFreeze: false + arMaxDate: '2022-08-05' + arMinDate: '2022-09-15' + associationType: null + complianceWarnings: [] + coopType: Not Available + fiscalYearEndDate: '2021-09-15' + foundingDate: '2021-09-15T16:00:14.432669+00:00' + goodStanding: true + hasCorrections: false + hasRestrictions: false + identifier: BC0870737 + lastAddressChangeDate: '2021-09-15' + lastAnnualGeneralMeetingDate: '' + lastAnnualReportDate: '' + lastDirectorChangeDate: '2021-09-15' + lastLedgerTimestamp: '2021-09-15T16:01:39.303977+00:00' + lastModified: '2021-09-15T16:01:39.303957+00:00' + legalName: TEST CONSUMED STATE 2 LTD. + legalType: BEN + naicsCode: null + naicsDescription: null + naicsKey: null + nextAnnualReport: '2022-09-15T07:00:00+00:00' + state: ACTIVE + warnings: [] + entityAct: Business Corporations Act + entityDescription: BC Benefit Company + registrarInfo: + endDate: null + name: T.K. SPARKS + startDate: '2022-06-01T00:00:00' + title: Registrar of Companies + reportDateTime: '2022-08-05T16:49:06.231324+00:00' + reportType: cogs + cstat-json: + value: + business: + adminFreeze: false + arMaxDate: '2022-08-05' + arMinDate: '2022-09-14' + associationType: null + complianceWarnings: [] + coopType: Not Available + fiscalYearEndDate: '2021-09-14' + foundingDate: '2019-09-14T17:17:45.348163+00:00' + goodStanding: true + hasCorrections: false + hasRestrictions: false + identifier: BC0870731 + lastAddressChangeDate: '2021-09-14' + lastAnnualGeneralMeetingDate: '' + lastAnnualReportDate: '2021-09-14' + lastDirectorChangeDate: '2021-09-22' + lastLedgerTimestamp: '2021-09-14T17:18:01.298719+00:00' + lastModified: '2021-09-14T17:18:01.298697+00:00' + legalName: TESTING CONV CORP. + legalType: BEN + naicsCode: null + naicsDescription: null + naicsKey: null + nextAnnualReport: '2022-09-14T07:00:00+00:00' + state: ACTIVE + warnings: [] + entityAct: Business Corporations Act + entityDescription: BC Benefit Company + registrarInfo: + endDate: null + name: T.K. SPARKS + startDate: '2022-06-01T00:00:00' + title: Registrar of Companies + reportDateTime: '2022-08-05T19:49:15.643657+00:00' + reportType: cstat + lseal-json: + value: + business: + adminFreeze: false + arMaxDate: '2022-01-23' + arMinDate: '2021-11-24' + associationType: null + complianceWarnings: [] + coopType: Not Available + fiscalYearEndDate: '2020-11-24' + foundingDate: '2020-11-24T18:23:53.498863+00:00' + goodStanding: false + hasCorrections: false + hasRestrictions: false + identifier: BC1230038 + lastAddressChangeDate: '2020-11-24' + lastAnnualGeneralMeetingDate: '' + lastAnnualReportDate: '' + lastDirectorChangeDate: '2020-11-24' + lastLedgerTimestamp: '2020-11-24T18:24:27.179623+00:00' + lastModified: '2020-11-24T18:24:27.179616+00:00' + legalName: 1230038 B.C. LTD. + legalType: BEN + naicsCode: null + naicsDescription: null + naicsKey: null + nextAnnualReport: '2021-11-24T08:00:00+00:00' + state: ACTIVE + warnings: [] + entityAct: Business Corporations Act + entityDescription: BC Benefit Company + offices: + recordsOffice: + deliveryAddress: + addressCity: Montréal + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 38012 + postalCode: H4E 1G8 + streetAddress: 4-1900 Av De l'Église + streetAddressAdditional: '' + mailingAddress: + addressCity: Montréal + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 38011 + postalCode: H4E 1G8 + streetAddress: 4-1900 Av De l'Église + streetAddressAdditional: '' + registeredOffice: + deliveryAddress: + addressCity: Montréal + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: delivery + deliveryInstructions: '' + id: 38014 + postalCode: H4E 1G8 + streetAddress: 4-1900 Av De l'Église + streetAddressAdditional: '' + mailingAddress: + addressCity: Montréal + addressCountry: Canada + addressCountryDescription: Canada + addressRegion: BC + addressType: mailing + deliveryInstructions: '' + id: 38013 + postalCode: H4E 1G8 + streetAddress: 4-1900 Av De l'Église + streetAddressAdditional: '' + registrarInfo: + endDate: null + name: T.K. SPARKS + startDate: '2022-06-01T00:00:00' + title: Registrar of Companies + reportDateTime: '2022-08-05T19:50:04.960880+00:00' + reportType: lseal + stateFilings: [] + operationId: get-businesses-identifier-document-documentName + description: Return the requested document. + parameters: + - schema: + type: string + enum: + - application/pdf + - application/json + in: header + name: Accept + description: The accept mimetype of the object + - $ref: '#/components/parameters/accountId' + /businesses: + post: + summary: save business creation filing + tags: + - business + responses: + '201': + description: 'Created ' + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + operationId: post-businesses + description: Submitting a creation filing for a business will create that type of business if it is a fully valid filing and payment has been completed. + requestBody: + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/Incorporation_application' + - $ref: '#/components/schemas/Registration' + parameters: + - schema: + type: boolean + in: query + name: draft + description: Set to save a draft in the ledger. No validations are performed. + - schema: + type: boolean + in: query + description: 'Validate the submission, but do not save or process it. Errors and warnings are returned if there are any.' + name: only_validate + - $ref: '#/components/parameters/accountId' + parameters: [] + '/businesses/{identifier}/parties': + parameters: + - schema: + type: string + description: business identifier is the registration or incorporation number of the business. + name: identifier + in: path + required: true + get: + summary: get_all_parties + tags: + - business + responses: + '200': + description: OK + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/json: + schema: + $ref: '#/components/schemas/party' + operationId: get-businesses-identifier-parties + description: Get all associated parties with a business. + parameters: + - $ref: '#/components/parameters/accountId' + /businesses/search: + get: + summary: business_autocomplete + tags: + - search + responses: + '200': + description: OK + headers: + Access-Control-Allow-Origin: + $ref: '#/components/headers/AccessControlAllowOrigin' + Access-Control-Allow-Methods: + $ref: '#/components/headers/AccessControlAllowMethods' + Access-Control-Allow-Headers: + $ref: '#/components/headers/AccessControlAllowHeaders' + Access-Control-Max-Age: + $ref: '#/components/headers/AccessControlMaxAge' + content: + application/json: + schema: + type: object + x-examples: + example-1: + responseHeader: + status: 0 + QTime: 35 + suggest: + elec: + numFound: 3 + suggestions: + - term: electronics and computer1 + weight: 2199 + - term: electronics + weight: 649 + - term: electronics and stuff2 + weight: 279 + properties: + responseHeader: + type: object + properties: + status: + type: integer + description: success state of the search + QTime: + type: integer + description: Time the suggestion took to generate in ms. + suggest: + type: object + properties: + search-term: + type: object + description: The search term that was entered + properties: + numFound: + type: integer + description: number of suggestion weighted high enough to return + suggestions: + type: array + description: Array of suggestion in weighted order + items: + $ref: '#/components/schemas/Suggestion_item' + operationId: get-businesses-search + description: The search resource returns autocomplete suggestions for matching businesses. + parameters: + - schema: + type: string + minLength: 1 + in: query + name: q + description: 'partial string of a business name, identifier or BN' + - $ref: '#/components/parameters/accountId' + x-internal: false + parameters: [] +components: + schemas: + Address: + type: object + title: Address Schema + description: 'Standard address format: apartment, unit, or street address number and street name. City, province or territory code, country, postal code and instructions for delivery.' + properties: + streetAddress: + type: string + maxLength: 50 + description: 'Address line 1: appt no, house no, building name, street name/number.' + example: 5-4761 Bay Street + streetAddressAdditional: + type: string + maxLength: 50 + description: 'Address line 2: extra address details added to line 1. ' + addressCity: + type: string + maxLength: 40 + example: Victoria + description: 'City, town, municipality.' + addressRegion: + type: string + maxLength: 2 + example: 'BC for British Columbia ' + description: '2 char code for province, state, territory or district.' + addressCountry: + type: string + example: Canada + description: 'Country name or abbreviation eg: USA.' + postalCode: + type: string + maxLength: 15 + example: V8R 2P1 + description: 'Postal, Pin, Zip, or letters/digits representing po stcode. ' + deliveryInstructions: + type: string + example: '"Our apartment is located at the back of the building."' + description: 'Specific instructions for the freight forwarder or carrier ' + required: + - streetAddress + - addressCity + - addressRegion + - addressCountry + - postalCode + x-examples: + Example 1: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Student Residence + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + Agreement_type: + type: object + title: Incorporation Agreement Type + description: 'Agreement to adopt articles of incorpoation. ' + x-examples: + Example 1: {} + x-extension-1: null + properties: + agreementType: + type: string + enum: + - sample + - custom + example: Sample or custom + description: 'Example: Sample and custom' + required: + - agreementType + Alteration: + type: object + title: Alteration Filing + description: 'Notice of Alteration allows alteration of information on the company''s notice of articles, except changes to the company''s directors or the registered or records office addresses.' + properties: + alteration: + type: object + required: + - business + - contactPoint + properties: + business: + $ref: '#/components/schemas/Business' + contactPoint: + $ref: '#/components/schemas/Contact_point' + provisionsRemoved: + type: boolean + title: Has Pre-existing company provisions? + description: Removal of the pre-existing company provisions Yes/No. + nameRequest: + $ref: '#/components/schemas/Name_request' + nameTranslations: + type: array + description: 'Add, delete or change any translation of a company’s name.' + items: + type: string + example: A translation of company name does not include company names that are specified in an English and/or French form. + shareStructure: + type: object + description: 'Refers to the kinds, classes and special rights and restrictions of shares that a company is authorized to issue. ' + properties: + resolutionDates: + type: array + description: 'Date the resolution was adopted. ' + items: + type: string + format: date + shareClasses: + type: array + description: 'example: Class A shares.' + items: + $ref: '#/components/schemas/Share_structure' + courtOrder: + $ref: '#/components/schemas/Court_order' + required: + - alteration + x-examples: + Example 1: + alteration: + business: + lastLedgerTimestamp: '2020-11-24T18:24:27.179623+00:00' + fiscalYearEndDate: '2020-11-24' + dissolutionDate: '2020-11-24T18:23:53.498863+00:00' + foundingDate: '2020-11-24T18:23:53.498863+00:00' + identifier: 'BC1234567 is an identifier for a corporation ' + legalName: '1234567 B.C. Ltd. is a legal name for a corporation ' + state: ACTIVE + legalType: 'GP: General Partnership' + taxId: BN123456789 + goodStanding: true + adminFreeze: true + naics: + naicsCode: 32621 is the code for 'Tires Manufacturing' description + naicsDescription: '''Tires Manufacturing'' is the description for code 32621' + natureOfBusiness: '***This field has been replaced by the NAICS code and NAICS description***' + complianceWarnings: + - code: INVALID_LEGAL_STRUCTURE_DIRECTORS + message: A minimum of 3 directors is required + filing: 'https://LEGAL-API-HOST/api/v2/businesses/IDENTIFIER/filings/FILING_ID' + contactPoint: + email: abc.def@gov.bc.ca + phone: string + extension: 1234 + provisionsRemoved: true + nameRequest: + nrNumber: NR 0119436 + legalType: B.C. Company + legalName: ABC Inc. + requestType: BC Company Change of Name + status: Expired + expires: '2019-08-24T14:15:22Z' + consent: Consent to use name + submittedBy: John Smith + address: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Student Residences + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + nameTranslations: + - A translation of company name does not include company names that are specified in an English and/or French form. + shareStructure: + resolutionDates: + - '2019-08-24' + shareClasses: + - resolutionDates: + - '2019-08-24' + shareClasses: + - name: Redeemable Shares + priority: 0 + maxNumberOfShares: 100 + parValue: 50 + currency: CAD + hasMaximumShares: true + hasParValue: true + hasRightsOrRestrictions: true + series: + - name: Redeemable Preference Shares + priority: 0 + hasMaximumShares: true + hasRightsOrRestrictions: true + courtOrder: + courtOrder: + fileNumber: L041638 + orderDate: '2019-08-24T14:15:22Z' + effectOfOrder: The Company will cease operations + orderDetails: The Company is ordered to dissolve + Annual_report: + type: object + title: Annual Report Filing + description: To file any change or confirm the information shown in the Corporate Register. Must be filed within two months of the anniversary date of incorporation. + properties: + annualReport: + type: object + description: To file any change or confirm the information shown in the Corporate Register. Must be filed within two months of the anniversary date of incorporation. + required: + - annualReportDate + - directors + - offices + properties: + annualGeneralMeetingDate: + type: string + format: date + description: 'Date the AGM (annual general meeting) took place. ' + annualReportDate: + type: string + format: date + description: 'Fiscal Year covered in the annual report. ' + directors: + type: array + description: Individual who is a member of the board of directors of the company as a result of having been elected or appointed to that position + items: + type: object + properties: + officer: + type: object + description: Person responsible for the management and day-to-day operations of the company. + required: + - firstName + - lastName + properties: + firstName: + type: string + maxLength: 30 + description: First name of the director/officer. + lastName: + type: string + maxLength: 30 + description: Last name of the director/officer. + middleInitial: + type: string + maxLength: 30 + description: The middle name initial of the director/officer. + prevFirstName: + title: 'previous first name, in the case of a legal name change in a filing' + type: string + maxLength: 30 + description: Previous first name of director/officer if changed. + prevLastName: + title: 'previous last name, in the case of a legal name change in a filing' + type: string + maxLength: 30 + description: Previous last name of director/officer if changed. + prevMiddleInitial: + title: 'previous middle name, in the case of a legal name change in a filing' + type: string + maxLength: 30 + description: Previous middle name initial if changed. + deliveryAddress: + $ref: '#/components/schemas/Address' + mailingAddress: + $ref: '#/components/schemas/Address' + title: + type: string + example: Chief Executive Officer + description: Position in a corporation occupied by a director/officer. + appointmentDate: + type: string + format: date + description: Date the director or officer has started in the role. + cessationDate: + type: string + format: date + example: 'Date the officer has ended his/her role ' + description: Date the director or officer has been terminated in the role. + required: + - officer + - deliveryAddress + - appointmentDate + - cessationDate + offices: + $ref: '#/components/schemas/Office' + required: + - annualReport + x-examples: + Example 1: + annualReport: + annualGeneralMeetingDate: '2019-08-24' + annualReportDate: '2019-08-24' + directors: + - officer: + firstName: Mary + lastName: Smith + middleInitial: A + prevFirstName: Anna + prevLastName: White + prevMiddleInitial: B + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Samuel Building + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Samuel Building + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + title: Chief Executive Officer + appointmentDate: '2019-05-20' + cessationDate: '2019-08-10' + offices: + officeType: 'Head office ' + mailingAddress: + streetAddress: 5-4999 Fort Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our local is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Community Center A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our local is located at the back of the building."' + Business: + type: object + title: Businesses Schema + x-examples: + example-1: + lastLedgerTimestamp: '2020-11-24T18:24:27.179623+00:00' + fiscalYearEndDate: '2020-11-24' + dissolutionDate: '2020-11-24T18:23:53.498863+00:00' + foundingDate: '2020-11-24T18:23:53.498863+00:00' + identifier: BC1234567 + legalName: E.P. CHARLTON & CO. LIMITED + legalType: BEN + taxId: BN123456789 + state: ACTIVE + goodStanding: true + adminFreeze: true + natureOfBusiness: This field has been replaced by the NAICS code and NAICS description + naics: + naicsCode: 32621 is the code for 'Tires Manufacturing' description + naicsDescription: '''Tires Manufacturing'' is the description for code 32621' + complianceWarnings: + - code: INVALID_LEGAL_STRUCTURE_DIRECTORS + message: A minimum of 3 directors is required. + filing: 'https://LEGAL-API-HOST/api/v2/businesses/IDENTIFIER/filings/FILING_ID' + description: 'Organization or enterprising entity engaged in commercial, industrial, or professional activities.' + properties: + lastLedgerTimestamp: + type: string + format: date-time + example: '2020-11-24T18:24:27.179623+00:00' + description: Recorded date/time of a company's financial transactions. + fiscalYearEndDate: + type: string + format: date + example: '2020-11-24' + description: The fiscal year end is the date on which a company finishes a 12-month business cycle. + dissolutionDate: + type: string + format: date-time + example: '2020-11-24T18:23:53.498863+00:00' + description: Date the business has ceased operations. + foundingDate: + type: string + format: date-time + example: '2020-11-24T18:23:53.498863+00:00' + description: 'The date written on the company''s certificate of incorporation. ' + identifier: + type: string + example: 'BC1234567 is an identifier for a corporation ' + pattern: '^[A-Z]{1,3}[0-9]{7}|T[A-Za-z0-9]{9}$' + description: 'Unique code(letters & numbers) to identify a business, issued by the provincial or federal registry.' + legalName: + type: string + description: Name that appears on the formation document of the business. + example: '1234567 B.C. Ltd. is a legal name for a corporation ' + state: + type: string + enum: + - ACTIVE + - HISTORICAL + description: Indicates if the company is operational(active) or not. + legalType: + type: string + enum: + - BEN + - CP + - SP + - GP + - BC + example: 'GP: General Partnership' + description: 'Type of business eg: individual(SP), partnership(GP).' + taxId: + type: string + pattern: '^[0-9]{9}$' + example: BN123456789 + description: 'Company unique business number assigned by CRA: BN9 or BN15. ' + goodStanding: + type: boolean + description: Being in good standing means that the company is not in the process of being dissolved for non-filing of federal and/or provincial tax returns or non-filing of the BC annual report. + adminFreeze: + type: boolean + description: 'Example: If a business is not in good standing or investigated for fraud BC Registry Admin might freeze the business to prevent further filing from them. ' + naics: + $ref: '#/components/schemas/Naics' + natureOfBusiness: + type: string + maxLength: 1000 + minLength: 0 + example: '*** Not used, has been replaced by NAICS code and description***' + description: '*** Not used, has been replaced by NAICS code and description***' + complianceWarnings: + type: array + description: Changed for 'Warning' instead of 'compliance warning’ + items: + type: object + properties: + code: + type: string + description: 'eg: INVALID_LEGAL_STRUCTURE_DIRECTORS' + example: INVALID_LEGAL_STRUCTURE_DIRECTORS + message: + type: string + description: 'Text describing reason for warning: ''A minimum of 3 directors is required.''' + example: '''A minimum of 3 directors is required.''' + filing: + type: string + description: Filing link related to the warning. + example: '''https://LEGAL-API-HOST/api/v2/businesses/IDENTIFIER/filings/FILING_ID''' + required: + - identifier + Change_of_address: + type: object + description: 'Change of an address used by the business, could be different types of address eg: delivery address. ' + properties: + changeOfAddress: + type: object + description: 'Change of an address used by the business, could be different types of address eg: delivery address. ' + properties: + legalType: + type: string + example: Mailing address + description: 'Type of address to be changed eg: delivery address. ' + registeredOffice: + $ref: '#/components/schemas/Office' + recordsOffice: + $ref: '#/components/schemas/Office' + x-examples: + Example 1: + changeOfAddress: + legalType: Mailing address + registeredOffice: + officeType: 'Head office ' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + recordsOffice: + officeType: Head office + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Buillding A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + Change_of_directors: + type: object + description: 'Add or remove a director, or update information regarding a current director.' + properties: + changeOfDirectors: + type: array + description: 'Add or remove a director, or update information regarding a current director.' + items: + $ref: '#/components/schemas/party' + x-examples: + Example 1: + changeOfDirectors: + - party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Completing Party + officer: + givenName: John + familyName: Smith + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: BC for British Columbia + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: BC for British Columbia + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + title: Chief Executive Officer + Change_of_name: + type: object + title: Change of Entity Name + description: Change of legal name filing. + properties: + changeOfName: + anyOf: + - $ref: '#/components/schemas/Name_request' + - type: object + properties: + legalName: + type: string + description: Name that appears on the formation document of the business. + description: Change the legal name of a business. + required: + - changeOfName + x-examples: + Example 1: + changeOfName: + nrNumber: NR 0119436 + legalType: BC Corporation + legalName: ABC Inc. + requestType: Benefit Company Inc. + status: Expired + expires: '2019-08-24T14:15:22Z' + consent: 'NAME: Consent to use name' + submittedBy: John Smith + address: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building C + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + Change_of_registration: + type: object + description: 'Filing to alter the information of a business that uses a registration, such as Sole Proprietor or General Partnership.' + title: Change of Registration Filing + properties: + changeOfRegistration: + type: object + properties: + business: + $ref: '#/components/schemas/Business' + offices: + type: object + description: 'Addresses used by the business eg: office address.' + properties: + businessOffice: + $ref: '#/components/schemas/Office' + contactPoint: + $ref: '#/components/schemas/Contact_point' + nameRequest: + $ref: '#/components/schemas/Name_request' + parties: + type: array + items: + $ref: '#/components/schemas/party' + x-examples: + Example 1: + changeOfRegistration: + business: + lastLedgerTimestamp: '2020-11-24T18:24:27.179623+00:00' + fiscalYearEndDate: '2020-11-24' + dissolutionDate: '2020-11-24T18:23:53.498863+00:00' + foundingDate: '2020-11-24T18:23:53.498863+00:00' + identifier: 'BC1234567 is an identifier for a corporation ' + legalName: '1234567 B.C. Ltd. is a legal name for a corporation ' + state: ACTIVE + legalType: 'GP: General Partnership' + taxId: BN123456789 + goodStanding: true + adminFreeze: true + naics: + naicsCode: 32621 is the code for 'Tires Manufacturing' description.' + naicsDescription: '''Tires Manufacturing'' is the description for code 32621.' + natureOfBusiness: This field has been replaced by the NAICS code and NAICS description + complianceWarnings: + - code: string + message: string + filing: string + offices: + businessOffice: + officeType: 'Head office ' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4999 Bay Street + streetAddressAdditional: Building B + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the front of the building."' + contactPoint: + email: abc.def@gov.bc.ca + phone: (555) 555-5555 + extension: 1234 + nameRequest: + nrNumber: NR 0119436 + legalType: B.C. Company + legalName: ABC Inc. + requestType: Benefit Company Inc. + status: Expired + expires: '2019-08-24T14:15:22Z' + consent: 'Name: Consent to use name' + submittedBy: John Smith + address: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + parties: + - party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Officer + officer: + givenName: John + familyName: Smith + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit apartment is located at the back of the building."' + title: Chief Executive Officer + Comment: + type: object + description: 'Extra detail or note to post regarding the filing. ' + properties: + comment: + type: string + maxLength: 4096 + description: 'Extra detail or note to post regarding the filing. ' + example: '''BC Registry contacted the business owner by email on March 12'' ' + submitterDisplayName: + type: string + description: 'Display the name of the person making the filing. ' + timestamp: + type: string + format: date-time + example: '2022-04-19 15:59:55' + description: Date and time the comment has been posted. + reference: + oneOf: + - properties: + businessId: + type: string + example: C1234567 + description: 'Business Identifier-Business Number. ' + - properties: + filingId: + type: string + description: Filing referred to in comment. + description: 'What busineess and filing the comment is for. ' + type: object + title: '' + x-examples: + Example 1: + comment: '''BC Registry contacted the business owner by email on March 12''' + submitterDisplayName: John Smith + timestamp: '2022-04-19 15:59:55' + reference: + businessId: C1234567 + Contact_point: + type: object + title: Business Contact Point Schema + description: Contact information to use for the business. + x-examples: + Example 1: + email: abc.def@gov.bc.ca + phone: (555) 555-5555 + extension: 1234 + properties: + email: + type: string + format: email + description: email address to be used to contact the business. + example: abc.def@gov.bc.ca + phone: + type: string + format: phone + example: (250) 234-4433 + description: 'Phone number to be used to contact the business eg: (250) 234-4433.' + extension: + type: number + example: (555) 555-5555 + description: Extension number of the business contact phone number (555) 555-5555. + required: + - email + Conversion: + type: object + title: Conversion Filing + description: 'Filing to change the business type of an organization eg: convert from a Member-Funded Society to a BC Company.' + x-examples: + Example 1: + conversion: + nameRequest: + nrNumber: NR 0119436 + legalType: BC Corporation + legalName: ABC Inc. + requestType: BC Benefit Company Change of Name + status: COMPLETED + expires: '2019-08-24T14:15:22Z' + consent: 'NAME: Consent to use name' + submittedBy: John Smith + address: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + offices: + registeredOffice: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + recordsOffice: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + parties: + - party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Completing Party + officer: + givenName: John + familyName: Lane + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + title: Chief Executive Officer + shareStructure: + resolutionDates: + - '2019-08-24' + shareClasses: + - name: Common A + priority: 3 + maxNumberOfShares: 100 + parValue: 50 + currency: CAD + hasMaximumShares: true + hasParValue: true + hasRightsOrRestrictions: true + series: + - name: CLASS A + priority: 3 + hasMaximumShares: true + hasRightsOrRestrictions: true + contactPoint: + email: abc.def@gov.bc.ca + phone: string + extension: 1234 + incorporationAgreement: + agreementType: '"The Company has as its articles the following articles."' + properties: + conversion: + type: object + title: Conversion Filing + description: 'Filing to change the business type of an organization eg: convert from a Member-Funded Society to a BC Company' + required: + - nameRequest + - offices + - parties + - shareStructure + - contactPoint + properties: + nameRequest: + $ref: '#/components/schemas/Name_request' + offices: + type: object + description: A registered office is the statutory address of a registered business entity. + properties: + registeredOffice: + $ref: '#/components/schemas/Address' + recordsOffice: + $ref: '#/components/schemas/Address' + parties: + type: array + description: 'Director(s) and filing applicant information of business to convert. ' + items: + $ref: '#/components/schemas/party' + shareStructure: + $ref: '#/components/schemas/Share_structure' + contactPoint: + $ref: '#/components/schemas/Contact_point' + incorporationAgreement: + $ref: '#/components/schemas/Agreement_type' + required: + - conversion + Cooperative: + type: object + title: Cooperative Schema + description: Owned and controlled business from which benefits are derived and distributed equitably on the basis of use or as a business owned and controlled by the people who use its services. + x-examples: + Example 1: + cooperativeAssociationType: CP + rulesFileKey: cooperative/f722bf16-86be-430d-928d-5529853a3a2c.pdf + rulesFileName: Field not used + memorandumFileKey: cooperative/f722bf16-86be-430d-928d-5529853a3a2c.pdf + memorandumFileName: Field not used + properties: + cooperativeAssociationType: + type: string + title: The association type for cooperative filing + enum: + - CP + - HC + - CSC + example: '''CP''' + description: 'Defines cooperatives by type of membership eg: Financial Cooperatives.' + rulesFileKey: + type: string + title: The Identifier for rules file in file server + example: cooperative/f722bf16-86be-430d-928d-5529853a3a2c.pdf + description: 'Unique code identifying the memorendum of the cooperative eg: "cooperative/f722bf16-86be-430d-928d-5529853a3a2c.pdf"' + rulesFileName: + type: string + title: The file name while uploading + description: '***Item not used***' + example: '***Item not used***' + memorandumFileKey: + type: string + title: The Identifier for memorandum file in file server + example: cooperative/f722bf16-86be-430d-928d-5529853a3a2c.pdf + description: 'Unique code identifying the memorendum of the cooperative eg: "cooperative/f722bf16-86be-430d-928d-5529853a3a2c.pdf"' + memorandumFileName: + type: string + title: The file name while uploading + description: '***Item not used***' + example: '***Item not used***' + required: + - cooperativeAssociationType + - rulesFileKey + - rulesFileName + - memorandumFileKey + - memorandumFileName + Correction: + type: object + title: Correction Filing + description: '***Item not used*** Update of business information to fix/correct erroneous information. ' + properties: + correction: + type: object + required: + - correctedFilingId + - correctedFilingType + - comment + properties: + correctedFilingId: + type: integer + title: The id of the filing being corrected. + description: 'Identification of filing that needs correction. ' + correctedFilingType: + type: string + title: The type of the main filing being corrected. + enum: + - annualReport + - changeOfDirectors + - changeOfAddress + - dissolution + - specialResolution + - changeOfName + - incorporationApplication + - amalgamationApplication + - dissolved + - amendedAGM + - restoration + - amendedAnnualReport + - amendedChangeOfDirectors + - appointReceiver + - continuedOut + - correction + description: 'Type of filing that needs correction. ' + comment: + type: string + description: 'Comment on what is corrected and why. ' + correctedFilingDate: + type: string + format: date + title: The submission date of the final version of the filing being corrected. + description: 'The date the correction is filed. ' + diff: + type: array + description: What will be changed in the correction filing. + items: + $ref: '#/components/schemas/Diff' + required: + - correction + Court_order: + type: object + title: Court Order Information Schema + description: Order issued by the Provincial Court Registry. + properties: + courtOrder: + type: object + required: + - fileNumber + properties: + fileNumber: + type: string + minLength: 5 + maxLength: 20 + description: The court assigns each court order a unique file number up to 20 characters in length. + orderDate: + type: string + description: The date and time that the court order has been issued. + format: date-time + effectOfOrder: + type: string + minLength: 0 + maxLength: 500 + description: Textual description of the effect of the order on the legal entity. + orderDetails: + type: string + minLength: 0 + maxLength: 2000 + description: A brief note to explain the purpose of the Court Order. + required: + - courtOrder + x-examples: + Example 1: + courtOrder: + fileNumber: L041638 + orderDate: '2019-08-24T14:15:22Z' + effectOfOrder: The Company will cease operations + orderDetails: The Company is ordered to dissolve + Diff: + title: Differences filed in a correction + anyOf: + - properties: + '': + type: string + description: Description of the changes in correction filing. + properties: + diff: + type: array + items: + type: object + required: + - oldValue + - newValue + - path + properties: + oldValue: + title: Original Value + newValue: + title: Corrected Value + path: + type: string + title: Path of the property in json + description: '***Item not used*** What will be changed in the correction filing.' + type: object + Dissolution: + title: Dissolution Filing + type: object + description: 'Application for a company dissolution. ' + x-examples: + Example 1: + dissolution: + dissolutionDate: '2019-08-24' + dissolutionType: administrative + dissolutionStatementType: The company has made adequate provision for the payment of each of its liabilities + hasLiabilities: true + parties: + - party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Director + officer: + givenName: John + familyName: Smith + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + mailingAddress: + streetAddress: 2-111 Fort Street + streetAddressAdditional: Building ABC + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the front of the building."' + title: Chief Executive Officer + courtOrder: + courtOrder: + fileNumber: L041638 + orderDate: '2019-08-24T14:15:22Z' + effectOfOrder: The Company will cease operations + orderDetails: The Company is ordered to dissolve + custodialOffice: + officeType: 'Head office ' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building C + addressCity: Victoria + addressRegion: BC for British Columbia + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building C + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + affidavitFileKey: 011e332d-1b8e-4218-8710-ad8ac1fbc592.pdf + affidavitFileName: Field not used + properties: + dissolution: + type: object + description: 'Application for a company dissolution ' + required: + - dissolutionDate + - dissolutionType + properties: + dissolutionDate: + type: string + format: date + description: 'The dissolution is to take effect at 12:01a.m. Pacific Time on being a date that is not more than ten days after the date of the filing of the application.' + dissolutionType: + type: string + title: 'The Type of Dissolution, such as Administrative, Voluntary, etc.' + enum: + - administrative + - involuntary + - voluntary + - voluntaryLiquidation + - courtOrderedLiquidation + description: 'Type of dissolution stated in the filing eg: Court ordered liquidation.' + dissolutionStatementType: + type: string + example: The company has made adequate provision for the payment of each of its liabilities + description: Statement to describe the company’s liabilities + hasLiabilities: + title: The dissolved company has outstanding liabilities. + type: boolean + description: 'Whether the company has liability or not: Yes/No.' + parties: + type: array + description: Can be the company directors or applicant of the filing. + items: + $ref: '#/components/schemas/party' + courtOrder: + $ref: '#/components/schemas/Court_order' + custodialOffice: + $ref: '#/components/schemas/Office' + affidavitFileKey: + type: string + title: The Identifier for affidavit file in file server + description: Unique identifier for the dissolution filing affidavit. + affidavitFileName: + type: string + title: The file name while uploading + description: '***Item not used***' + example: '***Item not used***' + required: + - dissolution + filing_header: + type: object + description: 'Information identigying the filing. ' + x-examples: + Example 1: + header: + name: alteration + availableOnPaperOnly: true + inColinOnly: true + date: '2019-08-24' + certifiedBy: John Smith + email: John.Smith@gmail.ca + filingId: 1234 + effectiveDate: '2019-08-24T14:15:22Z' + paymentToken: string value + submitter: John Smith + status: DRAFT + affectedFilings: '[1234,4856]' + isCorrected: true + isCorrectionPending: true + comments: + - comment: '''BC Registry contacted the business owner by email on March 12'' ' + submitterDisplayName: John Smith + timestamp: '2022-04-19 15:59:55' + reference: + businessId: C1234567 + waiveFees: true + priority: true + routingSlipNumber: '123456789' + folioNumber: '1332' + datNumber: C234567890 + bcolAccountNumber: '910207' + sbcAccount: 82763 + paymentAccount: '180670' + paymentMethod: ONLINE_BANKING + isPaymentActionRequired: true + '': string + properties: + header: + type: object + required: + - name + - date + - certifiedBy + properties: + name: + type: string + title: The type of the main filing. + enum: + - alteration + - annualReport + - amalgamationApplication + - appointReceiver + - changeOfDirectors + - changeOfAddress + - changeOfName + - changeOfRegistration + - continuedOut + - conversion + - correction + - courtOrder + - dissolution + - dissolved + - incorporationApplication + - registration + - restoration + - specialResolution + - transition + - registrarsNotation + - registrarsOrder + description: 'Filing name. ' + availableOnPaperOnly: + type: boolean + description: 'If filing results(ouputs) available only on paper: Yes/No. ' + inColinOnly: + type: boolean + description: 'Filing information stored in COLIN only: Yes/No.' + date: + type: string + format: date + title: The submission date of the final version of the filing. + description: 'Date of the filing. ' + certifiedBy: + type: string + description: 'Staff certifying filing. ' + email: + type: string + format: email + description: email contact for the filing. + filingId: + type: integer + title: The id of the filing. + default: 0 + description: 'Filing identifier eg: 1234. ' + example: 1234 + effectiveDate: + type: string + format: date-time + title: The date and time a filing should become valid and applied. + description: Date and time the filing is taking effect. + paymentToken: + type: string + title: A valid payment token for this filing against this business. + description: 'Replaces sensitive payment information with a unique identifier, received back from SBC_PAY' + submitter: + type: string + title: Account name of the person submitting this filing. + description: 'Person/applicant submitting the filing. ' + status: + type: string + title: The status of this filing. + enum: + - DRAFT + - PENDING + - COMPLETED + - ERROR + description: 'Status of the filing eg: ''draft''. ' + example: '"DRAFT", "PENDING", "COMPLETED", "ERROR"' + affectedFilings: + type: array + title: List of affected filings (ids) from this filing. + description: 'Filings related to the header eg: [1234,4856].' + items: + type: integer + example: '[1234,4856]' + isCorrected: + type: boolean + title: Has this filing been corrected? + description: 'If filing has been corrected: Yes/No.' + isCorrectionPending: + type: boolean + title: Is a correction pending for this filing? + description: 'If filing correction are in pending status: Yes/No.' + comments: + type: array + title: List of filing comments. + description: 'Notes about filing. ' + items: + $ref: '#/components/schemas/Comment' + waiveFees: + type: boolean + description: 'Are fees being waived for the filing: Yes/No.' + priority: + type: boolean + description: 'Is it a priority filing: Yes/No. ' + routingSlipNumber: + type: string + title: A valid routing slip number in case of a staff filing. + maxLength: 9 + pattern: '^\d{9}$' + description: If filing paid with cash or cheque there will be a routing slip of 9 digits. + folioNumber: + type: string + title: A folio number used for payment tracking purposes. + maxLength: 50 + description: 'Reference number to help keep track of transactions eg: used in BCOL. ' + example: '1332' + datNumber: + type: string + title: A dat number used for payment tracking purposes. + maxLength: 10 + pattern: '^[A-Z]{1}[0-9]{7,9}$' + description: Payment identifyer (9 digits) for FAS payments. + example: C234567890 + bcolAccountNumber: + type: string + title: BCOL account number. + maxLength: 6 + pattern: ^(.*)$ + example: '910207' + description: 'BCOL account number to be debited if paying with a BCOL account eg: 910207.' + sbcAccount: + type: integer + title: authorization system account number. + description: 'SBC_AUTH account number. ' + paymentAccount: + type: string + title: payment org account identifier. + maxLength: 30 + pattern: ^(.*)$ + description: 'Payment identifyer from where the payment will be debited. ' + example: '180670' + paymentMethod: + type: string + title: payment method. + enum: + - ONLINE_BANKING + - CC + - DIRECT_PAY + - DRAWDOWN + - INTERNAL + description: 'Method of payment used to pay for filing, possible values are: ONLINE_BANKING,CC,DIRECT_PAY,DRAWDOWN,INTERNAL.' + example: credit card CC + isPaymentActionRequired: + type: boolean + title: flag for payment redirect. + description: Further action required to finalize the payment. + '': + type: string + x-stoplight: + id: 7nl2sc9w8mtqr + description: Header name. + required: + - header + Filing: + type: object + title: Registry Filing Envelope + x-examples: + example-1: + header: + header: + name: alteration + availableOnPaperOnly: true + inColinOnly: true + date: '2019-08-24' + certifiedBy: string + email: user@example.com + filingId: 0 + effectiveDate: '2019-08-24T14:15:22Z' + paymentToken: string + submitter: string + status: DRAFT + affectedFilings: + - 0 + isCorrected: true + isCorrectionPending: true + comments: + - comment: string + submitterDisplayName: string + timestamp: '2019-08-24T14:15:22Z' + reference: + businessId: string + waiveFees: true + priority: true + routingSlipNumber: string + folioNumber: string + datNumber: string + bcolAccountNumber: string + sbcAccount: 0 + paymentAccount: string + paymentMethod: ONLINE_BANKING + isPaymentActionRequired: true + business: + business: + lastLedgerTimestamp: '2019-08-24T14:15:22Z' + dissolutionDate: '2019-08-24' + fiscalYearEndDate: '2019-08-24' + foundingDate: '2019-08-24T14:15:22Z' + identifier: string + legalName: string + legalType: BC + taxId: string + state: ACTIVE + stateFiling: string + goodStanding: true + adminFreeze: true + complianceWarnings: + - code: string + message: string + filing: string + naics: + naicsCode: string + naicsDescription: string + natureOfBusiness: string + filing: + incorporationApplication: + contactPoint: + email: user@example.com + phone: string + extension: 0 + cooperative: + cooperativeAssociationType: CP + rulesFileKey: string + rulesFileName: string + memorandumFileKey: string + memorandumFileName: string + incorporationAgreement: + agreementType: sample + nameRequest: + nrNumber: string + legalName: string + legalType: string + requestType: string + status: string + expires: '2019-08-24T14:15:22Z' + consent: string + submittedBy: string + address: + streetAddress: string + streetAddressAdditional: string + addressCity: string + addressCountry: string + addressRegion: st + postalCode: string + deliveryInstructions: string + nameTranslations: + - id: string + name: string + offices: + registeredOffice: + officeType: string + mailingAddress: + streetAddress: string + streetAddressAdditional: string + addressCity: string + addressCountry: string + addressRegion: st + postalCode: string + deliveryInstructions: string + deliveryAddress: + streetAddress: string + streetAddressAdditional: string + addressCity: string + addressCountry: string + addressRegion: st + postalCode: string + deliveryInstructions: string + recordsOffice: + officeType: string + mailingAddress: + streetAddress: string + streetAddressAdditional: string + addressCity: string + addressCountry: string + addressRegion: st + postalCode: string + deliveryInstructions: string + deliveryAddress: + streetAddress: string + streetAddressAdditional: string + addressCity: string + addressCountry: string + addressRegion: st + postalCode: string + deliveryInstructions: string + parties: + - party: + taxId: string + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Completing Party + officer: + givenName: string + familyName: string + additionalName: string + middleInitial: string + taxId: string + email: user@example.com + deliveryAddress: + streetAddress: string + streetAddressAdditional: string + addressCity: string + addressCountry: string + addressRegion: st + postalCode: string + deliveryInstructions: string + mailingAddress: + streetAddress: string + streetAddressAdditional: string + addressCity: string + addressCountry: string + addressRegion: st + postalCode: string + deliveryInstructions: string + title: string + shareStructure: + resolutionDates: + - '2019-08-24' + shareClasses: + - name: string + priority: 0 + maxNumberOfShares: 0 + parValue: 0 + currency: string + hasMaximumShares: true + hasParValue: true + hasRightsOrRestrictions: true + series: + - name: string + priority: 0 + maxNumberOfShares: 0 + hasMaximumShares: true + hasRightsOrRestrictions: true + description: Submitting updates related to a business or incorporating/registering a new business. + properties: + header: + $ref: '#/components/schemas/filing_header' + business: + $ref: '#/components/schemas/Business' + filing: + oneOf: + - oneOf: + - $ref: '#/components/schemas/Incorporation_application' + - $ref: '#/components/schemas/Registration' + - anyOf: + - $ref: '#/components/schemas/Alteration' + - $ref: '#/components/schemas/Alteration' + - $ref: '#/components/schemas/Annual_report' + - $ref: '#/components/schemas/Change_of_address' + - $ref: '#/components/schemas/Change_of_directors' + - $ref: '#/components/schemas/Change_of_name' + - $ref: '#/components/schemas/Change_of_registration' + - $ref: '#/components/schemas/Conversion' + - $ref: '#/components/schemas/Court_order' + - $ref: '#/components/schemas/Correction' + - $ref: '#/components/schemas/Dissolution' + - $ref: '#/components/schemas/Incorporation_application' + - $ref: '#/components/schemas/Registrars_notation' + - $ref: '#/components/schemas/Registrars_order' + - $ref: '#/components/schemas/Registration' + - $ref: '#/components/schemas/Restoration' + - $ref: '#/components/schemas/Special_resolution' + - $ref: '#/components/schemas/Transition' + - $ref: '#/components/schemas/Unmanaged' + description: Submitting updates related to a business or incorporating/registering a new business. + required: + - header + Incorporation_application: + title: Incorporation Application Filing + type: object + description: Filing of Articles of Incorporation. The incorporation is to take effect at the time that the application is filed with the registrar. + x-examples: + Example 1: + incorporationApplication: + contactPoint: + email: abc.def@gov.bc.ca + phone: (250) 213-3412 + extension: 1234 + cooperative: + cooperativeAssociationType: Worker Cooperative + rulesFileKey: string + rulesFileName: string + memorandumFileKey: string + memorandumFileName: string + incorporationAgreement: + agreementType: Sample or custom + nameRequest: + nrNumber: string + legalType: string + legalName: string + requestType: Benefit Company Inc. + status: Expired + expires: '2019-08-24T14:15:22Z' + consent: string + submittedBy: string + address: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + nameTranslations: + - id: string + name: string + offices: + registeredOffice: + officeType: 'Head office ' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + recordsOffice: + officeType: 'Head office ' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + parties: + - party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Completing Party + officer: + givenName: string + familyName: string + additionalName: string + middleInitial: string + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + title: Chief Executive Officer + shareStructure: + resolutionDates: + - '2019-08-24' + shareClasses: + - name: string + priority: 0 + maxNumberOfShares: 0 + parValue: 0 + currency: string + hasMaximumShares: true + hasParValue: true + hasRightsOrRestrictions: true + series: + - name: string + priority: 0 + hasMaximumShares: true + hasRightsOrRestrictions: true + properties: + incorporationApplication: + type: object + description: Filing of Articles of Incorporation. The incorporation is to take effect at the time that the application is filed with the registrar. + required: + - contactPoint + - nameRequest + - offices + - parties + properties: + contactPoint: + $ref: '#/components/schemas/Contact_point' + cooperative: + $ref: '#/components/schemas/Cooperative' + incorporationAgreement: + $ref: '#/components/schemas/Agreement_type' + nameRequest: + $ref: '#/components/schemas/Name_request' + nameTranslations: + $ref: '#/components/schemas/Name_translations' + offices: + type: object + description: 'Addresses related to the business. ' + properties: + registeredOffice: + $ref: '#/components/schemas/Office' + recordsOffice: + $ref: '#/components/schemas/Office' + parties: + type: array + description: 'Persons having a role in the corporation eg: company officer.' + items: + $ref: '#/components/schemas/party' + shareStructure: + $ref: '#/components/schemas/Share_structure' + required: + - incorporationApplication + Filing_documents: + type: object + description: 'Documents submitted (uploaded) with filing. ' + x-examples: + Example 1: + documents: + certificate: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/BC0871331/filings/143690/documents/certificate' + legalFilings: + - incorporationApplication: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/BC0871331/filings/143690/documents/incorporationApplication' + noticeOfArticles: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/BC0871331/filings/143690/documents/noticeOfArticles' + receipt: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/BC0871331/filings/143690/documents/receipt' + properties: + documents: + type: object + description: Documents submitted (uploaded) with filing. + properties: + legalFilings: + type: array + description: 'Filings required by law. ' + items: + type: object + properties: + legalFilingNameKey: + type: string + format: uri + description: 'Name of legal filing. ' + example: '"http://example.com"' + receipt: + type: string + description: 'Confirmation of filing and payment completion. ' + Ledger: + type: array + x-examples: + example-1: + availableOnPaperOnly: false + businessIdentifier: CP0000840 + commentsCount: 3 + commentsLink: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/CP0000840/filings/112962/comments' + data: + applicationDate: '2021-10-19T07:00:00+00:00' + legalFilings: + - changeOfAddress + displayName: Address Change + documentsLink: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/CP0000840/filings/112962/documents' + effectiveDate: 'Tue, 19 Oct 2021 07:00:00 GMT' + filingId: 112962 + filingLink: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/CP0000840/filings/112962' + isFutureEffective: false + name: changeOfAddress + paymentStatusCode: COMPLETED + status: COMPLETED + submittedDate: 'Wed, 20 Oct 2021 17:55:05 GMT' + submitter: Registry Staff + items: + $ref: '#/components/schemas/Ledger_item' + description: 'Business record to summarize revenues and expenses of the business eg: common ledger for asset accounts.' + Ledger_item: + type: object + description: 'Ledger items track accounting items eg: assets, liabilities, capital, revenues, and expenses.' + x-examples: + Example 1: + availableOnPaperOnly: true + businessIdentifier: BC1234567 + commentsCount: 1 + commentsLink: 'http://example.com' + data: + applicationDate: '2019-08-24T14:15:22Z' + legalFilings: + - alteration + documentsLink: 'http://example.com' + displayName: Alteration info doc + effectiveDate: '2019-08-24T14:15:22Z' + filingId: 112962 + filingLink: 'https://legal-api-dev.apps.silver.devops.gov.bc.ca/api/v2/businesses/CP0000840/filings/112962' + name: changeOfAddress + isFutureEffective: true + paymentStatusCode: CREATED + status: COMPLETED + submittedDate: 'Wed, 20 Oct 2021 17:55:05 GMT' + submitter: Registry Staff + properties: + availableOnPaperOnly: + type: boolean + description: Yes if information only accessible on paper. + businessIdentifier: + type: string + minLength: 1 + description: 'Business idetifier eg: BC123456 or business number (BN9) BN123456789. ' + commentsCount: + type: number + description: 'Number of comments/notes posted for the ledger item. ' + commentsLink: + type: string + minLength: 1 + format: uri + description: URL related to comments for further details. + data: + type: object + required: + - applicationDate + - legalFilings + properties: + applicationDate: + type: string + format: date-time + minLength: 1 + description: Date the filing application was done. + legalFilings: + type: array + description: Filing that business is legally required to do. + items: + type: string + enum: + - alteration + - annualReport + - amalgamationApplication + - appointReceiver + - changeOfDirectors + - changeOfAddress + - changeOfName + - changeOfRegistration + - continuedOut + - conversion + - correction + - courtOrder + - dissolution + - dissolved + - incorporationApplication + - registration + - restoration + - specialResolution + - transition + - registrarsNotation + - registrarsOrder + documentsLink: + type: string + minLength: 1 + format: uri + description: 'Link for documents related to ledger. ' + displayName: + type: string + minLength: 1 + description: Name to be displayed for ledger item. + effectiveDate: + type: string + minLength: 1 + format: date-time + description: Date ledger item takes effect. + filingId: + type: number + description: 'Number identifying ledger item filing. ' + filingLink: + type: string + minLength: 1 + format: uri + description: 'Link related to ledger item filing. ' + name: + type: string + minLength: 1 + description: 'Name related to ledger item. ' + isFutureEffective: + type: boolean + description: Identify if ledger item filing effective date is further than the application date (yes/no). + paymentStatusCode: + type: string + minLength: 1 + description: 'Code indicating the state of the payment eg: Completed. ' + example: Completed + status: + type: string + minLength: 1 + description: 'Text describing the state of the ledger item. ' + submittedDate: + type: string + minLength: 1 + description: 'Date the ledger item was submitted. ' + submitter: + type: string + minLength: 1 + description: 'Name of the person submitting the ledger item. ' + required: + - availableOnPaperOnly + - businessIdentifier + - commentsCount + - commentsLink + - data + - documentsLink + - displayName + - effectiveDate + - filingId + - filingLink + - name + - isFutureEffective + - paymentStatusCode + - status + - submittedDate + - submitter + Naics: + type: object + title: NAICS Schema + description: NAICS is an abbreviation for The North American Industry Classification System and is a standard used to classify business activities. + properties: + naicsCode: + type: string + pattern: '^[0-9]{5,9}$' + description: 'Six digits unique identifier assigned to a business activity. ' + example: 32621 is the code for 'Tires Manufacturing' description + naicsDescription: + type: string + example: 32621 is the code for 'Tires Manufacturing' description + description: 'Description of the business activity linked to the NAICS code. ' + x-examples: + Example 1: + naicsCode: 32621 is the code for description 'Tires Manufacturing' + naicsDescription: '''Tires Manufacturing'' is the description for code 32621' + Name_request: + type: object + title: Name Request Schema + description: 'Filing requesting approval for a business name. ' + properties: + nrNumber: + type: string + maxLength: 10 + description: 'Unique number identifying the request. ' + legalType: + type: string + description: 'Type of business requesting name approval eg: Benefit Company.' + legalName: + type: string + description: 'Legal name requested for approval. ' + requestType: + type: string + title: The type of Name Request + example: Benefit Company Inc. + description: 'Representing the type of business and type of change eg: BC Benefit Company Change of Name.' + status: + type: string + description: 'Status of the request eg: completed.' + example: 'Expired ' + expires: + type: string + format: date-time + description: Date and time the request will be in 'expired' status. + consent: + type: string + description: Authorization to use the requested name. + submittedBy: + type: string + description: 'Name of the person submitting the request. ' + address: + $ref: '#/components/schemas/Address' + required: + - legalType + x-examples: + Example 1: + nrNumber: NR 0119514 + legalType: B.C. Company + legalName: JOHN SMITH COMPANY (LIMITED) + requestType: B.C. Company - Incorporation/Amalgamation + status: Completed + expires: '2019-08-24T14:15:22Z' + consent: 'NAME: consent to use name' + submittedBy: Registry Staff + address: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + Name_translations: + type: array + title: Name Translations Schema + description: 'Used when business name is to be translated. ' + x-examples: + Example 1: + - id: '1234' + name: Compagnie ABC + items: + type: object + properties: + id: + type: string + description: 'Name unique identifyer eg: 1234. ' + example: '1234' + name: + type: string + maxLength: 50 + title: Name Translation + pattern: '^[ A-Za-zÀ-ÿ_@./#’&+-]*$' + description: 'Text indicating name translation to be used. ' + required: + - name + Office: + title: Office Schema + type: object + description: 'Addresses related to the business. ' + properties: + officeType: + type: string + example: 'Head office ' + description: 'Type of office eg: registered office. ' + mailingAddress: + $ref: '#/components/schemas/Address' + deliveryAddress: + $ref: '#/components/schemas/Address' + x-examples: + Example 1: + officeType: Head office + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + party: + type: object + title: party + description: 'Represent a person and its role in relation to a business. ' + properties: + party: + type: object + description: 'Represent a person and its role in relation to a business. ' + properties: + taxId: + type: string + description: 'Company unique business number assigned by CRA: BN9 or BN15 eg: BN123456789.' + example: BN123456789 + roles: + type: array + description: 'Role of the person in relation to the business eg: director' + items: + $ref: '#/components/schemas/partyRole' + officer: + oneOf: + - $ref: '#/components/schemas/Person' + - $ref: '#/components/schemas/Business' + - $ref: '#/components/schemas/Business' + description: Officer is a key management executive of the business + deliveryAddress: + $ref: '#/components/schemas/Address' + mailingAddress: + $ref: '#/components/schemas/Address' + title: + type: string + example: Chief Executive Officer + description: 'Title of the party in relation to the business eg: Chief Executive Officer ' + required: + - roles + - officer + - mailingAddress + x-examples: + Example 1: + party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Officer + officer: + givenName: John + familyName: Smith + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + title: Chief Executive Officer + party - copy: + type: object + x-stoplight: + id: ee4nvid30gu0u + title: party + description: 'Represent a person and its role in relation to a business. ' + properties: + party: + type: object + description: 'Represent a person and its role in relation to a business. ' + properties: + taxId: + type: string + example: BN123456789 + description: 'Company unique business number assigned by CRA: BN9 or BN15 eg: BN123456789.' + roles: + type: array + description: 'Role of the person in relation to the business eg: director.' + items: + $ref: '#/components/schemas/partyRole' + officer: + oneOf: + - $ref: '#/components/schemas/Person' + - $ref: '#/components/schemas/Business' + - $ref: '#/components/schemas/Business' + description: Officer is a key management executive of the business + deliveryAddress: + $ref: '#/components/schemas/Address' + mailingAddress: + $ref: '#/components/schemas/Address' + title: + type: string + example: Chief Executive Officer + description: 'Title of the party in relation to the business eg: Chief Executive Officer.' + required: + - roles + - officer + - mailingAddress + x-examples: + Example 1: + party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Completing Party + officer: + givenName: John + familyName: smith + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + title: Chief Executive Officer + partyRole: + type: object + description: 'Role of the person in relation to the business eg: director.' + properties: + appointmentDate: + type: string + format: date + description: Date the person has been appointed to the role. + cessationDate: + type: string + format: date + description: Date the person's role has been terminated. + roleType: + type: string + enum: + - Completing Party + - Custodian + - Liquidator + - Director + - Incorporator + - Proprietor + - Partner + description: 'The role a person occupies in the business eg: officer.' + x-examples: + Example 1: + appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Director + Person: + type: object + title: Person Schema + description: 'An individual that is currently or had previously occupied a role in relation to a business. ' + properties: + givenName: + type: string + maxLength: 30 + description: First name of the individual. + familyName: + type: string + maxLength: 30 + description: Last name or surname of the individual. + additionalName: + type: string + title: 'An additional name for a Person, can be used for a middle name.' + maxLength: 30 + description: 'Other name used by the individual. ' + middleInitial: + type: string + maxLength: 30 + description: Initial of the individual's middle name. + taxId: + type: string + title: The CRA business number + pattern: '^[0-9]{9}$' + description: 'Company unique business number assigned by CRA: BN9 or BN15 ' + example: BN123456789 + email: + type: string + format: email + example: abc.def@gov.bc.ca + description: email address of the individual for contact information. + x-examples: + Example 1: + givenName: John + familyName: Smith + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + Registrars_notation: + title: Registrars Notation Information Schema + type: object + description: ' Notation regarding a registrar order.' + properties: + registrarsNotation: + type: object + required: + - orderDetails + properties: + fileNumber: + type: string + minLength: 0 + maxLength: 20 + description: The court assigns each court order a unique file number up to 20 characters in length. + orderDate: + type: string + description: The date and time of the order. + format: date-time + effectOfOrder: + type: string + minLength: 0 + maxLength: 500 + default: planOfArrangement + description: The effect that the order has on the business. + orderDetails: + type: string + minLength: 1 + maxLength: 2000 + description: A brief note to explain the purpose of the order. + required: + - registrarsNotation + x-examples: + Example 1: + registrarsNotation: + fileNumber: A1234 + orderDate: '2019-08-24T14:15:22Z' + effectOfOrder: planOfArrangement + orderDetails: Court order to process with liquidation of assets + Registrars_order: + type: object + title: Registrars Order Information Schema + properties: + registrarsOrder: + type: object + required: + - orderDetails + description: 'Order issued by the registrar eg: update an AGM date.' + properties: + fileNumber: + type: string + minLength: 0 + maxLength: 20 + description: Number identifying the registrar order. + orderDate: + type: string + description: The date and time of the order. + format: date-time + effectOfOrder: + type: string + minLength: 0 + maxLength: 500 + description: The effect the order will have on the business. + orderDetails: + type: string + minLength: 1 + maxLength: 2000 + description: A brief note to explain the purpose of the Order. + required: + - registrarsOrder + description: 'Order issued by the registrar eg: update an AGM date.' + x-examples: + Example 1: + registrarsOrder: + fileNumber: A1234 + orderDate: '2019-08-24T14:15:22Z' + effectOfOrder: Company will be dissolved + orderDetails: Order to proceed with company dissolution + Restoration: + title: Restoration Filing + type: object + description: 'Filing to request a company to be restored eg: after dissolution a company can apply for full or limited restoration.' + properties: + restoration: + type: object + required: + - date + - type + properties: + date: + type: string + format: date + description: Date the restoration request is filed. + type: + type: string + title: 'The Type of Restoration, such as Full Restoration, Limited Restoration, etc.' + enum: + - fullRestoration + - limitedRestoration + description: 'Type of restoration requested eg: limited, full.' + expiry: + title: The date the limited restoration is ends. + type: string + format: date + description: 'The date until which the restoration will be in effect: usually for limited restoration. ' + required: + - restoration + x-examples: + Example 1: + restoration: + date: '2019-08-24' + type: limitedRestoration + expiry: '2020-02-20' + Registration: + title: Registration Filing + type: object + description: 'Filing to register a business eg: sole proprietorship, general partnership.' + properties: + registration: + type: object + required: + - offices + - contactPoint + - startDate + - nameRequest + - parties + description: 'Filing to register a business eg: sole proprietorship, general partnership.' + properties: + business: + $ref: '#/components/schemas/Business' + offices: + type: object + description: 'Addresses related to the business eg: records office mailing address.' + properties: + businessOffice: + $ref: '#/components/schemas/Office' + businessType: + type: string + title: The business type of Sole Proprietorship (Doing Business As) Registration. + enum: + - SP + - DBA + description: 'Type of business to register eg: general partnership.' + contactPoint: + $ref: '#/components/schemas/Contact_point' + startDate: + type: string + format: date + description: 'The date the business operations start. ' + nameRequest: + $ref: '#/components/schemas/Name_request' + parties: + type: array + description: The persons related to the business and their role. + items: + $ref: '#/components/schemas/party' + courtOrder: + $ref: '#/components/schemas/Court_order' + required: + - registration + x-examples: + Example 1: + registration: + business: + lastLedgerTimestamp: '2020-11-24T18:24:27.179623+00:00' + fiscalYearEndDate: '2020-11-24' + dissolutionDate: '2020-11-24T18:23:53.498863+00:00' + foundingDate: '2020-11-24T18:23:53.498863+00:00' + identifier: 'BC1234567 is an identifier for a corporation ' + legalName: '1234567 B.C. Ltd. is a legal name for a corporation ' + state: ACTIVE + legalType: 'GP: General Partnership' + taxId: BN123456789 + goodStanding: true + adminFreeze: true + naics: + naicsCode: 32621 is the code for 'Tires Manufacturing' description + naicsDescription: 32621 is the code for 'Tires Manufacturing' description + natureOfBusiness: string + complianceWarnings: + - code: INVALID_LEGAL_STRUCTURE_DIRECTORS + message: INVALID_LEGAL_STRUCTURE_DIRECTORS + filing: '''https://LEGAL-API-HOST/api/v2/businesses/IDENTIFIER/filings/FILING_ID''' + offices: + businessOffice: + officeType: 'Head office ' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + businessType: SP + contactPoint: + email: abc.def@gov.bc.ca + phone: (555) 555-5555 + extension: 1234 + startDate: '2019-08-24' + nameRequest: + nrNumber: string + legalType: string + legalName: string + requestType: Benefit Company Inc. + status: 'Expired ' + expires: '2019-08-24T14:15:22Z' + consent: string + submittedBy: string + address: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + parties: + - party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2019-08-24' + roleType: Completing Party + officer: + givenName: string + familyName: string + additionalName: string + middleInitial: string + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our apartment is located at the back of the building."' + title: Chief Executive Officer + courtOrder: + courtOrder: + fileNumber: string + orderDate: '2019-08-24T14:15:22Z' + effectOfOrder: string + orderDetails: string + shareSeries: + type: object + description: Describe share structure of a company. + properties: + name: + type: string + title: The name of the share series. + description: 'Type of shares eg: general shares.' + priority: + type: integer + title: 'The display order that indicates priority. ' + description: Priority related to share type or class. + hasMaximumShares: + type: boolean + title: Has maximum number of shares? + description: If there is a maximum number of shares that the company can issue to the investors Yes/No. + hasRightsOrRestrictions: + type: boolean + title: Has special rights or restrictions? + description: 'If there are conditions to be met before the shares can be sold. ' + required: + - name + - priority + - hasMaximumShares + - hasRightsOrRestrictions + title: '' + x-examples: + Example 1: + name: convertible shares + priority: 100 + hasMaximumShares: true + hasRightsOrRestrictions: true + shareClass: + type: object + description: 'Designation that describes the different types of shares the company can issue, typically designated by letters of the alphabet, such as A or B. ' + x-examples: + Example 1: + name: Redeemable Shares + priority: 2 + maxNumberOfShares: 100 + parValue: 50 + currency: CAD + hasMaximumShares: true + hasParValue: true + hasRightsOrRestrictions: true + series: + - name: Redeemable Preference Shares + priority: 2 + hasMaximumShares: true + hasRightsOrRestrictions: true + properties: + name: + type: string + title: The name of the share class. + description: 'Type of shares eg: general shares.' + priority: + type: integer + title: 'The display order of the shares that indicates priority. ' + description: 'The display order that indicates priority eg: 2. with value 2, the share class will be displayed the second, after share class with priority 1. ' + example: 'Eg: with value 2, the share class will be displayed the second, after share class with priority 1. ' + maxNumberOfShares: + type: number + title: 'Maximum number of shares in the class. ' + description: The maximum number of shares that a corporation can issue to the investors called authorized shares. + parValue: + type: number + title: 'Initial value of each share. ' + description: 'The value of a single common share as set by a corporation''s charter. ' + currency: + type: string + description: The currency in which the Share is traded on the Exchange. + hasMaximumShares: + type: boolean + title: Has maximum number of shares? + description: 'If there is a maximum number of shares that the company can issue to the investors Yes/No. ' + hasParValue: + type: boolean + title: Has initial value of each share? + description: If company has Par Value defined in charter Yes/No. + hasRightsOrRestrictions: + type: boolean + title: Has special rights or restrictions? + description: 'If there are conditions to be met before the shares can be sold. ' + series: + type: array + description: A subdivision of a class of shares. If a corporation's articles permit shares of a class to be issued in one or more series. + items: + $ref: '#/components/schemas/shareSeries' + required: + - name + - priority + - maxNumberOfShares + - parValue + - currency + - hasMaximumShares + - hasParValue + - hasRightsOrRestrictions + Special_resolution: + type: object + title: Special Resolution Filing + description: 'Special resolutions are needed for certain changes as defined in the Corporations Act eg: decisions to change the company''s name. ' + properties: + specialResolution: + type: object + description: 'Special resolutions are needed for certain changes as defined in the Corporations Act eg: decisions to change the company''s name. ' + required: + - resolution + properties: + meetingDate: + type: string + format: date + description: 'Date of the meeting when the special resolution was adopted. ' + example: '2023-01-20' + resolution: + type: string + maxLength: 1000 + description: 'Description of the change that was adopted eg: amendments to memorandum and articles of association.' + resolutionDate: + type: string + format: date + description: Date the resolution is to take effect. + signingDate: + type: string + format: date + description: 'The date the resolution was authorized. ' + signatory: + $ref: '#/components/schemas/Person' + required: + - specialResolution + x-examples: + Example 1: + specialResolution: + meetingDate: '2023-01-20' + resolution: Issuance of preferred shares + resolutionDate: '2019-08-24' + signingDate: '2019-08-24' + signatory: + givenName: John + familyName: Smith + additionalName: Adam + middleInitial: A + taxId: BN123456789 + email: abc.def@gov.bc.ca + Share_structure: + type: object + title: Share Structure Schema + description: 'The type, series, and classes of shares that the company has been authorized. ' + properties: + resolutionDates: + type: array + description: 'The date the share structure of the company was adopted. ' + items: + type: string + format: date + shareClasses: + type: array + description: 'Designation that describes the different types of shares the company can issue, typically designated by letters of the alphabet, such as A or B. ' + items: + $ref: '#/components/schemas/shareClass' + required: + - shareClasses + x-examples: + Example 1: + resolutionDates: + - '2019-08-24' + shareClasses: + - name: Redeemable shares + priority: 2 + maxNumberOfShares: 100 + parValue: 50 + currency: CAD + hasMaximumShares: true + hasParValue: true + hasRightsOrRestrictions: true + series: + - name: Redeemable shares class A + priority: 2 + hasMaximumShares: true + hasRightsOrRestrictions: true + Suggestion_item: + type: object + description: '***Item not used*** A suggestion from an auto-search' + properties: + name: + type: string + description: Matching term + identifier: + type: string + BN: + type: string + target: + type: string + weight: + type: integer + description: The weight of the search term is scored by the matching algorithm against the search term provided. + title: '' + x-examples: + Example 1: + name: string + identifier: string + BN: '123456789' + target: string + weight: 0 + Suggestion_item - copy: + type: object + x-stoplight: + id: 21kymuins8gxo + description: A suggestion from an auto-search + properties: + name: + type: string + description: Matching term + identifier: + type: string + BN: + type: string + target: + type: string + weight: + type: integer + description: The weight of the search term is scored by the matching algorithm against the search term provided. + title: '' + Transition: + type: object + title: Transition Filing + description: Companies must file a Transition Application to update certain information that is on file with BC Registry. + properties: + transition: + type: object + description: Companies must file a Transition Application to update certain information that is on file with BC Registry. + required: + - offices + - parties + - shareStructure + - hasProvisions + properties: + nameTranslations: + $ref: '#/components/schemas/Name_translations' + offices: + type: object + description: Addresses related to the business. + properties: + registeredOffice: + $ref: '#/components/schemas/Office' + recordsOffice: + $ref: '#/components/schemas/Office' + parties: + type: array + description: 'Persons having a role in the company transition. ' + items: + $ref: '#/components/schemas/party' + shareStructure: + $ref: '#/components/schemas/Share_structure' + hasProvisions: + type: boolean + title: Has Pre-existing company provisions? + description: If the company has funds set aside to cover specific anticipated future expenses or other financial impacts Yes/No. + contactPoint: + $ref: '#/components/schemas/Contact_point' + required: + - transition + x-examples: + Example 1: + transition: + nameTranslations: + - id: string + name: string + offices: + registeredOffice: + officeType: Head office + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + deliveryAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: Building A + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + recordsOffice: + officeType: Records Office + mailingAddress: + streetAddress: 2-3342 Fort Street + streetAddressAdditional: Building C + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our office is located at the back of the building."' + deliveryAddress: + streetAddress: 311-1112 View Street + streetAddressAdditional: 3rd floor + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Receptopn is on 2nd floor."' + parties: + - party: + taxId: BN123456789 + roles: + - appointmentDate: '2019-08-24' + cessationDate: '2021-06-14' + roleType: Officer + officer: + givenName: Mary + familyName: Williams + additionalName: Lucy + middleInitial: L + taxId: BN123456789 + email: abc.def@gov.bc.ca + deliveryAddress: + streetAddress: 5-111 Bay Street + streetAddressAdditional: Building B + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located at the back of the building."' + mailingAddress: + streetAddress: 5-4761 Bay Street + streetAddressAdditional: string + addressCity: Victoria + addressRegion: 'BC for British Columbia ' + addressCountry: Canada + postalCode: V8R 2P1 + deliveryInstructions: '"Our unit is located in front of the building."' + title: Chief Executive Officer + shareStructure: + resolutionDates: + - '2019-08-24' + shareClasses: + - name: string + priority: 0 + maxNumberOfShares: 0 + parValue: 0 + currency: string + hasMaximumShares: true + hasParValue: true + hasRightsOrRestrictions: true + series: + - name: string + priority: 0 + hasMaximumShares: true + hasRightsOrRestrictions: true + hasProvisions: true + contactPoint: + email: abc.def@gov.bc.ca + phone: string + extension: 1234 + Unmanaged: + title: Unmanaged Filing + required: + - unmanaged + type: object + properties: + unManaged: + type: object + required: + - displayName + properties: + displayName: + type: string + title: Display name of the filing. + description: '***Item not used*** ' + securitySchemes: + api_key: + type: apiKey + description: API Gateway assigned API key for a consumer with the PPR API privilege. Required for all requests. + name: x-apikey + in: header + jwt: + type: oauth2 + flows: + password: + tokenUrl: '' + refreshUrl: '' + scopes: {} + description: '' + headers: + AccessControlAllowOrigin: + schema: + type: string + description: Access-Control-Allow-Origin + x-examples: + notify_1: + value: '' + AccessControlAllowMethods: + schema: + type: string + description: Access-Control-Allow-Methods + x-examples: + notify_1: + value: 'GET, PUT, POST, PATCH' + AccessControlAllowHeaders: + schema: + type: string + description: Access-Control-Allow-Headers + x-examples: + notify_1: + value: 'content-type, accept, x-apikey, authorization' + AccessControlMaxAge: + schema: + type: integer + description: Access-Control-Max-Age + x-examples: + notify_1: + value: 362880 + parameters: + accountId: + name: Account-Id + in: header + description: The account that the user is operating on behalf of. + required: true + schema: + type: string + example: '1234567' + identifier: + name: identifier + in: path + required: true + description: The unique identifier for the business or organization. + schema: + type: string + filingId: + name: filingId + in: path + required: true + description: The unique id of the filing + schema: + type: string + documentName: + name: documentName + in: path + required: true + description: The name of the legalName of the document. + schema: + type: string +tags: + - name: business + description: business services + - name: search + description: search services +security: + - api_key: [] From c39c1c1b4fe33b9d96ab2326c4e26b30aeb51e7b Mon Sep 17 00:00:00 2001 From: leodube-aot <122323255+leodube-aot@users.noreply.github.com> Date: Wed, 20 Mar 2024 15:10:53 -0700 Subject: [PATCH 004/113] 20320 Get entity-filer tests running (#2533) * Get unit tests running * Update pyproject.toml * Undo format changes to common migrations * Export BusinessCommon from common models --- .../business-registry-model/poetry.lock | 11 +- .../business-registry-model/pyproject.toml | 2 +- .../src/business_model/__init__.py | 6 + .../src/business_model/models/__init__.py | 2 + .../business_model/models/alternate_name.py | 260 +++- .../models/amalgamating_business.py | 2 +- .../src/business_model/models/amalgamation.py | 2 +- .../business_model/models/business_common.py | 272 ++++ .../src/business_model/models/colin_entity.py | 9 + .../business_model/models/dc_definition.py | 2 +- .../src/business_model/models/entity_role.py | 10 +- .../src/business_model/models/filing.py | 81 +- .../src/business_model/models/legal_entity.py | 424 +---- .../business_model/models/naics_element.py | 2 +- .../src/business_model/models/office.py | 2 + .../src/business_model/models/party.py | 4 +- .../models/registration_bootstrap.py | 2 +- .../business_model/models/request_tracker.py | 6 +- .../src/business_model/models/share_class.py | 2 +- .../src/business_model/models/share_series.py | 2 +- .../src/business_model/models/user.py | 4 +- .../src/business_model_migrations/env.py | 2 +- .../versions/004f7558063f_second.py | 1377 ++++++----------- .../versions/03201f7bc580_first.py | 15 +- .../versions/2fd104a5f3b5_.py | 6 +- .../versions/3d8eb786f4c2_add_sequences.py | 2 +- .../versions/4aed1fbbba29_.py | 6 +- .../versions/5238dd8fb805_.py | 143 ++ .../versions/60d9c14c2b7f_.py | 11 +- .../versions/9e36cf10f47c_.py | 16 +- .../versions/e7abbdeb252a_.py | 6 +- queue_services/entity-filer/poetry.lock | 42 +- queue_services/entity-filer/pyproject.toml | 3 +- .../entity-filer/src/entity_filer/config.py | 6 +- .../filing_processors/admin_freeze.py | 2 +- .../filing_processors/change_of_directors.py | 2 +- .../filing_processors/put_back_on.py | 2 +- queue_services/entity-filer/tests/conftest.py | 188 +-- .../entity-filer/tests/unit/__init__.py | 10 +- .../filing_components/test_business_info.py | 2 +- .../test_parties_entity_roles.py | 2 +- .../unit/filing_processors/test_alteration.py | 8 +- .../filing_processors/test_change_of_name.py | 4 +- .../filing_processors/test_dissolution.py | 4 +- .../tests/unit/worker/test_restoration.py | 2 +- 45 files changed, 1448 insertions(+), 1520 deletions(-) create mode 100644 python/common/business-registry-model/src/business_model/models/business_common.py create mode 100644 python/common/business-registry-model/src/business_model_migrations/versions/5238dd8fb805_.py diff --git a/python/common/business-registry-model/poetry.lock b/python/common/business-registry-model/poetry.lock index 9cadf11c34..86b1ac8b06 100644 --- a/python/common/business-registry-model/poetry.lock +++ b/python/common/business-registry-model/poetry.lock @@ -853,8 +853,8 @@ attrs = ">=22.2.0" rpds-py = ">=0.7.0" [[package]] -name = "registry-schemas" -version = "2.18.10" +name = "registry_schemas" +version = "2.18.19" description = "A short description of the project" optional = false python-versions = ">=3.6" @@ -864,14 +864,15 @@ develop = false [package.dependencies] flask = "*" jsonschema = {version = "*", extras = ["format"]} +referencing = "*" requests = "*" strict-rfc3339 = "*" [package.source] type = "git" url = "https://github.com/bcgov/business-schemas.git" -reference = "2.18.10" -resolved_reference = "9d341fe050bf7844905a3914380e71180d14d336" +reference = "2.18.19" +resolved_reference = "c9f4d10f33fdb14157573acac48945c6e7750f24" [[package]] name = "requests" @@ -1268,4 +1269,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "fe51aae29aee636caede34db3c599b8dee568357a69105a915dc31b21ff5ceb0" +content-hash = "9a898d957fb8d66e2928257df75a486a2ab1a7f79f164252f02d8610a6894962" diff --git a/python/common/business-registry-model/pyproject.toml b/python/common/business-registry-model/pyproject.toml index 542cd75264..5bd1808686 100644 --- a/python/common/business-registry-model/pyproject.toml +++ b/python/common/business-registry-model/pyproject.toml @@ -14,7 +14,7 @@ python = "^3.11" Flask-SQLAlchemy = "^3.0.5" pycountry = "^22.3.5" datedelta = "^1.4" -registry-schemas = {git = "https://github.com/bcgov/business-schemas.git", rev = "2.18.10"} +registry-schemas = {git = "https://github.com/bcgov/business-schemas.git", rev = "2.18.19"} ## sql-versioning = {path = "../sql-versioning"} sql-versioning = { git = "https://github.com/bcgov/lear.git", subdirectory = "python/common/sql-versioning", branch = "feature-legal-name" } diff --git a/python/common/business-registry-model/src/business_model/__init__.py b/python/common/business-registry-model/src/business_model/__init__.py index c68daad922..ad0451b9ad 100644 --- a/python/common/business-registry-model/src/business_model/__init__.py +++ b/python/common/business-registry-model/src/business_model/__init__.py @@ -36,6 +36,9 @@ from .models.address import Address from .models.alias import Alias from .models.alternate_name import AlternateName +from .models.amalgamating_business import AmalgamatingBusiness +from .models.amalgamation import Amalgamation +from .models.business_common import BusinessCommon from .models.colin_entity import ColinEntity from .models.colin_update import ColinLastUpdate from .models.comment import Comment @@ -68,6 +71,9 @@ "Address", "Alias", "AlternateName", + "AmalgamatingBusiness", + "Amalgamation", + "BusinessCommon", "ColinEntity", "ColinLastUpdate", "Comment", diff --git a/python/common/business-registry-model/src/business_model/models/__init__.py b/python/common/business-registry-model/src/business_model/models/__init__.py index fe9c30acc2..70c901a834 100644 --- a/python/common/business-registry-model/src/business_model/models/__init__.py +++ b/python/common/business-registry-model/src/business_model/models/__init__.py @@ -18,6 +18,7 @@ from .alternate_name import AlternateName from .amalgamating_business import AmalgamatingBusiness from .amalgamation import Amalgamation +from .business_common import BusinessCommon from .colin_entity import ColinEntity from .colin_update import ColinLastUpdate from .comment import Comment @@ -52,6 +53,7 @@ "Amalgamation", "Alias", "AlternateName", + "BusinessCommon", "ColinEntity", "LegalEntity", "ColinLastUpdate", diff --git a/python/common/business-registry-model/src/business_model/models/alternate_name.py b/python/common/business-registry-model/src/business_model/models/alternate_name.py index 434ebfbb71..d407de456e 100644 --- a/python/common/business-registry-model/src/business_model/models/alternate_name.py +++ b/python/common/business-registry-model/src/business_model/models/alternate_name.py @@ -14,37 +14,38 @@ """This module holds data for aliases.""" from __future__ import annotations -from legal_api.utils.datetime import datetime +from enum import auto + +from flask import current_app from sql_versioning import Versioned from sqlalchemy.dialects.postgresql import UUID -from ..utils.enum import BaseEnum, auto +from ..utils.enum import BaseEnum +from ..utils.datetime import datetime +from ..utils.legislation_datetime import LegislationDatetime +from .address import Address # noqa: F401,I003 pylint: disable=unused-import; needed by the SQLAlchemy relationship +from .business_common import BusinessCommon from .db import db +from .office import Office # noqa: F401 pylint: disable=unused-import; needed by the SQLAlchemy relationship -class AlternateName(Versioned, db.Model): +# pylint: disable=import-outside-toplevel +class AlternateName(Versioned, db.Model, BusinessCommon): """This class manages the alternate names.""" class EntityType(BaseEnum): """Render an Enum of the types of aliases.""" DBA = "DBA" - SP = "DBA" - GP = "DBA" + SP = "SP" + GP = "GP" class NameType(BaseEnum): """Enum for the name type.""" - OPERATING = auto() + DBA = auto() TRANSLATION = auto() - class State(BaseEnum): - """Enum for the Business state.""" - - ACTIVE = auto() - HISTORICAL = auto() - LIQUIDATION = auto() - __tablename__ = "alternate_names" __mapper_args__ = { "include_properties": [ @@ -54,6 +55,7 @@ class State(BaseEnum): "end_date", "identifier", "legal_entity_id", + "colin_entity_id", "name", "name_type", "start_date", @@ -66,6 +68,9 @@ class State(BaseEnum): "state_filing_id", "admin_freeze", "last_modified", + "email", + "delivery_address_id", + "mailing_address_id", ] } @@ -81,19 +86,28 @@ class State(BaseEnum): naics_description = db.Column("naics_description", db.String(300), nullable=True) business_start_date = db.Column("business_start_date", db.DateTime(timezone=True), default=datetime.utcnow) dissolution_date = db.Column("dissolution_date", db.DateTime(timezone=True), default=None) - state = db.Column("state", db.Enum(State), default=State.ACTIVE.value) + state = db.Column("state", db.Enum(BusinessCommon.State), default=BusinessCommon.State.ACTIVE) admin_freeze = db.Column("admin_freeze", db.Boolean, unique=False, default=False) last_modified = db.Column("last_modified", db.DateTime(timezone=True), default=datetime.utcnow) + email = db.Column("email", db.String(254), nullable=True) + delivery_address_id = db.Column("delivery_address_id", db.Integer, db.ForeignKey("addresses.id")) + mailing_address_id = db.Column("mailing_address_id", db.Integer, db.ForeignKey("addresses.id")) # parent keys legal_entity_id = db.Column("legal_entity_id", db.Integer, db.ForeignKey("legal_entities.id")) + colin_entity_id = db.Column("colin_entity_id", db.Integer, db.ForeignKey("colin_entities.id")) change_filing_id = db.Column("change_filing_id", db.Integer, db.ForeignKey("filings.id"), index=True) state_filing_id = db.Column("state_filing_id", db.Integer, db.ForeignKey("filings.id")) # relationships legal_entity = db.relationship("LegalEntity", back_populates="alternate_names") + colin_entity = db.relationship("ColinEntity", back_populates="alternate_names") filings = db.relationship("Filing", lazy="dynamic", foreign_keys="Filing.alternate_name_id") documents = db.relationship("Document", lazy="dynamic") + offices = db.relationship("Office", lazy="dynamic", cascade="all, delete, delete-orphan") + + owner_delivery_address = db.relationship("Address", foreign_keys=[delivery_address_id]) + owner_mailing_address = db.relationship("Address", foreign_keys=[mailing_address_id]) @classmethod def find_by_identifier(cls, identifier: str) -> AlternateName | None: @@ -101,6 +115,12 @@ def find_by_identifier(cls, identifier: str) -> AlternateName | None: alternate_name = cls.query.filter_by(identifier=identifier).one_or_none() return alternate_name + @classmethod + def find_by_internal_id(cls, internal_id: int) -> AlternateName | None: + """Return None or the AlternateName found by the internal id.""" + alternate_name = cls.query.filter_by(id=internal_id).one_or_none() + return alternate_name + @classmethod def find_by_name(cls, name: str = None): """Given a name, this will return an AlternateName.""" @@ -109,7 +129,219 @@ def find_by_name(cls, name: str = None): alternate_name = cls.query.filter_by(name=name).filter_by(end_date=None).one_or_none() return alternate_name + @classmethod + def find_by_id(cls, id: int = None): # pylint: disable=W0622 + """Given a name, this will return an AlternateName.""" + if not id: + return None + alternate_name = cls.query.filter_by(id=id).one_or_none() + return alternate_name + + @classmethod + def find_by_name_type(cls, legal_entity_id: int, name_type: str): + """Return the aliases matching the type.""" + if name_type not in [nt.name for nt in AlternateName.NameType]: + return [] + + aliases = ( + db.session.query(AlternateName) + .filter(AlternateName.legal_entity_id == legal_entity_id) + .filter(AlternateName.name_type == name_type) + .all() + ) + return aliases + + @property + def office_mailing_address(self): + """Return the mailing address.""" + if ( + business_office := db.session.query(Office) # SP/GP + .filter(Office.alternate_name_id == self.id) + .filter(Office.office_type == "businessOffice") + .one_or_none() + ): + return business_office.addresses.filter(Address.address_type == "mailing") + + return ( + db.session.query(Address) + .filter(Address.alternate_name_id == self.id) + .filter(Address.address_type == Address.MAILING) + ) + + @property + def office_delivery_address(self): + """Return the delivery address.""" + if ( + business_office := db.session.query(Office) # SP/GP + .filter(Office.alternate_name_id == self.id) + .filter(Office.office_type == "businessOffice") + .one_or_none() + ): + return business_office.addresses.filter(Address.address_type == "delivery") + + return ( + db.session.query(Address) + .filter(Address.alternate_name_id == self.id) + .filter(Address.address_type == Address.DELIVERY) + ) + + @property + def is_owned_by_legal_entity_person(self): + """Return if owned by LE person.""" + return bool(self.legal_entity) and self.legal_entity.entity_type == BusinessCommon.EntityTypes.PERSON.value + + @property + def is_owned_by_legal_entity_org(self): + """Return if owned by LE org.""" + return bool(self.legal_entity) and self.legal_entity.entity_type not in BusinessCommon.NON_BUSINESS_ENTITY_TYPES + + @property + def is_owned_by_colin_entity(self): + """Return if owned by colin entity.""" + return bool(self.colin_entity) + + @property + def owner_data_json(self): + """Return if owner data for SP only.""" + json = { + "deliveryAddress": None, + "mailingAddress": None, + "officer": {}, + "roles": [ + { + "appointmentDate": datetime.date(self.start_date).isoformat(), + "cessationDate": None, + "roleType": "Proprietor", + } + ], + } + + delivery_address = None + mailing_address = None + + if self.is_owned_by_legal_entity_person: + delivery_address = self.legal_entity.entity_delivery_address + mailing_address = self.legal_entity.entity_mailing_address + else: + delivery_address = self.owner_delivery_address + mailing_address = self.owner_mailing_address + + if delivery_address: + member_address = delivery_address.json + if "addressType" in member_address: + del member_address["addressType"] + json["deliveryAddress"] = member_address + if mailing_address: + member_mailing_address = mailing_address.json + if "addressType" in member_mailing_address: + del member_mailing_address["addressType"] + json["mailingAddress"] = member_mailing_address + else: + if delivery_address: + json["mailingAddress"] = json["deliveryAddress"] + + if self.is_owned_by_legal_entity_person: + json["officer"] = { + "id": self.legal_entity.id, + "email": self.legal_entity.email, + "firstName": self.legal_entity.first_name, + "lastName": self.legal_entity.last_name, + "middleInitial": self.legal_entity.middle_initial, + "partyType": "person", + } + elif self.is_owned_by_legal_entity_org: + json["officer"] = { + "id": self.legal_entity.id, + "email": self.legal_entity.email, + "identifier": self.legal_entity.identifier, + "organizationName": self.legal_name, + "partyType": "organization", + } + elif self.is_owned_by_colin_entity: + json["officer"] = { + "id": self.colin_entity.id, + "email": self.colin_entity.email, + "identifier": self.colin_entity.identifier, + "organizationName": self.legal_name, + "partyType": "organization", + } + + return json + def save(self): """Save the object to the database immediately.""" db.session.add(self) db.session.commit() + + @property + def alias_json(self): + """Return the Alias as a json object.""" + alias = {"id": str(self.id), "name": self.name, "type": self.name_type.name} + return alias + + def json(self, slim=False): + """Return the Business as a json object. + None fields are not included. + """ + # TODO flesh out json fully once all additional columns added to this model + slim_json = self._slim_json() + if slim: + return slim_json + + d = { + **slim_json, + "complianceWarnings": self.compliance_warnings, + "warnings": self.warnings, + "foundingDate": self.start_date.isoformat(), + "lastModified": self.last_modified.isoformat(), + "naicsKey": self.naics_key, + "naicsCode": self.naics_code, + "naicsDescription": self.naics_description, + "allowedActions": self.allowable_actions, + } + self._extend_json(d) + + return d + + def _slim_json(self): + """Return a smaller/faster version of the business json.""" + d = { + "adminFreeze": self.admin_freeze or False, + "goodStanding": True, + "identifier": self.identifier, + "legalName": self.legal_name, + "legalType": self.entity_type, + "state": self.state.name, + "alternateNames": [ + { + "entityType": self.entity_type, + "identifier": self.identifier, + "name": self.name, + "nameRegisteredDate": self.start_date.isoformat(), + "nameStartDate": LegislationDatetime.format_as_legislation_date(self.business_start_date) + if self.business_start_date + else None, + "nameType": self.name_type.name, + "operatingName": self.name, # will be removed in the future + } + ], + } + return d + + def _extend_json(self, d): + """Include conditional fields to json.""" + from ..models import Filing + + base_url = current_app.config.get("LEGAL_API_BASE_URL") + + if self.dissolution_date: + d["dissolutionDate"] = LegislationDatetime.format_as_legislation_date(self.dissolution_date) + + if self.state_filing_id: + d["stateFiling"] = f"{base_url}/{self.identifier}/filings/{self.state_filing_id}" + + if self.business_start_date: + d["startDate"] = LegislationDatetime.format_as_legislation_date(self.business_start_date) + + d["hasCorrections"] = Filing.has_completed_filing(self, "correction") + d["hasCourtOrders"] = Filing.has_completed_filing(self, "courtOrder") diff --git a/python/common/business-registry-model/src/business_model/models/amalgamating_business.py b/python/common/business-registry-model/src/business_model/models/amalgamating_business.py index 482881d079..0b7fdf887d 100644 --- a/python/common/business-registry-model/src/business_model/models/amalgamating_business.py +++ b/python/common/business-registry-model/src/business_model/models/amalgamating_business.py @@ -18,7 +18,7 @@ from enum import auto -from ..utils.base import BaseEnum +from ..utils.enum import BaseEnum from .db import db diff --git a/python/common/business-registry-model/src/business_model/models/amalgamation.py b/python/common/business-registry-model/src/business_model/models/amalgamation.py index 387c42d02d..36eb389d52 100644 --- a/python/common/business-registry-model/src/business_model/models/amalgamation.py +++ b/python/common/business-registry-model/src/business_model/models/amalgamation.py @@ -19,7 +19,7 @@ from enum import auto -from ..utils.base import BaseEnum +from ..utils.enum import BaseEnum from .db import db diff --git a/python/common/business-registry-model/src/business_model/models/business_common.py b/python/common/business-registry-model/src/business_model/models/business_common.py new file mode 100644 index 0000000000..bfd2f559e6 --- /dev/null +++ b/python/common/business-registry-model/src/business_model/models/business_common.py @@ -0,0 +1,272 @@ +# Copyright © 2021 Province of British Columbia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License +"""The business and its historical values. +This is the core business class. +It is used to represent a business and its historical values. +""" +from enum import Enum, auto +from typing import Final + +import datedelta +from sql_versioning import history_cls + +from ..utils.enum import BaseEnum +from ..utils.datetime import datetime + +from .db import db + + +# pylint: disable=no-member,import-outside-toplevel,protected-access +class BusinessCommon: + """This class is used to share common properties and functions between LegalEntity and AlternateName.""" + + class State(BaseEnum): + """Enum for the Business state.""" + + ACTIVE = auto() + HISTORICAL = auto() + + # NB: commented out items that exist in namex but are not yet supported by Lear + class EntityTypes(str, Enum): + """Render an Enum of the Business Legal Types.""" + + BCOMP = "BEN" # aka BENEFIT_COMPANY in namex + BC_CCC = "CC" + BC_ULC_COMPANY = "ULC" + CCC_CONTINUE_IN = "CCC" + CEMETARY = "CEM" + CO_1860 = "QA" + CO_1862 = "QB" + CO_1878 = "QC" + CO_1890 = "QD" + CO_1897 = "QE" + COMP = "BC" # aka CORPORATION in namex + CONT_IN_SOCIETY = "CS" + CONTINUE_IN = "C" + COOP = "CP" # aka COOPERATIVE in namex + EXTRA_PRO_A = "A" + EXTRA_PRO_B = "B" + EXTRA_PRO_REG = "EPR" + FINANCIAL = "FI" + FOREIGN = "FOR" + LIBRARY = "LIB" + LICENSED = "LIC" + LIM_PARTNERSHIP = "LP" + LIMITED_CO = "LLC" + LL_PARTNERSHIP = "LL" + MISC_FIRM = "MF" + ORGANIZATION = "organization" + PARISHES = "PAR" + PARTNERSHIP = "GP" + PENS_FUND_SOC = "PFS" + PERSON = "person" + PRIVATE_ACT = "PA" + RAILWAYS = "RLY" + REGISTRATION = "REG" + SOCIETY = "S" + SOCIETY_BRANCH = "SB" + SOLE_PROP = "SP" + TRAMWAYS = "TMY" + TRUST = "T" + ULC_CONTINUE_IN = "CUL" + ULC_CO_1860 = "UQA" + ULC_CO_1862 = "UQB" + ULC_CO_1878 = "UQC" + ULC_CO_1890 = "UQD" + ULC_CO_1897 = "UQE" + XPRO_COOP = "XCP" + XPRO_LIM_PARTNR = "XP" + XPRO_LL_PARTNR = "XL" + XPRO_SOCIETY = "XS" + # *** The following are not yet supported by legal-api: *** + # DOING_BUSINESS_AS = 'DBA' + # XPRO_CORPORATION = 'XCR' + # XPRO_UNLIMITED_LIABILITY_COMPANY = 'XUL' + + LIMITED_COMPANIES: Final = [ + EntityTypes.COMP, + EntityTypes.CONTINUE_IN, + EntityTypes.CO_1860, + EntityTypes.CO_1862, + EntityTypes.CO_1878, + EntityTypes.CO_1890, + EntityTypes.CO_1897, + ] + + UNLIMITED_COMPANIES: Final = [ + EntityTypes.BC_ULC_COMPANY, + EntityTypes.ULC_CONTINUE_IN, + EntityTypes.ULC_CO_1860, + EntityTypes.ULC_CO_1862, + EntityTypes.ULC_CO_1878, + EntityTypes.ULC_CO_1890, + EntityTypes.ULC_CO_1897, + ] + + NON_BUSINESS_ENTITY_TYPES: Final = [EntityTypes.PERSON, EntityTypes.ORGANIZATION] + + @property + def is_alternate_name_entity(self): + """Return True if the entity is an AlternateName.""" + from ..models import AlternateName + + return isinstance(self, (AlternateName, history_cls(AlternateName))) + + @property + def is_legal_entity(self): + """Return True if the entity is a LegalEntity.""" + from ..models import LegalEntity + + return isinstance(self, (LegalEntity, history_cls(LegalEntity))) + + @property + def entity_type(self): + """Return entity_type.""" + from ..models import AlternateName + + if self.is_legal_entity: + return self._entity_type + + if self.is_alternate_name_entity and self.name_type.value == AlternateName.NameType.DBA: + return self.EntityTypes.SOLE_PROP.value + + return None + + @property + def compliance_warnings(self): + """Return compliance warnings.""" + if not hasattr(self, "_compliance_warnings"): + return [] + + return self._compliance_warnings + + @compliance_warnings.setter + def compliance_warnings(self, value): + """Set compliance warnings.""" + self._compliance_warnings = value + + @property + def warnings(self): + """Return warnings.""" + if not hasattr(self, "_warnings"): + return [] + + return self._warnings + + @warnings.setter + def warnings(self, value): + """Set warnings.""" + self._warnings = value + + @property + def allowable_actions(self): + """Return warnings.""" + if not hasattr(self, "_allowable_actions"): + return {} + + return self._allowable_actions + + @allowable_actions.setter + def allowable_actions(self, value): + """Set warnings.""" + self._allowable_actions = value + + @property + def is_firm(self): + """Return if is firm, otherwise false.""" + return self.entity_type in [ + self.EntityTypes.SOLE_PROP.value, + self.EntityTypes.PARTNERSHIP.value, + ] + + @property + def legal_name(self): + """Return legal name. + For SP individual, return person LE's legal name. + For SP DBA where owner is in LEAR, return firm owner LE's legal name. + For SP DBA where owner is in COLIN, return firm owner's CE's organization name. + For others, return LE's legal name. + """ + from . import ColinEntity, LegalEntity + + if self.entity_type == self.EntityTypes.SOLE_PROP: + if self.legal_entity_id: + owner = LegalEntity.find_by_id(self.legal_entity_id) + return owner._legal_name if owner else None + else: + owner = ColinEntity.find_by_id(self.colin_entity_id) + return owner.organization_name if owner else None + + return self._legal_name + + @property + def business_name(self): + """Return operating name for firms and legal name for non-firm entities. + + For SP, returns its operating name from AlternateName. + For GP, returns its primary operating name from AlternateName. + """ + from ..models import AlternateName + + if not self.is_firm: + return self._legal_name + + if self.is_alternate_name_entity and ( + alternate_name := AlternateName.find_by_identifier(identifier=self.identifier) + ): + return alternate_name.name + + return None + + @property + def good_standing(self): + """Return true if in good standing, otherwise false.""" + # A firm is always in good standing + # from ..models import LegalEntity + + if self.is_firm: + return True + # Date of last AR or founding date if they haven't yet filed one + last_ar_date = self.last_ar_date or self.founding_date + # Good standing is if last AR was filed within the past 1 year, 2 months and 1 day and is in an active state + if self.state == BusinessCommon.State.ACTIVE: + if self.restoration_expiry_date: + return False # A business in limited restoration is not in good standing + else: + return last_ar_date + datedelta.datedelta(years=1, months=2, days=1) > datetime.utcnow() + return True + + def get_filing_by_id(self, filing_id: int): + """Return the filings for a specific business and filing_id.""" + from ..models import AlternateName, Filing, LegalEntity + + # Determine the model to query based on is_legal_entity property + if self.is_legal_entity: + entity_model = LegalEntity + filing_filter = LegalEntity.id == Filing.legal_entity_id + entity_filter = LegalEntity.id == self.id + else: + entity_model = AlternateName + filing_filter = AlternateName.id == Filing.alternate_name_id + entity_filter = AlternateName.id == self.id + + filing = ( + db.session.query(entity_model, Filing) + .filter(filing_filter) + .filter(Filing.id == filing_id) + .filter(entity_filter) + .one_or_none() + ) + + return None if not filing else filing[1] diff --git a/python/common/business-registry-model/src/business_model/models/colin_entity.py b/python/common/business-registry-model/src/business_model/models/colin_entity.py index 1c2ea4fc1a..4de82c8c4b 100644 --- a/python/common/business-registry-model/src/business_model/models/colin_entity.py +++ b/python/common/business-registry-model/src/business_model/models/colin_entity.py @@ -46,6 +46,7 @@ class ColinEntity(Versioned, db.Model): mailing_address_id = db.Column("mailing_address_id", db.Integer, db.ForeignKey("addresses.id")) # relationships + alternate_names = db.relationship("AlternateName", back_populates="colin_entity", lazy="dynamic") delivery_address = db.relationship("Address", foreign_keys=[delivery_address_id]) mailing_address = db.relationship("Address", foreign_keys=[mailing_address_id]) @@ -57,6 +58,14 @@ def find_by_identifier(cls, identifier: str = None): colin_entity = cls.query.filter_by(identifier=identifier).one_or_none() return colin_entity + @classmethod + def find_by_id(cls, colin_entity_id: int): + """Return a colin entity by the internal id.""" + colin_entity = None + if colin_entity_id: + colin_entity = cls.query.filter_by(id=colin_entity_id).one_or_none() + return colin_entity + def save(self): """Save the object to the database immediately.""" db.session.add(self) diff --git a/python/common/business-registry-model/src/business_model/models/dc_definition.py b/python/common/business-registry-model/src/business_model/models/dc_definition.py index b1f2fac3ec..acec7e91dc 100644 --- a/python/common/business-registry-model/src/business_model/models/dc_definition.py +++ b/python/common/business-registry-model/src/business_model/models/dc_definition.py @@ -14,7 +14,7 @@ """This module holds data for digital credentials schema and credential definition.""" from __future__ import annotations -from legal_api.utils.enum import BaseEnum, auto +from ..utils.enum import BaseEnum, auto from sqlalchemy import text from .db import db diff --git a/python/common/business-registry-model/src/business_model/models/entity_role.py b/python/common/business-registry-model/src/business_model/models/entity_role.py index ac35387edf..18094ce2f4 100644 --- a/python/common/business-registry-model/src/business_model/models/entity_role.py +++ b/python/common/business-registry-model/src/business_model/models/entity_role.py @@ -180,7 +180,7 @@ def find_party_by_name( org_name: str, ): """Return a Party connected to the given legal_entity_id by the given name.""" - from legal_api.models import ColinEntity, LegalEntity + from ..models import ColinEntity, LegalEntity party = None @@ -360,7 +360,7 @@ def is_related_colin_entity(self): @property def is_related_person(self): """Return if entity role is for individual entity in legal_entities table.""" - from legal_api.models import LegalEntity + from ..models import LegalEntity if self.related_entity_id and self.related_entity.entity_type == LegalEntity.EntityTypes.PERSON.value: return True @@ -370,7 +370,7 @@ def is_related_person(self): @property def is_related_organization(self): """Return if entity role is a business in legal_entities table.""" - from legal_api.models import LegalEntity + from ..models import LegalEntity if self.related_entity_id and self.related_entity.entity_type != LegalEntity.EntityTypes.PERSON.value: return True @@ -385,7 +385,7 @@ def is_filing_colin_entity(self): @property def is_filing_related_person(self): """Return if entity role is for individual entity in legal_entities table.""" - from legal_api.models import LegalEntity + from ..models import LegalEntity if ( self.filing_id @@ -399,7 +399,7 @@ def is_filing_related_person(self): @property def is_filing_related_organization(self): """Return if entity role is a business in legal_entities table.""" - from legal_api.models import LegalEntity + from ..models import LegalEntity if ( self.filing_id diff --git a/python/common/business-registry-model/src/business_model/models/filing.py b/python/common/business-registry-model/src/business_model/models/filing.py index 1534b2e783..25d81d71c2 100644 --- a/python/common/business-registry-model/src/business_model/models/filing.py +++ b/python/common/business-registry-model/src/business_model/models/filing.py @@ -15,15 +15,15 @@ from http import HTTPStatus from typing import Final, List -from legal_api.exceptions import BusinessException -from legal_api.models.colin_event_id import ColinEventId -from legal_api.schemas import rsbc_schemas -from legal_api.utils.util import build_schema_error_response from sqlalchemy import and_, desc, event, func, inspect, not_, or_, select from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import backref +from ..exceptions import BusinessException +from ..models.colin_event_id import ColinEventId +from ..schemas import rsbc_schemas, build_schema_error_response + from .comment import Comment # noqa: I001,F401,I003 pylint: disable=unused-import; needed by SQLAlchemy relationship from .db import db # noqa: I001 @@ -38,7 +38,8 @@ class DissolutionTypes(str, Enum): # pylint: disable=too-many-lines VOLUNTARY_LIQUIDATION = "voluntaryLiquidation" -class Filing(db.Model): # pylint: disable=too-many-instance-attributes,too-many-public-methods +# pylint: disable=too-many-instance-attributes,too-many-public-methods,protected-access +class Filing(db.Model): # allowing the model to be deep. """Immutable filing record. @@ -424,7 +425,9 @@ class FilingTypes(str, Enum): comments = db.relationship("Comment", lazy="dynamic") documents = db.relationship("Document", lazy="dynamic") - filing_entity_roles = db.relationship("EntityRole", lazy="dynamic", primaryjoin="(Filing.id==EntityRole.filing_id)") + filing_entity_roles = db.relationship( + "EntityRole", lazy="dynamic", primaryjoin="(Filing.id==EntityRole.filing_id)", overlaps="filing" + ) # FUTURE: parent_filing_id and parent_filing should no longer be used for correction filings and will be removed parent_filing_id = db.Column(db.Integer, db.ForeignKey("filings.id")) @@ -602,8 +605,10 @@ def set_processed(self, business_type): if not self.effective_date_can_be_before_payment_completion_date(business_type) and ( self.effective_date is None or ( - self.payment_completion_date and self.effective_date < self.payment_completion_date - ) # pylint: disable=W0143; hybrid property # noqa: E501 + self.payment_completion_date + and self.effective_date # pylint: disable=W0143 + < self.payment_completion_date # pylint: disable=W0143; hybrid property # noqa: E501 + ) ): self.effective_date = self.payment_completion_date @@ -654,7 +659,7 @@ def comments_count(self): def comments_count(self): """Return comments count expression for this filing.""" return ( - select([func.count(Comment.legal_entity_id)]) + select([func.count(Comment.legal_entity_id)]) # pylint: disable=not-callable .where(Comment.legal_entity_id == self.id) .label("comments_count") ) @@ -729,11 +734,12 @@ def get_filing_by_payment_token(token: str): return filing @staticmethod - def get_filings_by_status(legal_entity_id: int, status: list, after_date: date = None): + def get_filings_by_status(business: any, status: list, after_date: date = None): """Return the filings with statuses in the status array input.""" + business_attr = Filing.alternate_name_id if business.is_alternate_name_entity else Filing.legal_entity_id query = ( db.session.query(Filing) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attr == business.id) .filter(Filing._status.in_(status)) .order_by(Filing._filing_date.desc(), Filing.effective_date.desc()) ) # pylint: disable=no-member; @@ -745,11 +751,12 @@ def get_filings_by_status(legal_entity_id: int, status: list, after_date: date = return query.all() @staticmethod - def get_incomplete_filings_by_type(legal_entity_id: int, filing_type: str): + def get_incomplete_filings_by_type(business: any, filing_type: str): """Return the incomplete filings of a particular type.""" + business_attr = Filing.alternate_name_id if business.is_alternate_name_entity else Filing.legal_entity_id filings = ( db.session.query(Filing) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attr == business.id) .filter(Filing._filing_type == filing_type) .filter(Filing._status != Filing.Status.COMPLETED.value) .order_by(desc(Filing.filing_date)) @@ -758,11 +765,12 @@ def get_incomplete_filings_by_type(legal_entity_id: int, filing_type: str): return filings @staticmethod - def get_filings_by_types(legal_entity_id: int, filing_types): + def get_filings_by_types(business: any, filing_types): """Return the completed filings of a particular type.""" + business_attr = Filing.alternate_name_id if business.is_alternate_name_entity else Filing.legal_entity_id filings = ( db.session.query(Filing) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attr == business.id) .filter(Filing._filing_type.in_(filing_types)) .filter(Filing._status == Filing.Status.COMPLETED.value) .order_by(desc(Filing.effective_date)) @@ -771,16 +779,17 @@ def get_filings_by_types(legal_entity_id: int, filing_types): return filings @staticmethod - def get_incomplete_filings_by_types(legal_entity_id: int, filing_types: list, excluded_statuses: list = None): + def get_incomplete_filings_by_types(business: any, filing_types: list, excluded_statuses: list = None): """Return the filings of particular types and statuses. excluded_statuses is a list of filing statuses that will be excluded from the query for incomplete filings """ excluded_statuses = [] if excluded_statuses is None else excluded_statuses + business_attr = Filing.alternate_name_id if business.is_alternate_name_entity else Filing.legal_entity_id filings = ( db.session.query(Filing) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attr == business.id) .filter(Filing._filing_type.in_(filing_types)) .filter(Filing._status != Filing.Status.COMPLETED.value) .filter(not_(Filing._status.in_(excluded_statuses))) @@ -791,7 +800,7 @@ def get_incomplete_filings_by_types(legal_entity_id: int, filing_types: list, ex @staticmethod def get_filings_by_type_pairs( - legal_entity_id: int, + business: any, filing_type_pairs: list, status: list, return_unique_pairs=False, @@ -800,6 +809,7 @@ def get_filings_by_type_pairs( If return_unique_pairs is True, only return one instance of each filing type/sub-type pair. """ + business_attr = Filing.alternate_name_id if business.is_alternate_name_entity else Filing.legal_entity_id filing_type_conditions = [ and_( Filing._filing_type == filing_type, @@ -810,7 +820,7 @@ def get_filings_by_type_pairs( base_query = ( db.session.query(Filing) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attr == business.id) .filter(Filing._status.in_(status)) .filter(or_(*filing_type_conditions)) ) @@ -834,14 +844,13 @@ def get_filings_by_type_pairs( return filings @staticmethod - def get_a_businesses_most_recent_filing_of_a_type( - legal_entity_id: int, filing_type: str, filing_sub_type: str = None - ): + def get_a_businesses_most_recent_filing_of_a_type(business: any, filing_type: str, filing_sub_type: str = None): """Return the filings of a particular type.""" + business_attr = Filing.alternate_name_id if business.is_alternate_name_entity else Filing.legal_entity_id max_filing = ( db.session.query(db.func.max(Filing._filing_date).label("last_filing_date")) .filter(Filing._filing_type == filing_type) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attr == business.id) ) if filing_sub_type: max_filing = max_filing.filter(Filing._filing_sub_type == filing_sub_type) @@ -849,7 +858,7 @@ def get_a_businesses_most_recent_filing_of_a_type( filing = ( Filing.query.join(max_filing, Filing._filing_date == max_filing.c.last_filing_date) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attr == business.id) .filter(Filing._filing_type == filing_type) .filter(Filing._status == Filing.Status.COMPLETED.value) ) @@ -859,11 +868,13 @@ def get_a_businesses_most_recent_filing_of_a_type( return filing.one_or_none() @staticmethod - def get_most_recent_legal_filing(legal_entity_id: str, filing_type: str = None): + def get_most_recent_legal_filing(business: any, filing_type: str = None): """Return the most recent filing containing the legal_filing type.""" + business_attribute = Filing.legal_entity_id if business.is_legal_entity else Filing.alternate_name_id + query = ( db.session.query(db.func.max(Filing._filing_date).label("last_filing_date")) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attribute == business.id) .filter(Filing._status == Filing.Status.COMPLETED.value) ) if filing_type: @@ -878,7 +889,7 @@ def get_most_recent_legal_filing(legal_entity_id: str, filing_type: str = None): filing = ( Filing.query.join(max_filing, Filing._filing_date == max_filing.c.last_filing_date) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attribute == business.id) .filter(Filing._status == Filing.Status.COMPLETED.value) .order_by(Filing.id.desc()) ) @@ -902,7 +913,7 @@ def get_completed_filings_for_colin(): db.session.query(Filing) .join(LegalEntity, Filing.legal_entity_id == LegalEntity.id) .filter( - ~LegalEntity.entity_type.in_( + ~LegalEntity._entity_type.in_( [ LegalEntity.EntityTypes.SOLE_PROP.value, LegalEntity.EntityTypes.PARTNERSHIP.value, @@ -928,9 +939,16 @@ def get_all_filings_by_status(status): @staticmethod def get_previous_completed_filing(filing): """Return the previous completed filing.""" + if filing.legal_entity_id: + business_attr = Filing.legal_entity_id + business_attr_value = filing.legal_entity_id + else: + business_attr = Filing.alternate_name_id + business_attr_value = filing.alternate_name_id + filings = ( db.session.query(Filing) - .filter(Filing.legal_entity_id == filing.legal_entity_id) + .filter(business_attr == business_attr_value) .filter(Filing._status == Filing.Status.COMPLETED.value) .filter(Filing.id < filing.id) .filter(Filing.effective_date < filing.effective_date) @@ -942,11 +960,12 @@ def get_previous_completed_filing(filing): return None @staticmethod - def has_completed_filing(legal_entity_id: int, filing_type: str) -> bool: + def has_completed_filing(business: any, filing_type: str) -> bool: """Return whether a completed filing of a given filing type exists.""" + business_attribute = Filing.legal_entity_id if business.is_legal_entity else Filing.alternate_name_id query = ( db.session.query(Filing) - .filter(Filing.legal_entity_id == legal_entity_id) + .filter(business_attribute == business.id) .filter(Filing._filing_type == filing_type) .filter(Filing._status == Filing.Status.COMPLETED.value) ) diff --git a/python/common/business-registry-model/src/business_model/models/legal_entity.py b/python/common/business-registry-model/src/business_model/models/legal_entity.py index 4270027256..cb5ea1d7c1 100644 --- a/python/common/business-registry-model/src/business_model/models/legal_entity.py +++ b/python/common/business-registry-model/src/business_model/models/legal_entity.py @@ -16,27 +16,28 @@ The Business class and Schema are held in this module """ import re -from enum import Enum, auto +from enum import Enum from http import HTTPStatus from typing import Final, Optional import datedelta from flask import current_app -from legal_api.exceptions import BusinessException -from legal_api.utils.base import BaseEnum, BaseMeta -from legal_api.utils.datetime import datetime, timezone -from legal_api.utils.legislation_datetime import LegislationDatetime from sql_versioning import Versioned -from sqlalchemy import case, event, text +from sqlalchemy import event, text from sqlalchemy.exc import OperationalError, ResourceClosedError from sqlalchemy.ext.hybrid import hybrid_property -from sqlalchemy.orm import aliased, backref -from sqlalchemy.sql.functions import func +from sqlalchemy.orm import backref + +from ..exceptions import BusinessException +from ..utils.enum import BaseMeta +from ..utils.datetime import datetime, timezone +from ..utils.legislation_datetime import LegislationDatetime from .address import Address # noqa: F401,I003 pylint: disable=unused-import; needed by the SQLAlchemy relationship from .alias import Alias # noqa: F401 pylint: disable=unused-import; needed by the SQLAlchemy relationship from .alternate_name import AlternateName # noqa: F401 pylint: disable=unused-import; needed by SQLAlchemy relationship from .amalgamation import Amalgamation # noqa: F401 pylint: disable=unused-import; needed by SQLAlchemy relationship +from .business_common import BusinessCommon from .db import db # noqa: I001 from .entity_role import EntityRole # noqa: F401 pylint: disable=unused-import; needed by the SQLAlchemy relationship from .filing import Filing # noqa: F401 pylint: disable=unused-import; needed by the SQLAlchemy backref @@ -48,7 +49,7 @@ class LegalEntity( - Versioned, db.Model + Versioned, db.Model, BusinessCommon ): # pylint: disable=too-many-instance-attributes, too-many-public-methods, too-many-lines """This class manages all of the base data about a LegalEntity. @@ -57,92 +58,6 @@ class LegalEntity( Businesses can be sole-proprietors, corporations, societies, etc. """ - class State(BaseEnum): - """Enum for the Business state.""" - - ACTIVE = auto() - HISTORICAL = auto() - LIQUIDATION = auto() - - # NB: commented out items that exist in namex but are not yet supported by Lear - class EntityTypes(str, Enum): - """Render an Enum of the Business Legal Types.""" - - BCOMP = "BEN" # aka BENEFIT_COMPANY in namex - BC_CCC = "CC" - BC_ULC_COMPANY = "ULC" - CCC_CONTINUE_IN = "CCC" - CEMETARY = "CEM" - CO_1860 = "QA" - CO_1862 = "QB" - CO_1878 = "QC" - CO_1890 = "QD" - CO_1897 = "QE" - COMP = "BC" # aka CORPORATION in namex - CONT_IN_SOCIETY = "CS" - CONTINUE_IN = "C" - COOP = "CP" # aka COOPERATIVE in namex - EXTRA_PRO_A = "A" - EXTRA_PRO_B = "B" - EXTRA_PRO_REG = "EPR" - FINANCIAL = "FI" - FOREIGN = "FOR" - LIBRARY = "LIB" - LICENSED = "LIC" - LIM_PARTNERSHIP = "LP" - LIMITED_CO = "LLC" - LL_PARTNERSHIP = "LL" - MISC_FIRM = "MF" - ORGANIZATION = "organization" - PARISHES = "PAR" - PARTNERSHIP = "GP" - PENS_FUND_SOC = "PFS" - PERSON = "person" - PRIVATE_ACT = "PA" - RAILWAYS = "RLY" - REGISTRATION = "REG" - SOCIETY = "S" - SOCIETY_BRANCH = "SB" - SOLE_PROP = "SP" - TRAMWAYS = "TMY" - TRUST = "T" - ULC_CONTINUE_IN = "CUL" - ULC_CO_1860 = "UQA" - ULC_CO_1862 = "UQB" - ULC_CO_1878 = "UQC" - ULC_CO_1890 = "UQD" - ULC_CO_1897 = "UQE" - XPRO_COOP = "XCP" - XPRO_LIM_PARTNR = "XP" - XPRO_LL_PARTNR = "XL" - XPRO_SOCIETY = "XS" - # *** The following are not yet supported by legal-api: *** - # DOING_BUSINESS_AS = 'DBA' - # XPRO_CORPORATION = 'XCR' - # XPRO_UNLIMITED_LIABILITY_COMPANY = 'XUL' - - LIMITED_COMPANIES: Final = [ - EntityTypes.COMP, - EntityTypes.CONTINUE_IN, - EntityTypes.CO_1860, - EntityTypes.CO_1862, - EntityTypes.CO_1878, - EntityTypes.CO_1890, - EntityTypes.CO_1897, - ] - - UNLIMITED_COMPANIES: Final = [ - EntityTypes.BC_ULC_COMPANY, - EntityTypes.ULC_CONTINUE_IN, - EntityTypes.ULC_CO_1860, - EntityTypes.ULC_CO_1862, - EntityTypes.ULC_CO_1878, - EntityTypes.ULC_CO_1890, - EntityTypes.ULC_CO_1897, - ] - - NON_BUSINESS_ENTITY_TYPES: Final = [EntityTypes.PERSON, EntityTypes.ORGANIZATION] - class AssociationTypes(Enum): """Render an Enum of the Business Association Types.""" @@ -154,19 +69,19 @@ class AssociationTypes(Enum): SP_DOING_BUSINESS_AS = "DBA" BUSINESSES = { - EntityTypes.BCOMP: { + BusinessCommon.EntityTypes.BCOMP: { "numberedBusinessNameSuffix": "B.C. LTD.", "numberedDescription": "Numbered Benefit Company", }, - EntityTypes.COMP: { + BusinessCommon.EntityTypes.COMP: { "numberedBusinessNameSuffix": "B.C. LTD.", "numberedDescription": "Numbered Limited Company", }, - EntityTypes.BC_ULC_COMPANY: { + BusinessCommon.EntityTypes.BC_ULC_COMPANY: { "numberedBusinessNameSuffix": "B.C. UNLIMITED LIABILITY COMPANY", "numberedDescription": "Numbered Unlimited Liability Company", }, - EntityTypes.BC_CCC: { + BusinessCommon.EntityTypes.BC_CCC: { "numberedBusinessNameSuffix": "B.C. COMMUNITY CONTRIBUTION COMPANY LTD.", "numberedDescription": "Numbered Community Contribution Company", }, @@ -235,7 +150,7 @@ class AssociationTypes(Enum): last_coa_date = db.Column("last_coa_date", db.DateTime(timezone=True)) last_cod_date = db.Column("last_cod_date", db.DateTime(timezone=True)) _legal_name = db.Column("legal_name", db.String(1000), index=True) - entity_type = db.Column("entity_type", db.String(15), index=True) + _entity_type = db.Column("entity_type", db.String(15), index=True) founding_date = db.Column("founding_date", db.DateTime(timezone=True), default=datetime.utcnow) start_date = db.Column("start_date", db.DateTime(timezone=True)) restoration_expiry_date = db.Column("restoration_expiry_date", db.DateTime(timezone=True)) @@ -248,7 +163,7 @@ class AssociationTypes(Enum): last_ar_year = db.Column("last_ar_year", db.Integer) last_ar_reminder_year = db.Column("last_ar_reminder_year", db.Integer) association_type = db.Column("association_type", db.String(50)) - state = db.Column("state", db.Enum(State), default=State.ACTIVE.value) + state = db.Column("state", db.Enum(BusinessCommon.State), default=BusinessCommon.State.ACTIVE) admin_freeze = db.Column("admin_freeze", db.Boolean, unique=False, default=False) submitter_userid = db.Column("submitter_userid", db.Integer, db.ForeignKey("users.id")) submitter = db.relationship( @@ -301,7 +216,7 @@ class AssociationTypes(Enum): lazy="dynamic", overlaps="legal_entity", ) - _alternate_names = db.relationship("AlternateName", back_populates="legal_entity", lazy="dynamic") + alternate_names = db.relationship("AlternateName", back_populates="legal_entity", lazy="dynamic") role_addresses = db.relationship("RoleAddress", lazy="dynamic") entity_delivery_address = db.relationship( "Address", @@ -398,6 +313,15 @@ def office_mailing_address(self): .filter(Address.address_type == Address.MAILING) ) + @property + def aliases(self): + """Return aliases(name translation) for a business if any.""" + return ( + db.session.query(AlternateName) + .filter(AlternateName.legal_entity_id == self.id) + .filter(AlternateName.name_type == AlternateName.NameType.TRANSLATION) + ) + @property def office_delivery_address(self): """Return the delivery address.""" @@ -423,149 +347,9 @@ def office_delivery_address(self): .filter(Address.address_type == Address.DELIVERY) ) - @property - def is_firm(self): - """Return if is firm, otherwise false.""" - return self.entity_type in [ - self.EntityTypes.SOLE_PROP.value, - self.EntityTypes.PARTNERSHIP.value, - ] - - @property - def good_standing(self): - """Return true if in good standing, otherwise false.""" - # A firm is always in good standing - if self.is_firm: - return True - # Date of last AR or founding date if they haven't yet filed one - last_ar_date = self.last_ar_date or self.founding_date - # Good standing is if last AR was filed within the past 1 year, 2 months and 1 day and is in an active state - if self.state == LegalEntity.State.ACTIVE: - if self.restoration_expiry_date: - return False # A business in limited restoration is not in good standing - else: - return last_ar_date + datedelta.datedelta(years=1, months=2, days=1) > datetime.utcnow() - return True - - @property - def legal_name(self): - """Return legal name for entity. - - For non-firms, just return the value in _legal_name field. - For SPs, return the legal name of the proprietor or the organization that owns the firm. - For SP/GPs: - 1. Union the proprietor/partner that owns the firm and sort by legal name(individual or organization's name). - 2. Take the first two proprietor/partner legal names and concatenate them with a comma. - 3. If there are more than two matching proprietor/partners, append ', et al' - 4. Return final legal_name result - """ - - match self.entity_type: - case self.EntityTypes.PARTNERSHIP: - return self._legal_name - - case self.EntityTypes.PERSON: - person_full_name = "" - for token in [self.first_name, self.middle_initial, self.last_name]: - if token: - if len(person_full_name) > 0: - person_full_name = f"{person_full_name} {token}" - else: - person_full_name = token - - return person_full_name - - from . import ColinEntity # pylint: disable=import-outside-toplevel - - if self.is_firm: - related_le_alias = aliased(LegalEntity, name="related_le_alias") - related_le_stmt = ( - db.session.query( - case( - ( - related_le_alias.entity_type == "person", - func.concat_ws( - " ", - func.nullif(related_le_alias.last_name, ""), - func.nullif(related_le_alias.middle_initial, ""), - func.nullif(related_le_alias.first_name, ""), - ), - ), - ( - related_le_alias.entity_type == "organization", - related_le_alias._legal_name, - ), # pylint: disable=protected-access # noqa: E501 - else_=None, - ).label("sortName"), - case( - ( - related_le_alias.entity_type == "person", - func.concat_ws( - " ", - func.nullif(related_le_alias.first_name, ""), - func.nullif(related_le_alias.middle_initial, ""), - func.nullif(related_le_alias.last_name, ""), - ), - ), - ( - related_le_alias.entity_type == "organization", - related_le_alias._legal_name, - ), # pylint: disable=protected-access # noqa: E501 - else_=None, - ).label("legalName"), - ) - .select_from(LegalEntity) - .join(EntityRole, EntityRole.legal_entity_id == LegalEntity.id) - .join( - related_le_alias, - related_le_alias.id == EntityRole.related_entity_id, - ) - .filter(LegalEntity.id == self.id) - ) - - related_colin_entity_stmt = ( - db.session.query( - ColinEntity.organization_name.label("sortName"), - ColinEntity.organization_name.label("legalName"), - ) - .select_from(LegalEntity) - .join(EntityRole, EntityRole.legal_entity_id == LegalEntity.id) - .join(ColinEntity, ColinEntity.id == EntityRole.related_colin_entity_id) - .filter(LegalEntity.id == self.id) - ) - - result_query = related_le_stmt.union(related_colin_entity_stmt).order_by("sortName") - - results = result_query.all() - if results and len(results) > 2: - legal_name_str = ", ".join([r.legalName for r in results[:2]]) - legal_name_str = f"{legal_name_str}, et al" - else: - legal_name_str = ", ".join([r.legalName for r in results]) - return legal_name_str - - return self._legal_name - - @legal_name.setter - def legal_name(self, value): - """Set the legal_name of the LegalEntity.""" - self._legal_name = value - - @property - def business_name(self): - """Return operating name for firms and legal name for non-firm entities.""" - - if not self.is_firm: - return self._legal_name - - if alternate_name := self._alternate_names.filter_by(identifier=self.identifier).one_or_none(): - return alternate_name.name - - return None - # @property def alternate_names_json(self): - """Return operating names for a business if any.""" + """Return alternate names (dba & translation) for a business if any.""" # le_alias = aliased(LegalEntity) # alternate_names = ( # db.session.query(AlternateName.identifier, @@ -580,17 +364,35 @@ def alternate_names_json(self): # ) if alternate_names := self.alternate_names.all(): - names = [ - { - "identifier": alternate_name.identifier, - "operatingName": alternate_name.name, - # 'entityType': alternate_name.name_type, - "entityType": self.entity_type, - "nameStartDate": LegislationDatetime.format_as_legislation_date(alternate_name.start_date), - "nameRegisteredDate": alternate_name.registration_date.isoformat(), - } - for alternate_name in alternate_names - ] + names = [] + for alternate_name in alternate_names: + if alternate_name.name_type == AlternateName.NameType.DBA: + # format dba + names.append( + { + "entityType": alternate_name.entity_type, + "identifier": alternate_name.identifier, + "name": alternate_name.name, + "nameRegisteredDate": alternate_name.start_date.isoformat(), + "nameStartDate": LegislationDatetime.format_as_legislation_date( + alternate_name.business_start_date + ) + if alternate_name.business_start_date + else None, + "nameType": alternate_name.name_type.name, + "operatingName": alternate_name.name, # will be removed in the future + } + ) + else: + # format name translation + names.append( + { + "name": alternate_name.name, + "nameStartDate": LegislationDatetime.format_as_legislation_date(alternate_name.start_date), + "nameType": alternate_name.name_type.name, + } + ) + return names return [] @@ -654,9 +456,9 @@ def _slim_json(self): "adminFreeze": self.admin_freeze or False, "goodStanding": self.good_standing, "identifier": self.identifier, - "legalName": self.legal_name, + "legalName": self._legal_name, "legalType": self.entity_type, - "state": self.state.name if self.state else LegalEntity.State.ACTIVE.name, + "state": self.state.name, } if self.tax_id: @@ -682,13 +484,15 @@ def _extend_json(self, d): if self.fiscal_year_end_date: d["fiscalYearEndDate"] = datetime.date(self.fiscal_year_end_date).isoformat() if self.state_filing_id: - if self.state == LegalEntity.State.HISTORICAL and ( - amalgamating_business := self.amalgamating_businesses.one_or_none() - ): - amalgamation = Amalgamation.find_by_id(amalgamating_business.amalgamation_id) - d["amalgamatedInto"] = amalgamation.json() - else: - d["stateFiling"] = f"{base_url}/{self.identifier}/filings/{self.state_filing_id}" + # TODO: revert once amalgamation tables and migration scripts have been run + # if self.state == LegalEntity.State.HISTORICAL and ( + # amalgamating_business := self.amalgamating_businesses.one_or_none() + # ): + # amalgamation = Amalgamation.find_by_id(amalgamating_business.amalgamation_id) + # d["amalgamatedInto"] = amalgamation.json() + # else: + # d["stateFiling"] = f"{base_url}/{self.identifier}/filings/{self.state_filing_id}" + d["stateFiling"] = f"{base_url}/{self.identifier}/filings/{self.state_filing_id}" if self.start_date: d["startDate"] = LegislationDatetime.format_as_legislation_date(self.start_date) @@ -710,8 +514,8 @@ def _extend_json(self, d): else None ) - d["hasCorrections"] = Filing.has_completed_filing(self.id, "correction") - d["hasCourtOrders"] = Filing.has_completed_filing(self.id, "courtOrder") + d["hasCorrections"] = Filing.has_completed_filing(self, "correction") + d["hasCourtOrders"] = Filing.has_completed_filing(self, "courtOrder") @property def party_json(self) -> dict: @@ -734,7 +538,7 @@ def party_json(self) -> dict: "officer": { "id": self.id, "partyType": self.entity_type, - "organizationName": self.legal_name, + "organizationName": self._legal_name, "identifier": self.identifier, } } @@ -755,40 +559,6 @@ def party_json(self) -> dict: return member - @property - def compliance_warnings(self): - """Return compliance warnings.""" - if not hasattr(self, "_compliance_warnings"): - return [] - - return self._compliance_warnings - - @compliance_warnings.setter - def compliance_warnings(self, value): - """Set compliance warnings.""" - self._compliance_warnings = value - - @property - def warnings(self): - """Return warnings.""" - if not hasattr(self, "_warnings"): - return [] - - return self._warnings - - @warnings.setter - def warnings(self, value): - """Set warnings.""" - self._warnings = value - - @property - def allowable_actions(self): - """Return warnings.""" - if not hasattr(self, "_allowable_actions"): - return {} - - return self._allowable_actions - @property def name(self) -> str: """Return the full name of the party for comparison.""" @@ -796,12 +566,7 @@ def name(self) -> str: if self.middle_initial: return " ".join((self.first_name, self.middle_initial, self.last_name)).strip().upper() return " ".join((self.first_name, self.last_name)).strip().upper() - return self.legal_name - - @allowable_actions.setter - def allowable_actions(self, value): - """Set warnings.""" - self._allowable_actions = value + return self._legal_name @classmethod def find_by_legal_name(cls, legal_name: str = None): @@ -819,7 +584,7 @@ def find_by_legal_name(cls, legal_name: str = None): return legal_entity @classmethod - def find_by_operating_name(cls, operating_name: str = None) -> LegalEntity | None: + def find_by_operating_name(cls, operating_name: str = None): """Given a operating_name, this will return an Active LegalEntity.""" if not operating_name: return None @@ -833,22 +598,15 @@ def find_by_identifier(cls, identifier: str = None): if not identifier or not cls.validate_identifier(entity_type=None, identifier=identifier): return None - legal_entity = None - - if identifier.startswith("FM"): - if alt_name := AlternateName.find_by_identifier(identifier): - legal_entity = cls.find_by_id(alt_name.legal_entity_id) - else: - non_entity_types = [ - LegalEntity.EntityTypes.PERSON.value, - LegalEntity.EntityTypes.ORGANIZATION.value, - ] - - legal_entity = ( - cls.query.filter(~LegalEntity.entity_type.in_(non_entity_types)) - .filter_by(identifier=identifier) - .one_or_none() - ) + non_business_types = [ + LegalEntity.EntityTypes.PERSON.value, + LegalEntity.EntityTypes.ORGANIZATION.value, + ] + legal_entity = ( + cls.query.filter(~LegalEntity._entity_type.in_(non_business_types)) + .filter_by(identifier=identifier) + .one_or_none() + ) return legal_entity @@ -878,21 +636,9 @@ def get_all_by_no_tax_id(cls): LegalEntity.EntityTypes.PERSON.value, LegalEntity.EntityTypes.ORGANIZATION.value, ] - legal_entities = cls.query.filter(~LegalEntity.entity_type.in_(no_tax_id_types)).filter_by(tax_id=None).all() + legal_entities = cls.query.filter(~LegalEntity._entity_type.in_(no_tax_id_types)).filter_by(tax_id=None).all() return legal_entities - @classmethod - def get_filing_by_id(cls, legal_entity_identifier: int, filing_id: str): - """Return the filings for a specific business and filing_id.""" - filing = ( - db.session.query(LegalEntity, Filing) - .filter(LegalEntity.id == Filing.legal_entity_id) - .filter(LegalEntity.identifier == legal_entity_identifier) - .filter(Filing.id == filing_id) - .one_or_none() - ) - return None if not filing else filing[1] - @classmethod def get_next_value_from_sequence(cls, business_type: str) -> Optional[int]: """Return the next value from the sequence.""" @@ -906,7 +652,7 @@ def get_next_value_from_sequence(cls, business_type: str) -> Optional[int]: return None @staticmethod - def validate_identifier(entity_type: EntityTypes, identifier: str) -> bool: + def validate_identifier(entity_type: BusinessCommon.EntityTypes, identifier: str) -> bool: """Validate the identifier meets the Registry naming standards. All legal entities with BC Reg are PREFIX + 7 digits @@ -951,13 +697,13 @@ def valid_party_type_data(self) -> bool: return False if self.entity_type == LegalEntity.EntityTypes.PERSON.value: - if not (self.first_name or self.middle_initial or self.last_name) or self.legal_name: + if not (self.first_name or self.middle_initial or self.last_name) or self._legal_name: return False return True @classmethod def find_by_id(cls, legal_entity_id: int): - """Return a legal enntity by the internal id.""" + """Return a legal entity by the internal id.""" legal_entity = None if legal_entity_id: legal_entity = cls.query.filter_by(id=legal_entity_id).one_or_none() diff --git a/python/common/business-registry-model/src/business_model/models/naics_element.py b/python/common/business-registry-model/src/business_model/models/naics_element.py index 3a2421336b..2832faf3e8 100644 --- a/python/common/business-registry-model/src/business_model/models/naics_element.py +++ b/python/common/business-registry-model/src/business_model/models/naics_element.py @@ -17,7 +17,7 @@ """ from enum import auto -from legal_api.utils.base import BaseEnum +from ..utils.enum import BaseEnum from .db import db # noqa: I001 diff --git a/python/common/business-registry-model/src/business_model/models/office.py b/python/common/business-registry-model/src/business_model/models/office.py index 1621384543..c16d59f7c3 100644 --- a/python/common/business-registry-model/src/business_model/models/office.py +++ b/python/common/business-registry-model/src/business_model/models/office.py @@ -34,6 +34,7 @@ class Office(Versioned, db.Model): # pylint: disable=too-few-public-methods "change_filing_id", "deactivated_date", "office_type", + "alternate_name_id", ] } @@ -44,6 +45,7 @@ class Office(Versioned, db.Model): # pylint: disable=too-few-public-methods # Parent Keys change_filing_id = db.Column("change_filing_id", db.Integer, db.ForeignKey("filings.id"), index=True) legal_entity_id = db.Column("legal_entity_id", db.Integer, db.ForeignKey("legal_entities.id"), index=True) + alternate_name_id = db.Column("alternate_name_id", db.Integer, db.ForeignKey("alternate_names.id"), nullable=True) # Relationships addresses = db.relationship("Address", lazy="dynamic", cascade="all, delete, delete-orphan") diff --git a/python/common/business-registry-model/src/business_model/models/party.py b/python/common/business-registry-model/src/business_model/models/party.py index ab0598f5d4..5d45db0aff 100644 --- a/python/common/business-registry-model/src/business_model/models/party.py +++ b/python/common/business-registry-model/src/business_model/models/party.py @@ -16,8 +16,8 @@ from http import HTTPStatus -from legal_api.exceptions import BusinessException -from legal_api.utils.enum import BaseEnum, auto +from ..exceptions import BusinessException +from ..utils.enum import BaseEnum, auto from sql_versioning import Versioned from sqlalchemy import event diff --git a/python/common/business-registry-model/src/business_model/models/registration_bootstrap.py b/python/common/business-registry-model/src/business_model/models/registration_bootstrap.py index 7458b9199f..5672532ab7 100644 --- a/python/common/business-registry-model/src/business_model/models/registration_bootstrap.py +++ b/python/common/business-registry-model/src/business_model/models/registration_bootstrap.py @@ -17,7 +17,7 @@ """ from datetime import datetime -from legal_api.exceptions import BusinessException +from ..exceptions import BusinessException from sqlalchemy.ext.hybrid import hybrid_property from .db import db diff --git a/python/common/business-registry-model/src/business_model/models/request_tracker.py b/python/common/business-registry-model/src/business_model/models/request_tracker.py index a569d74a0e..dc2fd07681 100644 --- a/python/common/business-registry-model/src/business_model/models/request_tracker.py +++ b/python/common/business-registry-model/src/business_model/models/request_tracker.py @@ -17,9 +17,9 @@ from enum import auto from typing import List -from legal_api.utils.base import BaseEnum -from legal_api.utils.datetime import datetime -from legal_api.utils.legislation_datetime import LegislationDatetime +from ..utils.enum import BaseEnum +from ..utils.datetime import datetime +from ..utils.legislation_datetime import LegislationDatetime from .db import db diff --git a/python/common/business-registry-model/src/business_model/models/share_class.py b/python/common/business-registry-model/src/business_model/models/share_class.py index 0590db1f90..538b0b4e62 100644 --- a/python/common/business-registry-model/src/business_model/models/share_class.py +++ b/python/common/business-registry-model/src/business_model/models/share_class.py @@ -16,7 +16,7 @@ from http import HTTPStatus -from legal_api.exceptions import BusinessException +from ..exceptions import BusinessException from sql_versioning import Versioned from sqlalchemy import event diff --git a/python/common/business-registry-model/src/business_model/models/share_series.py b/python/common/business-registry-model/src/business_model/models/share_series.py index 761e80eada..6e3c9bb7fb 100644 --- a/python/common/business-registry-model/src/business_model/models/share_series.py +++ b/python/common/business-registry-model/src/business_model/models/share_series.py @@ -15,7 +15,7 @@ from http import HTTPStatus -from legal_api.exceptions import BusinessException +from ..exceptions import BusinessException from sql_versioning import Versioned from sqlalchemy import event diff --git a/python/common/business-registry-model/src/business_model/models/user.py b/python/common/business-registry-model/src/business_model/models/user.py index 0545d56f65..e73efa98d8 100644 --- a/python/common/business-registry-model/src/business_model/models/user.py +++ b/python/common/business-registry-model/src/business_model/models/user.py @@ -19,8 +19,8 @@ from datetime import datetime from flask import current_app -from legal_api.exceptions import BusinessException -from legal_api.utils.enum import BaseEnum, auto +from ..exceptions import BusinessException +from ..utils.enum import BaseEnum, auto from sql_versioning import Versioned from .db import db diff --git a/python/common/business-registry-model/src/business_model_migrations/env.py b/python/common/business-registry-model/src/business_model_migrations/env.py index 650c629d8a..a4418335cf 100644 --- a/python/common/business-registry-model/src/business_model_migrations/env.py +++ b/python/common/business-registry-model/src/business_model_migrations/env.py @@ -94,7 +94,7 @@ def process_revision_directives(context, revision, directives): connection=connection, target_metadata=get_metadata(), process_revision_directives=process_revision_directives, - **current_app.extensions["migrate"].configure_args + **current_app.extensions["migrate"].configure_args, ) with context.begin_transaction(): diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/004f7558063f_second.py b/python/common/business-registry-model/src/business_model_migrations/versions/004f7558063f_second.py index 105db1cac2..81acdb28bf 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/004f7558063f_second.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/004f7558063f_second.py @@ -18,7 +18,6 @@ def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.execute("CREATE SEQUENCE business_identifier_coop START 1002395") op.create_table( "addresses", sa.Column("id", sa.Integer(), nullable=False), @@ -34,6 +33,7 @@ def upgrade(): sa.Column("change_filing_id", sa.Integer(), nullable=True), sa.Column("office_id", sa.Integer(), nullable=True), sa.Column("version", sa.Integer(), nullable=False), + sa.Column("alternate_name_id", sa.Integer(), nullable=True), sa.ForeignKeyConstraint( ["change_filing_id"], ["filings.id"], @@ -43,26 +43,19 @@ def upgrade(): ["legal_entities.id"], ), sa.ForeignKeyConstraint(["office_id"], ["offices.id"], ondelete="CASCADE"), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.PrimaryKeyConstraint("id"), sqlite_autoincrement=True, ) with op.batch_alter_table("addresses", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_addresses_address_type"), ["address_type"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_addresses_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_addresses_legal_entity_id"), - ["legal_entity_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_addresses_street"), ["street"], unique=False - ) + batch_op.create_index(batch_op.f("ix_addresses_address_type"), ["address_type"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_street"), ["street"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_alternate_name_id"), ["alternate_name_id"], unique=False) op.create_table( "colin_last_update", @@ -85,24 +78,12 @@ def upgrade(): ) op.create_table( "corp_types_history", - sa.Column( - "corp_type_cd", sa.String(length=5), autoincrement=False, nullable=False - ), - sa.Column( - "colin_ind", sa.String(length=1), autoincrement=False, nullable=False - ), - sa.Column( - "corp_class", sa.String(length=10), autoincrement=False, nullable=False - ), - sa.Column( - "short_desc", sa.String(length=25), autoincrement=False, nullable=False - ), - sa.Column( - "full_desc", sa.String(length=100), autoincrement=False, nullable=False - ), - sa.Column( - "legislation", sa.String(length=100), autoincrement=False, nullable=True - ), + sa.Column("corp_type_cd", sa.String(length=5), autoincrement=False, nullable=False), + sa.Column("colin_ind", sa.String(length=1), autoincrement=False, nullable=False), + sa.Column("corp_class", sa.String(length=10), autoincrement=False, nullable=False), + sa.Column("short_desc", sa.String(length=25), autoincrement=False, nullable=False), + sa.Column("full_desc", sa.String(length=100), autoincrement=False, nullable=False), + sa.Column("legislation", sa.String(length=100), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.PrimaryKeyConstraint("corp_type_cd", "version"), @@ -112,9 +93,7 @@ def upgrade(): "dc_definitions", sa.Column("id", sa.Integer(), nullable=False), sa.Column( - "credential_type", - sa.Enum("business", "business_relationship", name="credentialtype"), - nullable=False, + "credential_type", sa.Enum("business", "business_relationship", name="credentialtype"), nullable=False ), sa.Column("schema_id", sa.String(length=100), nullable=True), sa.Column("schema_name", sa.String(length=50), nullable=True), @@ -138,26 +117,12 @@ def upgrade(): sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("naics_structures", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_naics_structures_class_definition"), - ["class_definition"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_naics_structures_class_title"), ["class_title"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_structures_code"), ["code"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_structures_level"), ["level"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_structures_version"), ["version"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_structures_year"), ["year"], unique=False - ) + batch_op.create_index(batch_op.f("ix_naics_structures_class_definition"), ["class_definition"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_structures_class_title"), ["class_title"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_structures_code"), ["code"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_structures_level"), ["level"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_structures_version"), ["version"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_structures_year"), ["year"], unique=False) op.create_table( "office_types", @@ -173,9 +138,7 @@ def upgrade(): sa.PrimaryKeyConstraint("identifier"), ) with op.batch_alter_table("registration_bootstrap", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_registration_bootstrap_account"), ["account"], unique=False - ) + batch_op.create_index(batch_op.f("ix_registration_bootstrap_account"), ["account"], unique=False) op.create_table( "users", @@ -196,86 +159,48 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("users", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_users_idp_userid"), ["idp_userid"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_users_username"), ["username"], unique=False - ) + batch_op.create_index(batch_op.f("ix_users_idp_userid"), ["idp_userid"], unique=False) + batch_op.create_index(batch_op.f("ix_users_username"), ["username"], unique=False) op.create_table( "users_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), - sa.Column( - "username", sa.String(length=1000), autoincrement=False, nullable=True - ), - sa.Column( - "firstname", sa.String(length=1000), autoincrement=False, nullable=True - ), - sa.Column( - "lastname", sa.String(length=1000), autoincrement=False, nullable=True - ), - sa.Column( - "middlename", sa.String(length=1000), autoincrement=False, nullable=True - ), + sa.Column("username", sa.String(length=1000), autoincrement=False, nullable=True), + sa.Column("firstname", sa.String(length=1000), autoincrement=False, nullable=True), + sa.Column("lastname", sa.String(length=1000), autoincrement=False, nullable=True), + sa.Column("middlename", sa.String(length=1000), autoincrement=False, nullable=True), sa.Column("email", sa.String(length=1024), autoincrement=False, nullable=True), sa.Column("sub", sa.String(length=36), autoincrement=False, nullable=True), sa.Column("iss", sa.String(length=1024), autoincrement=False, nullable=True), - sa.Column( - "idp_userid", sa.String(length=256), autoincrement=False, nullable=True - ), - sa.Column( - "login_source", sa.String(length=200), autoincrement=False, nullable=True - ), - sa.Column( - "creation_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), + sa.Column("idp_userid", sa.String(length=256), autoincrement=False, nullable=True), + sa.Column("login_source", sa.String(length=200), autoincrement=False, nullable=True), + sa.Column("creation_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.PrimaryKeyConstraint("id", "version"), sqlite_autoincrement=True, ) with op.batch_alter_table("users_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_users_history_idp_userid"), ["idp_userid"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_users_history_username"), ["username"], unique=False - ) + batch_op.create_index(batch_op.f("ix_users_history_idp_userid"), ["idp_userid"], unique=False) + batch_op.create_index(batch_op.f("ix_users_history_username"), ["username"], unique=False) op.create_table( "addresses_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), - sa.Column( - "address_type", sa.String(length=4096), autoincrement=False, nullable=True - ), + sa.Column("address_type", sa.String(length=4096), autoincrement=False, nullable=True), sa.Column("street", sa.String(length=4096), autoincrement=False, nullable=True), - sa.Column( - "street_additional", - sa.String(length=4096), - autoincrement=False, - nullable=True, - ), + sa.Column("street_additional", sa.String(length=4096), autoincrement=False, nullable=True), sa.Column("city", sa.String(length=4096), autoincrement=False, nullable=True), sa.Column("region", sa.String(length=4096), autoincrement=False, nullable=True), sa.Column("country", sa.String(length=2), autoincrement=False, nullable=True), - sa.Column( - "postal_code", sa.String(length=15), autoincrement=False, nullable=True - ), - sa.Column( - "delivery_instructions", - sa.String(length=4096), - autoincrement=False, - nullable=True, - ), + sa.Column("postal_code", sa.String(length=15), autoincrement=False, nullable=True), + sa.Column("delivery_instructions", sa.String(length=4096), autoincrement=False, nullable=True), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("office_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), + sa.Column("alternate_name_id", sa.Integer(), nullable=True), sa.ForeignKeyConstraint( ["change_filing_id"], ["filings.id"], @@ -284,28 +209,19 @@ def upgrade(): ["legal_entity_id"], ["legal_entities.id"], ), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.PrimaryKeyConstraint("id", "version"), sqlite_autoincrement=True, ) with op.batch_alter_table("addresses_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_addresses_history_address_type"), - ["address_type"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_addresses_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_addresses_history_legal_entity_id"), - ["legal_entity_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_addresses_history_street"), ["street"], unique=False - ) + batch_op.create_index(batch_op.f("ix_addresses_history_address_type"), ["address_type"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_history_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_history_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_history_street"), ["street"], unique=False) + batch_op.create_index(batch_op.f("ix_addresses_history_alternate_name_id"), ["alternate_name_id"], unique=False) op.create_table( "aliases", @@ -328,11 +244,7 @@ def upgrade(): ) with op.batch_alter_table("aliases", schema=None) as batch_op: batch_op.create_index(batch_op.f("ix_aliases_alias"), ["alias"], unique=False) - batch_op.create_index( - batch_op.f("ix_aliases_change_filing_id"), - ["change_filing_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_aliases_change_filing_id"), ["change_filing_id"], unique=False) op.create_table( "aliases_history", @@ -355,111 +267,55 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("aliases_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_aliases_history_alias"), ["alias"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_aliases_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_aliases_history_alias"), ["alias"], unique=False) + batch_op.create_index(batch_op.f("ix_aliases_history_change_filing_id"), ["change_filing_id"], unique=False) op.create_table( - "alternate_names", + "colin_entities", sa.Column("id", sa.Integer(), nullable=False), + sa.Column("organization_name", sa.String(length=150), nullable=True), sa.Column("identifier", sa.String(length=10), nullable=True), - sa.Column("name_type", sa.Enum("OPERATING", name="nametype"), nullable=False), - sa.Column("name", sa.String(length=1000), nullable=False), - sa.Column("bn15", sa.String(length=20), nullable=True), - sa.Column("start_date", sa.DateTime(timezone=True), nullable=False), - sa.Column("registration_date", sa.DateTime(timezone=True), nullable=False), - sa.Column("end_date", sa.DateTime(timezone=True), nullable=True), - sa.Column("legal_entity_id", sa.Integer(), nullable=True), + sa.Column("email", sa.String(length=254), nullable=True), sa.Column("change_filing_id", sa.Integer(), nullable=True), - sa.Column("naics_key", sa.String(length=50), nullable=True), - sa.Column("naics_code", sa.String(length=10), nullable=True), - sa.Column("naics_description", sa.String(length=300), nullable=True), + sa.Column("delivery_address_id", sa.Integer(), nullable=True), + sa.Column("mailing_address_id", sa.Integer(), nullable=True), sa.Column("version", sa.Integer(), nullable=False), sa.ForeignKeyConstraint( ["change_filing_id"], ["filings.id"], ), sa.ForeignKeyConstraint( - ["legal_entity_id"], - ["legal_entities.id"], + ["delivery_address_id"], + ["addresses.id"], + ), + sa.ForeignKeyConstraint( + ["mailing_address_id"], + ["addresses.id"], ), sa.PrimaryKeyConstraint("id"), sqlite_autoincrement=True, ) - with op.batch_alter_table("alternate_names", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_alternate_names_change_filing_id"), - ["change_filing_id"], - unique=False, - ) + with op.batch_alter_table("colin_entities", schema=None) as batch_op: + batch_op.create_index(batch_op.f("ix_colin_entities_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_colin_entities_email"), ["email"], unique=False) + batch_op.create_index(batch_op.f("ix_colin_entities_identifier"), ["identifier"], unique=False) + batch_op.create_index(batch_op.f("ix_colin_entities_organization_name"), ["organization_name"], unique=False) op.create_table( - "alternate_names_history", + "colin_entities_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), - sa.Column( - "identifier", sa.String(length=10), autoincrement=False, nullable=True - ), - sa.Column( - "name_type", - sa.Enum("OPERATING", name="nametype"), - autoincrement=False, - nullable=False, - ), - sa.Column("name", sa.String(length=1000), autoincrement=False, nullable=False), - sa.Column("bn15", sa.String(length=20), autoincrement=False, nullable=True), - sa.Column( - "start_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=False, - ), - sa.Column( - "end_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True - ), - sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("organization_name", sa.String(length=150), autoincrement=False, nullable=True), + sa.Column("identifier", sa.String(length=10), autoincrement=False, nullable=True), + sa.Column("email", sa.String(length=254), autoincrement=False, nullable=True), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column("naics_key", sa.String(length=50), nullable=True), - sa.Column("naics_code", sa.String(length=10), nullable=True), - sa.Column("naics_description", sa.String(length=300), nullable=True), + sa.Column("delivery_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("mailing_address_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( ["change_filing_id"], ["filings.id"], ), - sa.ForeignKeyConstraint( - ["legal_entity_id"], - ["legal_entities.id"], - ), - sa.PrimaryKeyConstraint("id", "version"), - sqlite_autoincrement=True, - ) - with op.batch_alter_table("alternate_names_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_alternate_names_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - - op.create_table( - "colin_entities", - sa.Column("id", sa.Integer(), nullable=False), - sa.Column("organization_name", sa.String(length=150), nullable=True), - sa.Column("identifier", sa.String(length=10), nullable=True), - sa.Column("email", sa.String(length=254), nullable=True), - sa.Column("change_filing_id", sa.Integer(), nullable=True), - sa.Column("delivery_address_id", sa.Integer(), nullable=True), - sa.Column("mailing_address_id", sa.Integer(), nullable=True), - sa.Column("version", sa.Integer(), nullable=False), - sa.ForeignKeyConstraint( - ["change_filing_id"], - ["filings.id"], - ), sa.ForeignKeyConstraint( ["delivery_address_id"], ["addresses.id"], @@ -468,53 +324,46 @@ def upgrade(): ["mailing_address_id"], ["addresses.id"], ), - sa.PrimaryKeyConstraint("id"), + sa.PrimaryKeyConstraint("id", "version"), sqlite_autoincrement=True, ) - with op.batch_alter_table("colin_entities", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_colin_entities_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_colin_entities_email"), ["email"], unique=False - ) + with op.batch_alter_table("colin_entities_history", schema=None) as batch_op: batch_op.create_index( - batch_op.f("ix_colin_entities_identifier"), ["identifier"], unique=False + batch_op.f("ix_colin_entities_history_change_filing_id"), ["change_filing_id"], unique=False ) + batch_op.create_index(batch_op.f("ix_colin_entities_history_email"), ["email"], unique=False) + batch_op.create_index(batch_op.f("ix_colin_entities_history_identifier"), ["identifier"], unique=False) batch_op.create_index( - batch_op.f("ix_colin_entities_organization_name"), - ["organization_name"], - unique=False, + batch_op.f("ix_colin_entities_history_organization_name"), ["organization_name"], unique=False ) op.create_table( - "colin_entities_history", + "alternate_names_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), - sa.Column( - "organization_name", - sa.String(length=150), - autoincrement=False, - nullable=True, - ), - sa.Column( - "identifier", sa.String(length=10), autoincrement=False, nullable=True - ), - sa.Column("email", sa.String(length=254), autoincrement=False, nullable=True), + sa.Column("identifier", sa.String(length=10), autoincrement=False, nullable=True), + sa.Column("name_type", sa.Enum("DBA", "TRANSLATION", name="nametype"), autoincrement=False, nullable=False), + sa.Column("name", sa.String(length=1000), autoincrement=False, nullable=False), + sa.Column("bn15", sa.String(length=20), autoincrement=False, nullable=True), + sa.Column("start_date", sa.DateTime(timezone=True), autoincrement=False, nullable=False), + sa.Column("end_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("business_start_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("dissolution_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("state", sa.Enum("ACTIVE", "HISTORICAL", name="state"), autoincrement=False, nullable=True), + sa.Column("state_filing_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("admin_freeze", sa.Boolean(), autoincrement=False, nullable=True), + sa.Column("last_modified", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("entity_type", sa.String(length=15), autoincrement=False, nullable=True), + sa.Column("colin_entity_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "delivery_address_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "mailing_address_id", sa.Integer(), autoincrement=False, nullable=True - ), + sa.Column("email", sa.String(length=254), autoincrement=False, nullable=True), + sa.Column("delivery_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("mailing_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("naics_key", sa.String(length=50), autoincrement=False, nullable=True), + sa.Column("naics_code", sa.String(length=10), autoincrement=False, nullable=True), + sa.Column("naics_description", sa.String(length=300), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), - sa.ForeignKeyConstraint( - ["change_filing_id"], - ["filings.id"], - ), sa.ForeignKeyConstraint( ["delivery_address_id"], ["addresses.id"], @@ -523,28 +372,32 @@ def upgrade(): ["mailing_address_id"], ["addresses.id"], ), + sa.ForeignKeyConstraint( + ["change_filing_id"], + ["filings.id"], + ), + sa.ForeignKeyConstraint( + ["legal_entity_id"], + ["legal_entities.id"], + ), + sa.ForeignKeyConstraint( + ["colin_entity_id"], + ["colin_entities.id"], + ), + sa.ForeignKeyConstraint( + ["state_filing_id"], + ["filings.id"], + ), sa.PrimaryKeyConstraint("id", "version"), sqlite_autoincrement=True, ) - with op.batch_alter_table("colin_entities_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_colin_entities_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_colin_entities_history_email"), ["email"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_colin_entities_history_identifier"), - ["identifier"], - unique=False, - ) + with op.batch_alter_table("alternate_names_history", schema=None) as batch_op: batch_op.create_index( - batch_op.f("ix_colin_entities_history_organization_name"), - ["organization_name"], - unique=False, + batch_op.f("ix_alternate_names_history_change_filing_id"), ["change_filing_id"], unique=False ) + batch_op.create_index(batch_op.f("ix_alternate_names_history_name"), ["name"], unique=False) + batch_op.create_index(batch_op.f("ix_alternate_names_history_identifier"), ["identifier"], unique=False) + batch_op.create_index(batch_op.f("ix_alternate_names_history_entity_type"), ["entity_type"], unique=False) op.create_table( "colin_event_ids", @@ -563,6 +416,7 @@ def upgrade(): sa.Column("comment", sa.String(length=4096), nullable=True), sa.Column("timestamp", sa.DateTime(timezone=True), nullable=True), sa.Column("legal_entity_id", sa.Integer(), nullable=True), + sa.Column("alternate_name_id", sa.Integer(), nullable=True), sa.Column("staff_id", sa.Integer(), nullable=True), sa.Column("filing_id", sa.Integer(), nullable=True), sa.ForeignKeyConstraint( @@ -573,6 +427,10 @@ def upgrade(): ["legal_entity_id"], ["legal_entities.id"], ), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.ForeignKeyConstraint( ["staff_id"], ["users.id"], @@ -580,15 +438,10 @@ def upgrade(): sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("comments", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_comments_filing_id"), ["filing_id"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_comments_legal_entity_id"), ["legal_entity_id"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_comments_staff_id"), ["staff_id"], unique=False - ) + batch_op.create_index(batch_op.f("ix_comments_filing_id"), ["filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_comments_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_comments_alternate_name_id"), ["alternate_name_id"], unique=False) + batch_op.create_index(batch_op.f("ix_comments_staff_id"), ["staff_id"], unique=False) op.create_table( "dc_connections", @@ -598,10 +451,15 @@ def upgrade(): sa.Column("is_active", sa.Boolean(), nullable=True), sa.Column("connection_state", sa.String(length=50), nullable=True), sa.Column("legal_entity_id", sa.Integer(), nullable=True), + sa.Column("alternate_name_id", sa.Integer(), nullable=True), sa.ForeignKeyConstraint( ["legal_entity_id"], ["legal_entities.id"], ), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.PrimaryKeyConstraint("id"), ) op.create_table( @@ -610,6 +468,7 @@ def upgrade(): sa.Column("type", sa.String(length=30), nullable=False), sa.Column("file_key", sa.String(length=100), nullable=False), sa.Column("legal_entity_id", sa.Integer(), nullable=True), + sa.Column("alternate_name_id", sa.Integer(), nullable=True), sa.Column("filing_id", sa.Integer(), nullable=True), sa.Column("version", sa.Integer(), nullable=False), sa.ForeignKeyConstraint( @@ -620,27 +479,25 @@ def upgrade(): ["legal_entity_id"], ["legal_entities.id"], ), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.PrimaryKeyConstraint("id"), sqlite_autoincrement=True, ) with op.batch_alter_table("documents", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_documents_filing_id"), ["filing_id"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_documents_legal_entity_id"), - ["legal_entity_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_documents_filing_id"), ["filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_documents_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_documents_alternate_name_id"), ["alternate_name_id"], unique=False) op.create_table( "documents_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), sa.Column("type", sa.String(length=30), autoincrement=False, nullable=False), - sa.Column( - "file_key", sa.String(length=100), autoincrement=False, nullable=False - ), + sa.Column("file_key", sa.String(length=100), autoincrement=False, nullable=False), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("alternate_name_id", sa.Integer(), nullable=True), sa.Column("filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), @@ -652,198 +509,67 @@ def upgrade(): ["legal_entity_id"], ["legal_entities.id"], ), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.PrimaryKeyConstraint("id", "version"), sqlite_autoincrement=True, ) with op.batch_alter_table("documents_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_documents_history_filing_id"), ["filing_id"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_documents_history_legal_entity_id"), - ["legal_entity_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_documents_history_filing_id"), ["filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_documents_history_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_documents_history_alternate_name_id"), ["alternate_name_id"], unique=False) op.create_table( "legal_entities_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), - sa.Column( - "last_modified", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), + sa.Column("last_modified", sa.DateTime(timezone=True), autoincrement=False, nullable=True), sa.Column("last_ledger_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "last_remote_ledger_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "last_ledger_timestamp", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "last_ar_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "last_agm_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "last_coa_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "last_cod_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "legal_name", sa.String(length=1000), autoincrement=False, nullable=True - ), - sa.Column( - "entity_type", sa.String(length=15), autoincrement=False, nullable=True - ), - sa.Column( - "founding_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "start_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True - ), - sa.Column( - "restoration_expiry_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "dissolution_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "cco_expiry_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "continuation_out_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "identifier", sa.String(length=10), autoincrement=False, nullable=True - ), + sa.Column("last_remote_ledger_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("last_ledger_timestamp", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("last_ar_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("last_agm_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("last_coa_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("last_cod_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("legal_name", sa.String(length=1000), autoincrement=False, nullable=True), + sa.Column("entity_type", sa.String(length=15), autoincrement=False, nullable=True), + sa.Column("founding_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("start_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("restoration_expiry_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("dissolution_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("cco_expiry_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("continuation_out_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("identifier", sa.String(length=10), autoincrement=False, nullable=True), sa.Column("tax_id", sa.String(length=15), autoincrement=False, nullable=True), - sa.Column( - "fiscal_year_end_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), + sa.Column("fiscal_year_end_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), sa.Column("restriction_ind", sa.Boolean(), autoincrement=False, nullable=True), sa.Column("last_ar_year", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "last_ar_reminder_year", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "association_type", sa.String(length=50), autoincrement=False, nullable=True - ), - sa.Column( - "state", - sa.Enum("ACTIVE", "HISTORICAL", "LIQUIDATION", name="state"), - autoincrement=False, - nullable=True, - ), + sa.Column("last_ar_reminder_year", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("association_type", sa.String(length=50), autoincrement=False, nullable=True), + sa.Column("state", sa.Enum("ACTIVE", "HISTORICAL", name="state"), autoincrement=False, nullable=True), sa.Column("state_filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("admin_freeze", sa.Boolean(), autoincrement=False, nullable=True), sa.Column("submitter_userid", sa.Integer(), autoincrement=False, nullable=True), sa.Column("send_ar_ind", sa.Boolean(), autoincrement=False, nullable=True), sa.Column("bn9", sa.String(length=9), autoincrement=False, nullable=True), - sa.Column( - "first_name", sa.String(length=30), autoincrement=False, nullable=True - ), - sa.Column( - "middle_initial", sa.String(length=30), autoincrement=False, nullable=True - ), - sa.Column( - "last_name", sa.String(length=30), autoincrement=False, nullable=True - ), - sa.Column( - "additional_name", sa.String(length=100), autoincrement=False, nullable=True - ), + sa.Column("first_name", sa.String(length=30), autoincrement=False, nullable=True), + sa.Column("middle_initial", sa.String(length=30), autoincrement=False, nullable=True), + sa.Column("last_name", sa.String(length=30), autoincrement=False, nullable=True), + sa.Column("additional_name", sa.String(length=100), autoincrement=False, nullable=True), sa.Column("title", sa.String(length=1000), autoincrement=False, nullable=True), sa.Column("email", sa.String(length=254), autoincrement=False, nullable=True), - sa.Column( - "delivery_address_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "mailing_address_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "naics_key", sa.String(length=50), autoincrement=False, nullable=True - ), - sa.Column( - "naics_code", sa.String(length=10), autoincrement=False, nullable=True - ), - sa.Column( - "naics_description", - sa.String(length=300), - autoincrement=False, - nullable=True, - ), - sa.Column( - "foreign_jurisdiction", - sa.String(length=10), - autoincrement=False, - nullable=True, - ), - sa.Column( - "foreign_jurisdiction_region", - sa.String(length=10), - autoincrement=False, - nullable=True, - ), - sa.Column( - "foreign_identifier", - sa.String(length=15), - autoincrement=False, - nullable=True, - ), - sa.Column( - "foreign_legal_name", - sa.String(length=1000), - autoincrement=False, - nullable=True, - ), - sa.Column( - "foreign_legal_type", - sa.String(length=10), - autoincrement=False, - nullable=True, - ), - sa.Column( - "foreign_incorporation_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), + sa.Column("delivery_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("mailing_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("naics_key", sa.String(length=50), autoincrement=False, nullable=True), + sa.Column("naics_code", sa.String(length=10), autoincrement=False, nullable=True), + sa.Column("naics_description", sa.String(length=300), autoincrement=False, nullable=True), + sa.Column("foreign_jurisdiction", sa.String(length=10), autoincrement=False, nullable=True), + sa.Column("foreign_jurisdiction_region", sa.String(length=10), autoincrement=False, nullable=True), + sa.Column("foreign_identifier", sa.String(length=15), autoincrement=False, nullable=True), + sa.Column("foreign_legal_name", sa.String(length=1000), autoincrement=False, nullable=True), + sa.Column("foreign_legal_type", sa.String(length=10), autoincrement=False, nullable=True), + sa.Column("foreign_incorporation_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -858,38 +584,20 @@ def upgrade(): ["submitter_userid"], ["users.id"], ), + sa.ForeignKeyConstraint( + ["state_filing_id"], + ["filings.id"], + ), sa.PrimaryKeyConstraint("id", "version"), sqlite_autoincrement=True, ) with op.batch_alter_table("legal_entities_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_legal_entities_history_entity_type"), - ["entity_type"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_history_first_name"), - ["first_name"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_history_identifier"), - ["identifier"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_history_legal_name"), - ["legal_name"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_history_middle_initial"), - ["middle_initial"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_history_tax_id"), ["tax_id"], unique=False - ) + batch_op.create_index(batch_op.f("ix_legal_entities_history_entity_type"), ["entity_type"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_history_first_name"), ["first_name"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_history_identifier"), ["identifier"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_history_legal_name"), ["legal_name"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_history_middle_initial"), ["middle_initial"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_history_tax_id"), ["tax_id"], unique=False) op.create_table( "naics_elements", @@ -901,13 +609,7 @@ def upgrade(): sa.Column("class_title", sa.String(length=150), nullable=False), sa.Column( "element_type", - sa.Enum( - "ALL_EXAMPLES", - "ILLUSTRATIVE_EXAMPLES", - "INCLUSIONS", - "EXCLUSIONS", - name="elementtype", - ), + sa.Enum("ALL_EXAMPLES", "ILLUSTRATIVE_EXAMPLES", "INCLUSIONS", "EXCLUSIONS", name="elementtype"), nullable=False, ), sa.Column("element_description", sa.String(length=500), nullable=False), @@ -919,49 +621,25 @@ def upgrade(): sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("naics_elements", schema=None) as batch_op: + batch_op.create_index(batch_op.f("ix_naics_elements_class_title"), ["class_title"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_elements_code"), ["code"], unique=False) batch_op.create_index( - batch_op.f("ix_naics_elements_class_title"), ["class_title"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_elements_code"), ["code"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_elements_element_description"), - ["element_description"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_naics_elements_element_type"), ["element_type"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_elements_level"), ["level"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_elements_naics_structure_id"), - ["naics_structure_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_naics_elements_version"), ["version"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_naics_elements_year"), ["year"], unique=False + batch_op.f("ix_naics_elements_element_description"), ["element_description"], unique=False ) + batch_op.create_index(batch_op.f("ix_naics_elements_element_type"), ["element_type"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_elements_level"), ["level"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_elements_naics_structure_id"), ["naics_structure_id"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_elements_version"), ["version"], unique=False) + batch_op.create_index(batch_op.f("ix_naics_elements_year"), ["year"], unique=False) op.create_table( "offices_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), - sa.Column( - "office_type", sa.String(length=75), autoincrement=False, nullable=True - ), - sa.Column( - "deactivated_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), + sa.Column("office_type", sa.String(length=75), autoincrement=False, nullable=True), + sa.Column("deactivated_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("alternate_name_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -972,6 +650,10 @@ def upgrade(): ["legal_entity_id"], ["legal_entities.id"], ), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.ForeignKeyConstraint( ["office_type"], ["office_types.identifier"], @@ -980,16 +662,9 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("offices_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_offices_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_offices_history_legal_entity_id"), - ["legal_entity_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_offices_history_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_offices_history_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_offices_history_alternate_name_id"), ["alternate_name_id"], unique=False) op.create_table( "parties", @@ -1022,51 +697,24 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("parties", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_parties_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_parties_first_name"), ["first_name"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_parties_middle_initial"), ["middle_initial"], unique=False - ) + batch_op.create_index(batch_op.f("ix_parties_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_parties_first_name"), ["first_name"], unique=False) + batch_op.create_index(batch_op.f("ix_parties_middle_initial"), ["middle_initial"], unique=False) - op.create_table( - "parties_history", - sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), - sa.Column( - "party_type", sa.String(length=30), autoincrement=False, nullable=True - ), - sa.Column( - "first_name", sa.String(length=30), autoincrement=False, nullable=True - ), - sa.Column( - "middle_initial", sa.String(length=30), autoincrement=False, nullable=True - ), - sa.Column( - "last_name", sa.String(length=30), autoincrement=False, nullable=True - ), + op.create_table( + "parties_history", + sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), + sa.Column("party_type", sa.String(length=30), autoincrement=False, nullable=True), + sa.Column("first_name", sa.String(length=30), autoincrement=False, nullable=True), + sa.Column("middle_initial", sa.String(length=30), autoincrement=False, nullable=True), + sa.Column("last_name", sa.String(length=30), autoincrement=False, nullable=True), sa.Column("title", sa.String(length=1000), autoincrement=False, nullable=True), - sa.Column( - "organization_name", - sa.String(length=150), - autoincrement=False, - nullable=True, - ), - sa.Column( - "identifier", sa.String(length=10), autoincrement=False, nullable=True - ), + sa.Column("organization_name", sa.String(length=150), autoincrement=False, nullable=True), + sa.Column("identifier", sa.String(length=10), autoincrement=False, nullable=True), sa.Column("email", sa.String(length=254), autoincrement=False, nullable=True), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "delivery_address_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "mailing_address_id", sa.Integer(), autoincrement=False, nullable=True - ), + sa.Column("delivery_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("mailing_address_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -1085,19 +733,9 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("parties_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_parties_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_parties_history_first_name"), ["first_name"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_parties_history_middle_initial"), - ["middle_initial"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_parties_history_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_parties_history_first_name"), ["first_name"], unique=False) + batch_op.create_index(batch_op.f("ix_parties_history_middle_initial"), ["middle_initial"], unique=False) op.create_table( "request_tracker", @@ -1120,14 +758,13 @@ def upgrade(): sa.Column("request_object", sa.Text(), nullable=True), sa.Column("response_object", sa.Text(), nullable=True), sa.Column("retry_number", sa.Integer(), nullable=False), - sa.Column( - "service_name", sa.Enum("BN_HUB", name="servicename"), nullable=False - ), + sa.Column("service_name", sa.Enum("BN_HUB", name="servicename"), nullable=False), sa.Column("creation_date", sa.DateTime(timezone=True), nullable=True), sa.Column("last_modified", sa.DateTime(timezone=True), nullable=True), sa.Column("is_admin", sa.Boolean(), nullable=True), sa.Column("message_id", sa.String(length=60), nullable=True), sa.Column("legal_entity_id", sa.Integer(), nullable=True), + sa.Column("alternate_name_id", sa.Integer(), nullable=True), sa.Column("filing_id", sa.Integer(), nullable=True), sa.ForeignKeyConstraint( ["filing_id"], @@ -1137,17 +774,16 @@ def upgrade(): ["legal_entity_id"], ["legal_entities.id"], ), + sa.ForeignKeyConstraint( + ["alternate_name_id"], + ["alternate_names.id"], + ), sa.PrimaryKeyConstraint("id"), ) with op.batch_alter_table("request_tracker", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_request_tracker_filing_id"), ["filing_id"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_request_tracker_legal_entity_id"), - ["legal_entity_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_request_tracker_filing_id"), ["filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_request_tracker_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_request_tracker_alternate_name_id"), ["alternate_name_id"], unique=False) op.create_table( "role_addresses", @@ -1192,11 +828,7 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("role_addresses", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_role_addresses_change_filing_id"), - ["change_filing_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_role_addresses_change_filing_id"), ["change_filing_id"], unique=False) op.create_table( "role_addresses_history", @@ -1219,12 +851,8 @@ def upgrade(): ), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "delivery_address_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "mailing_address_id", sa.Integer(), autoincrement=False, nullable=True - ), + sa.Column("delivery_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("mailing_address_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -1248,9 +876,7 @@ def upgrade(): ) with op.batch_alter_table("role_addresses_history", schema=None) as batch_op: batch_op.create_index( - batch_op.f("ix_role_addresses_history_change_filing_id"), - ["change_filing_id"], - unique=False, + batch_op.f("ix_role_addresses_history_change_filing_id"), ["change_filing_id"], unique=False ) op.create_table( @@ -1279,14 +905,8 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("share_classes", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_share_classes_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_share_classes_name"), ["name"], unique=False - ) + batch_op.create_index(batch_op.f("ix_share_classes_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_share_classes_name"), ["name"], unique=False) op.create_table( "share_classes_history", @@ -1298,9 +918,7 @@ def upgrade(): sa.Column("par_value_flag", sa.Boolean(), autoincrement=False, nullable=True), sa.Column("par_value", sa.Float(), autoincrement=False, nullable=True), sa.Column("currency", sa.String(length=10), autoincrement=False, nullable=True), - sa.Column( - "special_rights_flag", sa.Boolean(), autoincrement=False, nullable=True - ), + sa.Column("special_rights_flag", sa.Boolean(), autoincrement=False, nullable=True), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), @@ -1318,13 +936,9 @@ def upgrade(): ) with op.batch_alter_table("share_classes_history", schema=None) as batch_op: batch_op.create_index( - batch_op.f("ix_share_classes_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_share_classes_history_name"), ["name"], unique=False + batch_op.f("ix_share_classes_history_change_filing_id"), ["change_filing_id"], unique=False ) + batch_op.create_index(batch_op.f("ix_share_classes_history_name"), ["name"], unique=False) op.create_table( "dc_issued_credentials", @@ -1332,10 +946,12 @@ def upgrade(): sa.Column("dc_definition_id", sa.Integer(), nullable=True), sa.Column("dc_connection_id", sa.Integer(), nullable=True), sa.Column("credential_exchange_id", sa.String(length=100), nullable=True), - sa.Column("credential_id", sa.String(length=100), nullable=True), + sa.Column("credential_id", sa.String(length=10), nullable=True), sa.Column("is_issued", sa.Boolean(), nullable=True), sa.Column("date_of_issue", sa.DateTime(timezone=True), nullable=True), sa.Column("is_revoked", sa.Boolean(), nullable=True), + sa.Column("credential_revocation_id", sa.String(length=10), nullable=True), + sa.Column("revocation_registry_id", sa.String(length=200), nullable=True), sa.ForeignKeyConstraint( ["dc_connection_id"], ["dc_connections.id"], @@ -1346,6 +962,24 @@ def upgrade(): ), sa.PrimaryKeyConstraint("id"), ) + + op.create_table( + "dc_issued_business_user_credentials", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("legal_entity_id", sa.Integer(), nullable=True), # Allow null values + sa.Column("alternate_name_id", sa.Integer(), nullable=True), # Allow null values + sa.ForeignKeyConstraint(["legal_entity_id"], ["legal_entities.id"]), + sa.ForeignKeyConstraint(["alternate_name_id"], ["alternate_names.id"]), + sa.ForeignKeyConstraint(["user_id"], ["users.id"]), + sa.PrimaryKeyConstraint("id"), + ) + + # Add a check constraint to ensure at least one of legal_entity_id or alternate_name_id is non-null + op.execute( + "ALTER TABLE dc_issued_business_user_credentials ADD CONSTRAINT at_least_one_non_null CHECK (legal_entity_id IS NOT NULL OR alternate_name_id IS NOT NULL)" + ) + op.create_table( "entity_roles", sa.Column("id", sa.Integer(), nullable=False), @@ -1419,32 +1053,14 @@ def upgrade(): autoincrement=False, nullable=False, ), - sa.Column( - "appointment_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "cessation_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), + sa.Column("appointment_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("cessation_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "related_entity_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "related_colin_entity_id", sa.Integer(), autoincrement=False, nullable=True - ), + sa.Column("related_entity_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("related_colin_entity_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("filing_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "delivery_address_id", sa.Integer(), autoincrement=False, nullable=True - ), - sa.Column( - "mailing_address_id", sa.Integer(), autoincrement=False, nullable=True - ), + sa.Column("delivery_address_id", sa.Integer(), autoincrement=False, nullable=True), + sa.Column("mailing_address_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -1503,18 +1119,8 @@ def upgrade(): "party_roles_history", sa.Column("id", sa.Integer(), autoincrement=False, nullable=False), sa.Column("role", sa.String(length=30), autoincrement=False, nullable=True), - sa.Column( - "appointment_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), - sa.Column( - "cessation_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ), + sa.Column("appointment_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), + sa.Column("cessation_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("party_id", sa.Integer(), autoincrement=False, nullable=True), @@ -1568,11 +1174,7 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("resolutions", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_resolutions_change_filing_id"), - ["change_filing_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_resolutions_change_filing_id"), ["change_filing_id"], unique=False) op.create_table( "resolutions_history", @@ -1585,9 +1187,7 @@ def upgrade(): sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("signing_party_id", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "signing_legal_entity_id", sa.Integer(), autoincrement=False, nullable=True - ), + sa.Column("signing_legal_entity_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), sa.Column("changed", sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( @@ -1610,11 +1210,7 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("resolutions_history", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_resolutions_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_resolutions_history_change_filing_id"), ["change_filing_id"], unique=False) op.create_table( "share_series", @@ -1639,14 +1235,8 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("share_series", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_share_series_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_share_series_name"), ["name"], unique=False - ) + batch_op.create_index(batch_op.f("ix_share_series_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_share_series_name"), ["name"], unique=False) op.create_table( "share_series_history", @@ -1655,9 +1245,7 @@ def upgrade(): sa.Column("priority", sa.Integer(), autoincrement=False, nullable=True), sa.Column("max_share_flag", sa.Boolean(), autoincrement=False, nullable=True), sa.Column("max_shares", sa.Integer(), autoincrement=False, nullable=True), - sa.Column( - "special_rights_flag", sa.Boolean(), autoincrement=False, nullable=True - ), + sa.Column("special_rights_flag", sa.Boolean(), autoincrement=False, nullable=True), sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("share_class_id", sa.Integer(), autoincrement=False, nullable=True), sa.Column("version", sa.Integer(), autoincrement=False, nullable=False), @@ -1675,279 +1263,162 @@ def upgrade(): ) with op.batch_alter_table("share_series_history", schema=None) as batch_op: batch_op.create_index( - batch_op.f("ix_share_series_history_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_share_series_history_name"), ["name"], unique=False + batch_op.f("ix_share_series_history_change_filing_id"), ["change_filing_id"], unique=False ) + batch_op.create_index(batch_op.f("ix_share_series_history_name"), ["name"], unique=False) with op.batch_alter_table("filings", schema=None) as batch_op: - batch_op.add_column( - sa.Column("completion_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("filing_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("filing_type", sa.String(length=30), nullable=True) - ) - batch_op.add_column( - sa.Column("filing_sub_type", sa.String(length=30), nullable=True) - ) - batch_op.add_column( - sa.Column( - "filing_json", postgresql.JSONB(astext_type=sa.Text()), nullable=True - ) - ) - batch_op.add_column( - sa.Column( - "meta_data", postgresql.JSONB(astext_type=sa.Text()), nullable=True - ) - ) - batch_op.add_column( - sa.Column("payment_status_code", sa.String(length=50), nullable=True) - ) - batch_op.add_column( - sa.Column("payment_id", sa.String(length=4096), nullable=True) - ) - batch_op.add_column( - sa.Column( - "payment_completion_date", sa.DateTime(timezone=True), nullable=True - ) - ) + batch_op.add_column(sa.Column("completion_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("filing_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("filing_type", sa.String(length=30), nullable=True)) + batch_op.add_column(sa.Column("filing_sub_type", sa.String(length=30), nullable=True)) + batch_op.add_column(sa.Column("filing_json", postgresql.JSONB(astext_type=sa.Text()), nullable=True)) + batch_op.add_column(sa.Column("meta_data", postgresql.JSONB(astext_type=sa.Text()), nullable=True)) + batch_op.add_column(sa.Column("payment_status_code", sa.String(length=50), nullable=True)) + batch_op.add_column(sa.Column("payment_id", sa.String(length=4096), nullable=True)) + batch_op.add_column(sa.Column("payment_completion_date", sa.DateTime(timezone=True), nullable=True)) batch_op.add_column(sa.Column("status", sa.String(length=20), nullable=True)) batch_op.add_column(sa.Column("source", sa.String(length=15), nullable=True)) batch_op.add_column(sa.Column("paper_only", sa.Boolean(), nullable=True)) batch_op.add_column(sa.Column("colin_only", sa.Boolean(), nullable=True)) - batch_op.add_column( - sa.Column("payment_account", sa.String(length=30), nullable=True) - ) - batch_op.add_column( - sa.Column("effective_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("submitter_roles", sa.String(length=200), nullable=True) - ) - batch_op.add_column( - sa.Column( - "tech_correction_json", - postgresql.JSONB(astext_type=sa.Text()), - nullable=True, - ) - ) - batch_op.add_column( - sa.Column("court_order_file_number", sa.String(length=20), nullable=True) - ) - batch_op.add_column( - sa.Column("court_order_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column( - "court_order_effect_of_order", sa.String(length=500), nullable=True - ) - ) - batch_op.add_column( - sa.Column("order_details", sa.String(length=2000), nullable=True) - ) + batch_op.add_column(sa.Column("payment_account", sa.String(length=30), nullable=True)) + batch_op.add_column(sa.Column("effective_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("submitter_roles", sa.String(length=200), nullable=True)) + batch_op.add_column(sa.Column("tech_correction_json", postgresql.JSONB(astext_type=sa.Text()), nullable=True)) + batch_op.add_column(sa.Column("court_order_file_number", sa.String(length=20), nullable=True)) + batch_op.add_column(sa.Column("court_order_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("court_order_effect_of_order", sa.String(length=500), nullable=True)) + batch_op.add_column(sa.Column("order_details", sa.String(length=2000), nullable=True)) batch_op.add_column(sa.Column("deletion_locked", sa.Boolean(), nullable=True)) - batch_op.add_column( - sa.Column("approval_type", sa.String(length=15), nullable=True) - ) - batch_op.add_column( - sa.Column("application_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("notice_date", sa.DateTime(timezone=True), nullable=True) - ) + batch_op.add_column(sa.Column("approval_type", sa.String(length=15), nullable=True)) + batch_op.add_column(sa.Column("application_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("notice_date", sa.DateTime(timezone=True), nullable=True)) batch_op.add_column(sa.Column("transaction_id", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("legal_entity_id", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("alternate_name_id", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("temp_reg", sa.String(length=10), nullable=True)) batch_op.add_column(sa.Column("submitter_id", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("parent_filing_id", sa.Integer(), nullable=True)) batch_op.create_foreign_key(None, "users", ["submitter_id"], ["id"]) - batch_op.create_foreign_key( - None, "registration_bootstrap", ["temp_reg"], ["identifier"] - ) + batch_op.create_foreign_key(None, "registration_bootstrap", ["temp_reg"], ["identifier"]) batch_op.create_foreign_key(None, "filings", ["parent_filing_id"], ["id"]) batch_op.create_foreign_key(None, "legal_entities", ["legal_entity_id"], ["id"]) + batch_op.create_foreign_key(None, "alternate_names", ["alternate_name_id"], ["id"]) with op.batch_alter_table("legal_entities", schema=None) as batch_op: - batch_op.add_column( - sa.Column("last_modified", sa.DateTime(timezone=True), nullable=True) - ) + batch_op.add_column(sa.Column("last_modified", sa.DateTime(timezone=True), nullable=True)) batch_op.add_column(sa.Column("last_ledger_id", sa.Integer(), nullable=True)) - batch_op.add_column( - sa.Column("last_remote_ledger_id", sa.Integer(), nullable=True) - ) - batch_op.add_column( - sa.Column( - "last_ledger_timestamp", sa.DateTime(timezone=True), nullable=True - ) - ) - batch_op.add_column( - sa.Column("last_ar_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("last_agm_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("last_coa_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("last_cod_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("legal_name", sa.String(length=1000), nullable=True) - ) - batch_op.add_column( - sa.Column("entity_type", sa.String(length=15), nullable=True) - ) - batch_op.add_column( - sa.Column("founding_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("start_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column( - "restoration_expiry_date", sa.DateTime(timezone=True), nullable=True - ) - ) - batch_op.add_column( - sa.Column("dissolution_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column("cco_expiry_date", sa.DateTime(timezone=True), nullable=True) - ) - batch_op.add_column( - sa.Column( - "continuation_out_date", sa.DateTime(timezone=True), nullable=True - ) - ) - batch_op.add_column( - sa.Column("identifier", sa.String(length=10), nullable=True) - ) + batch_op.add_column(sa.Column("last_remote_ledger_id", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("last_ledger_timestamp", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("last_ar_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("last_agm_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("last_coa_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("last_cod_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("legal_name", sa.String(length=1000), nullable=True)) + batch_op.add_column(sa.Column("entity_type", sa.String(length=15), nullable=True)) + batch_op.add_column(sa.Column("founding_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("start_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("restoration_expiry_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("dissolution_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("cco_expiry_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("continuation_out_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("identifier", sa.String(length=10), nullable=True)) batch_op.add_column(sa.Column("tax_id", sa.String(length=15), nullable=True)) - batch_op.add_column( - sa.Column("fiscal_year_end_date", sa.DateTime(timezone=True), nullable=True) - ) + batch_op.add_column(sa.Column("fiscal_year_end_date", sa.DateTime(timezone=True), nullable=True)) batch_op.add_column(sa.Column("restriction_ind", sa.Boolean(), nullable=True)) batch_op.add_column(sa.Column("last_ar_year", sa.Integer(), nullable=True)) - batch_op.add_column( - sa.Column("last_ar_reminder_year", sa.Integer(), nullable=True) - ) - batch_op.add_column( - sa.Column("association_type", sa.String(length=50), nullable=True) - ) - batch_op.add_column( - sa.Column( - "state", - sa.Enum("ACTIVE", "HISTORICAL", "LIQUIDATION", name="state"), - nullable=True, - ) - ) + batch_op.add_column(sa.Column("last_ar_reminder_year", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("association_type", sa.String(length=50), nullable=True)) + batch_op.add_column(sa.Column("state", sa.Enum("ACTIVE", "HISTORICAL", name="state"), nullable=True)) batch_op.add_column(sa.Column("state_filing_id", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("admin_freeze", sa.Boolean(), nullable=True)) batch_op.add_column(sa.Column("submitter_userid", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("send_ar_ind", sa.Boolean(), nullable=True)) batch_op.add_column(sa.Column("bn9", sa.String(length=9), nullable=True)) - batch_op.add_column( - sa.Column("first_name", sa.String(length=30), nullable=True) - ) - batch_op.add_column( - sa.Column("middle_initial", sa.String(length=30), nullable=True) - ) + batch_op.add_column(sa.Column("first_name", sa.String(length=30), nullable=True)) + batch_op.add_column(sa.Column("middle_initial", sa.String(length=30), nullable=True)) batch_op.add_column(sa.Column("last_name", sa.String(length=30), nullable=True)) - batch_op.add_column( - sa.Column("additional_name", sa.String(length=100), nullable=True) - ) + batch_op.add_column(sa.Column("additional_name", sa.String(length=100), nullable=True)) batch_op.add_column(sa.Column("title", sa.String(length=1000), nullable=True)) batch_op.add_column(sa.Column("email", sa.String(length=254), nullable=True)) - batch_op.add_column( - sa.Column("delivery_address_id", sa.Integer(), nullable=True) - ) - batch_op.add_column( - sa.Column("mailing_address_id", sa.Integer(), nullable=True) - ) + batch_op.add_column(sa.Column("delivery_address_id", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("mailing_address_id", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("naics_key", sa.String(length=50), nullable=True)) + batch_op.add_column(sa.Column("naics_code", sa.String(length=10), nullable=True)) + batch_op.add_column(sa.Column("naics_description", sa.String(length=300), nullable=True)) + batch_op.add_column(sa.Column("foreign_jurisdiction", sa.String(length=10), nullable=True)) + batch_op.add_column(sa.Column("foreign_jurisdiction_region", sa.String(length=10), nullable=True)) + batch_op.add_column(sa.Column("foreign_identifier", sa.String(length=15), nullable=True)) + batch_op.add_column(sa.Column("foreign_legal_name", sa.String(length=1000), nullable=True)) + batch_op.add_column(sa.Column("foreign_legal_type", sa.String(length=10), nullable=True)) + batch_op.add_column(sa.Column("foreign_incorporation_date", sa.DateTime(timezone=True), nullable=True)) + batch_op.add_column(sa.Column("version", sa.Integer(), nullable=False)) + batch_op.create_index(batch_op.f("ix_legal_entities_entity_type"), ["entity_type"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_first_name"), ["first_name"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_identifier"), ["identifier"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_legal_name"), ["legal_name"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_middle_initial"), ["middle_initial"], unique=False) + batch_op.create_index(batch_op.f("ix_legal_entities_tax_id"), ["tax_id"], unique=False) + batch_op.create_foreign_key(None, "addresses", ["mailing_address_id"], ["id"]) + batch_op.create_foreign_key(None, "users", ["submitter_userid"], ["id"]) + batch_op.create_foreign_key(None, "addresses", ["delivery_address_id"], ["id"]) + batch_op.create_foreign_key(None, "filings", ["state_filing_id"], ["id"]) + + with op.batch_alter_table("alternate_names", schema=None) as batch_op: + batch_op.add_column(sa.Column("identifier", sa.String(length=10), nullable=True)) + batch_op.add_column(sa.Column("name_type", sa.Enum("DBA", "TRANSLATION", name="nametype"), nullable=False)) + batch_op.add_column(sa.Column("name", sa.String(length=1000), nullable=False)) + batch_op.add_column(sa.Column("bn15", sa.String(length=20), nullable=True)) + batch_op.add_column(sa.Column("start_date", sa.DateTime(timezone=True), nullable=False)) + batch_op.add_column(sa.Column("end_date", sa.DateTime(timezone=True), nullable=True)) batch_op.add_column( - sa.Column("naics_code", sa.String(length=10), nullable=True) - ) - batch_op.add_column( - sa.Column("naics_description", sa.String(length=300), nullable=True) - ) - batch_op.add_column( - sa.Column("foreign_jurisdiction", sa.String(length=10), nullable=True) - ) - batch_op.add_column( - sa.Column( - "foreign_jurisdiction_region", sa.String(length=10), nullable=True - ) - ) - batch_op.add_column( - sa.Column("foreign_identifier", sa.String(length=15), nullable=True) - ) - batch_op.add_column( - sa.Column("foreign_legal_name", sa.String(length=1000), nullable=True) + sa.Column("business_start_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True) ) batch_op.add_column( - sa.Column("foreign_legal_type", sa.String(length=10), nullable=True) + sa.Column("dissolution_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True) ) batch_op.add_column( - sa.Column( - "foreign_incorporation_date", sa.DateTime(timezone=True), nullable=True - ) + sa.Column("state", sa.Enum("ACTIVE", "HISTORICAL", name="state"), autoincrement=False, nullable=True) ) + batch_op.add_column(sa.Column("state_filing_id", sa.Integer(), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("admin_freeze", sa.Boolean(), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("last_modified", sa.DateTime(timezone=True), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("legal_entity_id", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("entity_type", sa.String(length=15), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("colin_entity_id", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("change_filing_id", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("email", sa.String(length=254), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("delivery_address_id", sa.Integer(), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("mailing_address_id", sa.Integer(), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("naics_key", sa.String(length=50), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("naics_code", sa.String(length=10), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column("naics_description", sa.String(length=300), autoincrement=False, nullable=True)) batch_op.add_column(sa.Column("version", sa.Integer(), nullable=False)) - batch_op.create_index( - batch_op.f("ix_legal_entities_entity_type"), ["entity_type"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_first_name"), ["first_name"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_identifier"), ["identifier"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_legal_name"), ["legal_name"], unique=False - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_middle_initial"), - ["middle_initial"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_legal_entities_tax_id"), ["tax_id"], unique=False - ) - batch_op.create_foreign_key(None, "addresses", ["mailing_address_id"], ["id"]) - batch_op.create_foreign_key(None, "users", ["submitter_userid"], ["id"]) batch_op.create_foreign_key(None, "addresses", ["delivery_address_id"], ["id"]) + batch_op.create_foreign_key(None, "addresses", ["mailing_address_id"], ["id"]) + batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) + batch_op.create_foreign_key(None, "legal_entities", ["legal_entity_id"], ["id"]) + batch_op.create_foreign_key(None, "colin_entities", ["colin_entity_id"], ["id"]) + batch_op.create_foreign_key(None, "filings", ["state_filing_id"], ["id"]) + batch_op.create_index(batch_op.f("ix_alternate_names_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_alternate_names_name"), ["name"], unique=False) + batch_op.create_index(batch_op.f("ix_alternate_names_identifier"), ["identifier"], unique=False) + batch_op.create_index(batch_op.f("ix_alternate_names_entity_type"), ["entity_type"], unique=False) with op.batch_alter_table("offices", schema=None) as batch_op: - batch_op.add_column( - sa.Column("office_type", sa.String(length=75), nullable=True) - ) - batch_op.add_column( - sa.Column("deactivated_date", sa.DateTime(timezone=True), nullable=True) - ) + batch_op.add_column(sa.Column("office_type", sa.String(length=75), nullable=True)) + batch_op.add_column(sa.Column("deactivated_date", sa.DateTime(timezone=True), nullable=True)) batch_op.add_column(sa.Column("change_filing_id", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("legal_entity_id", sa.Integer(), nullable=True)) + batch_op.add_column(sa.Column("alternate_name_id", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("version", sa.Integer(), nullable=False)) - batch_op.create_index( - batch_op.f("ix_offices_change_filing_id"), - ["change_filing_id"], - unique=False, - ) - batch_op.create_index( - batch_op.f("ix_offices_legal_entity_id"), ["legal_entity_id"], unique=False - ) + batch_op.create_index(batch_op.f("ix_offices_change_filing_id"), ["change_filing_id"], unique=False) + batch_op.create_index(batch_op.f("ix_offices_legal_entity_id"), ["legal_entity_id"], unique=False) + batch_op.create_index(batch_op.f("ix_offices_alternate_name_id"), ["alternate_name_id"], unique=False) batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) - batch_op.create_foreign_key( - None, "office_types", ["office_type"], ["identifier"] - ) + batch_op.create_foreign_key(None, "office_types", ["office_type"], ["identifier"]) batch_op.create_foreign_key(None, "legal_entities", ["legal_entity_id"], ["id"]) + batch_op.create_foreign_key(None, "alternate_names", ["alternate_name_id"], ["id"]) # ### end Alembic commands ### @@ -1958,11 +1429,14 @@ def downgrade(): batch_op.drop_constraint(None, type_="foreignkey") batch_op.drop_constraint(None, type_="foreignkey") batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_constraint(None, type_="foreignkey") batch_op.drop_index(batch_op.f("ix_offices_legal_entity_id")) batch_op.drop_index(batch_op.f("ix_offices_change_filing_id")) + batch_op.drop_index(batch_op.f("ix_offices_alternate_name_id")) batch_op.drop_column("version") batch_op.drop_column("legal_entity_id") batch_op.drop_column("change_filing_id") + batch_op.drop_column("alternate_name_id") batch_op.drop_column("deactivated_date") batch_op.drop_column("office_type") @@ -1970,6 +1444,7 @@ def downgrade(): batch_op.drop_constraint(None, type_="foreignkey") batch_op.drop_constraint(None, type_="foreignkey") batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_constraint(None, type_="foreignkey") batch_op.drop_index(batch_op.f("ix_legal_entities_tax_id")) batch_op.drop_index(batch_op.f("ix_legal_entities_middle_initial")) batch_op.drop_index(batch_op.f("ix_legal_entities_legal_name")) @@ -2024,6 +1499,41 @@ def downgrade(): batch_op.drop_column("last_ledger_id") batch_op.drop_column("last_modified") + with op.batch_alter_table("alternate_names", schema=None) as batch_op: + batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_constraint(None, type_="foreignkey") + batch_op.drop_index(batch_op.f("ix_alternate_names_change_filing_id")) + batch_op.drop_index(batch_op.f("ix_alternate_names_name")) + batch_op.drop_index(batch_op.f("ix_alternate_names_identifier")) + batch_op.drop_index(batch_op.f("ix_alternate_names_entity_type")) + batch_op.drop_column("identifier") + batch_op.drop_column("name_type") + batch_op.drop_column("name") + batch_op.drop_column("bn15") + batch_op.drop_column("start_date") + batch_op.drop_column("end_date") + batch_op.drop_column("business_start_date") + batch_op.drop_column("dissolution_date") + batch_op.drop_column("state") + batch_op.drop_column("state_filing_id") + batch_op.drop_column("admin_freeze") + batch_op.drop_column("last_modified") + batch_op.drop_column("legal_entity_id") + batch_op.drop_column("entity_type") + batch_op.drop_column("colin_entity_id") + batch_op.drop_column("change_filing_id") + batch_op.drop_column("email") + batch_op.drop_column("delivery_address_id") + batch_op.drop_column("mailing_address_id") + batch_op.drop_column("naics_key") + batch_op.drop_column("naics_code") + batch_op.drop_column("naics_description") + batch_op.drop_column("version") + with op.batch_alter_table("filings", schema=None) as batch_op: batch_op.drop_constraint(None, type_="foreignkey") batch_op.drop_constraint(None, type_="foreignkey") @@ -2033,6 +1543,7 @@ def downgrade(): batch_op.drop_column("submitter_id") batch_op.drop_column("temp_reg") batch_op.drop_column("legal_entity_id") + batch_op.drop_column("alternate_name_id") batch_op.drop_column("transaction_id") batch_op.drop_column("notice_date") batch_op.drop_column("application_date") @@ -2083,6 +1594,7 @@ def downgrade(): op.drop_table("entity_roles_history") op.drop_table("entity_roles") op.drop_table("dc_issued_credentials") + op.drop_table("dc_issued_business_user_credentials") with op.batch_alter_table("share_classes_history", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_share_classes_history_name")) batch_op.drop_index(batch_op.f("ix_share_classes_history_change_filing_id")) @@ -2103,6 +1615,7 @@ def downgrade(): op.drop_table("role_addresses") with op.batch_alter_table("request_tracker", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_request_tracker_legal_entity_id")) + batch_op.drop_index(batch_op.f("ix_request_tracker_alternate_name_id")) batch_op.drop_index(batch_op.f("ix_request_tracker_filing_id")) op.drop_table("request_tracker") @@ -2121,6 +1634,7 @@ def downgrade(): with op.batch_alter_table("offices_history", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_offices_history_legal_entity_id")) batch_op.drop_index(batch_op.f("ix_offices_history_change_filing_id")) + batch_op.drop_index(batch_op.f("ix_offices_history_alternate_name_id")) op.drop_table("offices_history") with op.batch_alter_table("naics_elements", schema=None) as batch_op: @@ -2157,6 +1671,7 @@ def downgrade(): with op.batch_alter_table("comments", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_comments_staff_id")) batch_op.drop_index(batch_op.f("ix_comments_legal_entity_id")) + batch_op.drop_index(batch_op.f("ix_comments_alternate_name_id")) batch_op.drop_index(batch_op.f("ix_comments_filing_id")) op.drop_table("comments") @@ -2177,10 +1692,16 @@ def downgrade(): op.drop_table("colin_entities") with op.batch_alter_table("alternate_names_history", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_alternate_names_history_change_filing_id")) + batch_op.drop_index(batch_op.f("ix_alternate_names_history_name")) + batch_op.drop_index(batch_op.f("ix_alternate_names_history_identifier")) + batch_op.drop_index(batch_op.f("ix_alternate_names_history_entity_type")) op.drop_table("alternate_names_history") with op.batch_alter_table("alternate_names", schema=None) as batch_op: batch_op.drop_index(batch_op.f("ix_alternate_names_change_filing_id")) + batch_op.drop_index(batch_op.f("ix_alternate_names_name")) + batch_op.drop_index(batch_op.f("ix_alternate_names_identifier")) + batch_op.drop_index(batch_op.f("ix_alternate_names_history_entity_type")) op.drop_table("alternate_names") with op.batch_alter_table("aliases_history", schema=None) as batch_op: @@ -2198,6 +1719,7 @@ def downgrade(): batch_op.drop_index(batch_op.f("ix_addresses_history_legal_entity_id")) batch_op.drop_index(batch_op.f("ix_addresses_history_change_filing_id")) batch_op.drop_index(batch_op.f("ix_addresses_history_address_type")) + batch_op.drop_index(batch_op.f("ix_addresses_history_alternate_name_id")) op.drop_table("addresses_history") with op.batch_alter_table("users_history", schema=None) as batch_op: @@ -2233,6 +1755,7 @@ def downgrade(): batch_op.drop_index(batch_op.f("ix_addresses_legal_entity_id")) batch_op.drop_index(batch_op.f("ix_addresses_change_filing_id")) batch_op.drop_index(batch_op.f("ix_addresses_address_type")) + batch_op.drop_index(batch_op.f("ix_addresses_alternate_name_id")) op.drop_table("addresses") # ### end Alembic commands ### diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/03201f7bc580_first.py b/python/common/business-registry-model/src/business_model_migrations/versions/03201f7bc580_first.py index 86d221be4e..08674849c0 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/03201f7bc580_first.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/03201f7bc580_first.py @@ -1,7 +1,7 @@ """empty message Revision ID: 03201f7bc580 -Revises: +Revises: Create Date: 2023-06-03 23:44:57.138750 """ @@ -18,18 +18,16 @@ def upgrade(): # ### commands auto generated by Alembic - please adjust! ### + op.create_table("filings", sa.Column("id", sa.Integer(), nullable=False), sa.PrimaryKeyConstraint("id")) + op.create_table("offices", sa.Column("id", sa.Integer(), nullable=False), sa.PrimaryKeyConstraint("id")) op.create_table( - "filings", - sa.Column("id", sa.Integer(), nullable=False), - sa.PrimaryKeyConstraint("id"), - ) - op.create_table( - "offices", + "legal_entities", sa.Column("id", sa.Integer(), nullable=False), sa.PrimaryKeyConstraint("id"), + sqlite_autoincrement=True, ) op.create_table( - "legal_entities", + "alternate_names", sa.Column("id", sa.Integer(), nullable=False), sa.PrimaryKeyConstraint("id"), sqlite_autoincrement=True, @@ -40,6 +38,7 @@ def upgrade(): def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_table("legal_entities") + op.drop_table("alternate_names") op.drop_table("filings") op.drop_table("offices") # ### end Alembic commands ### diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/2fd104a5f3b5_.py b/python/common/business-registry-model/src/business_model_migrations/versions/2fd104a5f3b5_.py index fd13db2ab4..29a5e0bc9f 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/2fd104a5f3b5_.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/2fd104a5f3b5_.py @@ -23,11 +23,7 @@ def upgrade(): batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) with op.batch_alter_table("party_roles_history", schema=None) as batch_op: - batch_op.add_column( - sa.Column( - "change_filing_id", sa.Integer(), autoincrement=False, nullable=True - ) - ) + batch_op.add_column(sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True)) batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) # ### end Alembic commands ### diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/3d8eb786f4c2_add_sequences.py b/python/common/business-registry-model/src/business_model_migrations/versions/3d8eb786f4c2_add_sequences.py index c61759554c..c1cd42bdf0 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/3d8eb786f4c2_add_sequences.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/3d8eb786f4c2_add_sequences.py @@ -19,7 +19,7 @@ def upgrade(): op.execute("CREATE SEQUENCE legal_entity_identifier_coop START 1002395") op.execute("CREATE SEQUENCE legal_entity_identifier_sp_gp START 1002395") - op.execute("CREATE SEQUENCE legal_entity_identifier_person START 0000001") + op.execute("CREATE SEQUENCE legal_entity_identifier_person START 1000000") def downgrade(): diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/4aed1fbbba29_.py b/python/common/business-registry-model/src/business_model_migrations/versions/4aed1fbbba29_.py index 896a629193..010b80e400 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/4aed1fbbba29_.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/4aed1fbbba29_.py @@ -38,11 +38,7 @@ def upgrade(): sqlite_autoincrement=True, ) with op.batch_alter_table("consent_continuation_outs", schema=None) as batch_op: - batch_op.create_index( - batch_op.f("ix_consent_continuation_outs_filing_id"), - ["filing_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_consent_continuation_outs_filing_id"), ["filing_id"], unique=False) op.create_table( "sent_to_gazette", diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/5238dd8fb805_.py b/python/common/business-registry-model/src/business_model_migrations/versions/5238dd8fb805_.py new file mode 100644 index 0000000000..f6bde6f8de --- /dev/null +++ b/python/common/business-registry-model/src/business_model_migrations/versions/5238dd8fb805_.py @@ -0,0 +1,143 @@ +"""amalgamation + +Revision ID: 5238dd8fb805 +Revises: 60d9c14c2b7f +Create Date: 2023-12-13 16:28:23.390151 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + + +# revision identifiers, used by Alembic. +revision = "5238dd8fb805" +down_revision = "60d9c14c2b7f" +branch_labels = None +depends_on = None + +role_enum = postgresql.ENUM("amalgamating", "holding", "primary", name="amalgamating_business_role") +amalgamation_type_enum = postgresql.ENUM("regular", "vertical", "horizontal", name="amalgamation_type") + + +def upgrade(): + # add enum values + role_enum.create(op.get_bind(), checkfirst=True) + amalgamation_type_enum.create(op.get_bind(), checkfirst=True) + + # ========================================================================================== + # amalgamating_businesses/amalgamations/amalgamations_history/amalgamating_businesses_history tables + # ========================================================================================== + + op.create_table( + "amalgamations", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("legal_entity_id", sa.Integer(), nullable=False), + sa.Column("filing_id", sa.Integer(), nullable=False), + sa.Column("amalgamation_date", sa.TIMESTAMP(timezone=True), nullable=False), + sa.Column("court_approval", sa.Boolean(), nullable=False), + sa.Column("version", sa.Integer(), nullable=False), + sa.Column("change_filing_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["filing_id"], ["filings.id"]), + sa.ForeignKeyConstraint(["change_filing_id"], ["filings.id"]), + sa.ForeignKeyConstraint(["legal_entity_id"], ["legal_entities.id"]), + sa.PrimaryKeyConstraint("id"), + sqlite_autoincrement=True, + ) + + # enum added after creating table as DuplicateObject error would be thrown otherwise + op.add_column("amalgamations", sa.Column("amalgamation_type", amalgamation_type_enum, nullable=False)) + + op.create_table( + "amalgamating_businesses", + sa.Column("id", sa.Integer(), primary_key=False), + sa.Column("legal_entity_id", sa.Integer(), nullable=True), + sa.Column("amalgamation_id", sa.Integer(), nullable=False), + sa.Column("foreign_jurisdiction", sa.String(length=10), nullable=True), + sa.Column("foreign_jurisdiction_region", sa.String(length=10), nullable=True), + sa.Column("foreign_name", sa.String(length=100), nullable=True), + sa.Column("foreign_identifier", sa.String(length=50), nullable=True), + sa.Column("version", sa.Integer(), nullable=False), + sa.Column("change_filing_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["legal_entity_id"], ["legal_entities.id"]), + sa.ForeignKeyConstraint(["amalgamation_id"], ["amalgamations.id"]), + sa.ForeignKeyConstraint(["change_filing_id"], ["filings.id"]), + sa.PrimaryKeyConstraint("id"), + sqlite_autoincrement=True, + ) + + # enum added after creating table as DuplicateObject error would be thrown otherwise + op.add_column("amalgamating_businesses", sa.Column("role", role_enum, nullable=False)) + + with op.batch_alter_table("amalgamating_businesses", schema=None) as batch_op: + batch_op.create_index( + batch_op.f("ix_amalgamating_businesses_change_filing_id"), ["change_filing_id"], unique=False + ) + + op.create_table( + "amalgamations_history", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("legal_entity_id", sa.Integer(), nullable=False), + sa.Column("filing_id", sa.Integer(), nullable=False), + sa.Column("amalgamation_date", sa.TIMESTAMP(timezone=True), nullable=False), + sa.Column("court_approval", sa.Boolean(), nullable=False), + sa.Column("version", sa.Integer(), nullable=False), + sa.Column("changed", sa.DateTime(), nullable=True), + sa.Column("change_filing_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(["filing_id"], ["filings.id"]), + sa.ForeignKeyConstraint(["change_filing_id"], ["filings.id"]), + sa.ForeignKeyConstraint(["legal_entity_id"], ["legal_entities.id"]), + sa.PrimaryKeyConstraint("id", "version"), + sqlite_autoincrement=True, + ) + + # enum added after creating table as DuplicateObject error would be thrown otherwise + op.add_column("amalgamations_history", sa.Column("amalgamation_type", amalgamation_type_enum, nullable=False)) + + with op.batch_alter_table("amalgamations_history", schema=None) as batch_op: + batch_op.create_index( + batch_op.f("ix_amalgamations_version_history_legal_entity_id"), ["legal_entity_id"], unique=False + ) + batch_op.create_index(batch_op.f("ix_amalgamations_version_history_filing_id"), ["filing_id"], unique=False) + + op.create_table( + "amalgamating_businesses_history", + sa.Column("id", sa.Integer(), primary_key=False), + sa.Column("legal_entity_id", sa.Integer(), nullable=True), + sa.Column("amalgamation_id", sa.Integer(), nullable=False), + sa.Column("foreign_jurisdiction", sa.String(length=10), nullable=True), + sa.Column("foreign_jurisdiction_region", sa.String(length=10), nullable=True), + sa.Column("foreign_name", sa.String(length=100), nullable=True), + sa.Column("foreign_identifier", sa.String(length=50), nullable=True), + sa.Column("change_filing_id", sa.Integer(), nullable=False), + sa.Column("version", sa.Integer(), nullable=False), + sa.Column("changed", sa.DateTime(), nullable=True), + sa.ForeignKeyConstraint(["legal_entity_id"], ["legal_entities.id"]), + sa.ForeignKeyConstraint(["change_filing_id"], ["filings.id"]), + sa.PrimaryKeyConstraint("id", "version"), + ) + + # enum added after creating table as DuplicateObject error would be thrown otherwise + op.add_column("amalgamating_businesses_history", sa.Column("role", role_enum, nullable=False)) + + with op.batch_alter_table("amalgamating_businesses_history", schema=None) as batch_op: + batch_op.create_index( + batch_op.f("ix_amalgamating_businesses_history_legal_entity_id"), ["legal_entity_id"], unique=False + ) + batch_op.create_index( + batch_op.f("ix_amalgamating_businesses_history_amalgamation_id"), ["amalgamation_id"], unique=False + ) + batch_op.create_index( + batch_op.f("ix_amalgamating_businesses_history_change_filing_id"), ["change_filing_id"], unique=False + ) + + +def downgrade(): + op.drop_table("amalgamating_businesses") + op.drop_table("amalgamations") + op.drop_table("amalgamating_businesses_history") + op.drop_table("amalgamations_history") + + # Drop enum types from the database + amalgamation_type_enum.drop(op.get_bind(), checkfirst=True) + role_enum.drop(op.get_bind(), checkfirst=True) diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/60d9c14c2b7f_.py b/python/common/business-registry-model/src/business_model_migrations/versions/60d9c14c2b7f_.py index ed01401f8a..47609aaab2 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/60d9c14c2b7f_.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/60d9c14c2b7f_.py @@ -26,16 +26,9 @@ def upgrade(): def downgrade(): with op.batch_alter_table("legal_entities", schema=None) as batch_op: - batch_op.add_column( - sa.Column("cco_expiry_date", sa.DateTime(timezone=True), nullable=True) - ) + batch_op.add_column(sa.Column("cco_expiry_date", sa.DateTime(timezone=True), nullable=True)) with op.batch_alter_table("legal_entities_history", schema=None) as batch_op: batch_op.add_column( - sa.Column( - "cco_expiry_date", - sa.DateTime(timezone=True), - autoincrement=False, - nullable=True, - ) + sa.Column("cco_expiry_date", sa.DateTime(timezone=True), autoincrement=False, nullable=True) ) diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/9e36cf10f47c_.py b/python/common/business-registry-model/src/business_model_migrations/versions/9e36cf10f47c_.py index 0b97198e09..a82ddce0d2 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/9e36cf10f47c_.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/9e36cf10f47c_.py @@ -23,23 +23,13 @@ def upgrade(): with op.batch_alter_table("legal_entities", schema=None) as batch_op: batch_op.add_column(sa.Column("change_filing_id", sa.Integer(), nullable=True)) - batch_op.create_index( - batch_op.f("ix_legal_entities_change_filing_id"), - ["change_filing_id"], - unique=False, - ) + batch_op.create_index(batch_op.f("ix_legal_entities_change_filing_id"), ["change_filing_id"], unique=False) batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) with op.batch_alter_table("legal_entities_history", schema=None) as batch_op: - batch_op.add_column( - sa.Column( - "change_filing_id", sa.Integer(), autoincrement=False, nullable=True - ) - ) + batch_op.add_column(sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True)) batch_op.create_index( - batch_op.f("ix_legal_entities_history_change_filing_id"), - ["change_filing_id"], - unique=False, + batch_op.f("ix_legal_entities_history_change_filing_id"), ["change_filing_id"], unique=False ) batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) diff --git a/python/common/business-registry-model/src/business_model_migrations/versions/e7abbdeb252a_.py b/python/common/business-registry-model/src/business_model_migrations/versions/e7abbdeb252a_.py index 4507c0ce49..3373714eca 100644 --- a/python/common/business-registry-model/src/business_model_migrations/versions/e7abbdeb252a_.py +++ b/python/common/business-registry-model/src/business_model_migrations/versions/e7abbdeb252a_.py @@ -23,11 +23,7 @@ def upgrade(): batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) with op.batch_alter_table("entity_roles_history", schema=None) as batch_op: - batch_op.add_column( - sa.Column( - "change_filing_id", sa.Integer(), autoincrement=False, nullable=True - ) - ) + batch_op.add_column(sa.Column("change_filing_id", sa.Integer(), autoincrement=False, nullable=True)) batch_op.create_foreign_key(None, "filings", ["change_filing_id"], ["id"]) # ### end Alembic commands ### diff --git a/queue_services/entity-filer/poetry.lock b/queue_services/entity-filer/poetry.lock index afaa13e483..ff581bb651 100644 --- a/queue_services/entity-filer/poetry.lock +++ b/queue_services/entity-filer/poetry.lock @@ -186,15 +186,12 @@ develop = false datedelta = "^1.4" Flask-SQLAlchemy = "^3.0.5" pycountry = "^22.3.5" -registry-schemas = {git = "https://github.com/bcgov/business-schemas.git", rev = "2.18.10"} +registry-schemas = {git = "https://github.com/bcgov/business-schemas.git", rev = "2.18.19"} sql-versioning = {git = "https://github.com/bcgov/lear.git", branch = "feature-legal-name", subdirectory = "python/common/sql-versioning"} [package.source] -type = "git" -url = "https://github.com/bcgov/lear.git" -reference = "feature-legal-name" -resolved_reference = "d9669d000ae4d5c1761c6a701ca2e9c746360662" -subdirectory = "python/common/business-registry-model" +type = "directory" +url = "../../python/common/business-registry-model" [[package]] name = "cachetools" @@ -1259,6 +1256,28 @@ files = [ {file = "protobuf-4.25.0.tar.gz", hash = "sha256:68f7caf0d4f012fd194a301420cf6aa258366144d814f358c5b32558228afa7c"}, ] +[[package]] +name = "psycopg2" +version = "2.9.9" +description = "psycopg2 - Python-PostgreSQL Database Adapter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psycopg2-2.9.9-cp310-cp310-win32.whl", hash = "sha256:38a8dcc6856f569068b47de286b472b7c473ac7977243593a288ebce0dc89516"}, + {file = "psycopg2-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:426f9f29bde126913a20a96ff8ce7d73fd8a216cfb323b1f04da402d452853c3"}, + {file = "psycopg2-2.9.9-cp311-cp311-win32.whl", hash = "sha256:ade01303ccf7ae12c356a5e10911c9e1c51136003a9a1d92f7aa9d010fb98372"}, + {file = "psycopg2-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:121081ea2e76729acfb0673ff33755e8703d45e926e416cb59bae3a86c6a4981"}, + {file = "psycopg2-2.9.9-cp312-cp312-win32.whl", hash = "sha256:d735786acc7dd25815e89cc4ad529a43af779db2e25aa7c626de864127e5a024"}, + {file = "psycopg2-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:a7653d00b732afb6fc597e29c50ad28087dcb4fbfb28e86092277a559ae4e693"}, + {file = "psycopg2-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:5e0d98cade4f0e0304d7d6f25bbfbc5bd186e07b38eac65379309c4ca3193efa"}, + {file = "psycopg2-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:7e2dacf8b009a1c1e843b5213a87f7c544b2b042476ed7755be813eaf4e8347a"}, + {file = "psycopg2-2.9.9-cp38-cp38-win32.whl", hash = "sha256:ff432630e510709564c01dafdbe996cb552e0b9f3f065eb89bdce5bd31fabf4c"}, + {file = "psycopg2-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:bac58c024c9922c23550af2a581998624d6e02350f4ae9c5f0bc642c633a2d5e"}, + {file = "psycopg2-2.9.9-cp39-cp39-win32.whl", hash = "sha256:c92811b2d4c9b6ea0285942b2e7cac98a59e166d59c588fe5cfe1eda58e72d59"}, + {file = "psycopg2-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:de80739447af31525feddeb8effd640782cf5998e1a4e9192ebdf829717e3913"}, + {file = "psycopg2-2.9.9.tar.gz", hash = "sha256:d1454bde93fb1e224166811694d600e746430c006fbb031ea06ecc2ea41bf156"}, +] + [[package]] name = "pyasn1" version = "0.5.0" @@ -1549,8 +1568,8 @@ attrs = ">=22.2.0" rpds-py = ">=0.7.0" [[package]] -name = "registry-schemas" -version = "2.18.10" +name = "registry_schemas" +version = "2.18.19" description = "A short description of the project" optional = false python-versions = ">=3.6" @@ -1560,14 +1579,15 @@ develop = false [package.dependencies] flask = "*" jsonschema = {version = "*", extras = ["format"]} +referencing = "*" requests = "*" strict-rfc3339 = "*" [package.source] type = "git" url = "https://github.com/bcgov/business-schemas.git" -reference = "2.18.10" -resolved_reference = "9d341fe050bf7844905a3914380e71180d14d336" +reference = "2.18.19" +resolved_reference = "c9f4d10f33fdb14157573acac48945c6e7750f24" [[package]] name = "requests" @@ -2103,4 +2123,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "ca49998a51db9743ea622d92335cc718487a283d7fa3af97ec13c3250a79376e" +content-hash = "12085771b95e9b803a49945e0ba39ad5c5b6d3407105f4bbc2732f093e5da5b4" diff --git a/queue_services/entity-filer/pyproject.toml b/queue_services/entity-filer/pyproject.toml index 4fe49555a5..e5f5118c9e 100644 --- a/queue_services/entity-filer/pyproject.toml +++ b/queue_services/entity-filer/pyproject.toml @@ -16,10 +16,11 @@ python-dateutil = "^2.8.2" python-dotenv = "^1.0.0" sentry-sdk = "^1.28.1" pycountry = "^22.3.5" +psycopg2 = "^2.9.6" pg8000 = "^1.29.8" flask-babel = "^3.1.0" -registry-schemas = {git = "https://github.com/bcgov/business-schemas.git", rev = "2.18.10"} +registry-schemas = {git = "https://github.com/bcgov/business-schemas.git", rev = "2.18.19"} simple_cloudevent = { git = "https://github.com/daxiom/simple-cloudevent.py" } ## sql-versioning = { git = "https://github.com/bcgov/lear.git", subdirectory = "python/common/sql-versioning", branch = "feature-legal-name" } diff --git a/queue_services/entity-filer/src/entity_filer/config.py b/queue_services/entity-filer/src/entity_filer/config.py index 0a2b441b9d..55826aaa7a 100644 --- a/queue_services/entity-filer/src/entity_filer/config.py +++ b/queue_services/entity-filer/src/entity_filer/config.py @@ -136,7 +136,11 @@ class Testing(Config): # pylint: disable=too-few-public-methods DB_NAME = os.getenv("DATABASE_TEST_NAME", "") DB_HOST = os.getenv("DATABASE_TEST_HOST", "") DB_PORT = os.getenv("DATABASE_TEST_PORT", "5432") - SQLALCHEMY_DATABASE_URI = f"postgresql+pg8000://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{int(DB_PORT)}/{DB_NAME}" + # POSTGRESQL + if DB_UNIX_SOCKET := os.getenv("DATABASE_UNIX_SOCKET", None): + SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{DB_USER}:{DB_PASSWORD}@/{DB_NAME}?host={DB_UNIX_SOCKET}" + else: + SQLALCHEMY_DATABASE_URI = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}" # Minio variables MINIO_ENDPOINT = "localhost:9000" diff --git a/queue_services/entity-filer/src/entity_filer/filing_processors/admin_freeze.py b/queue_services/entity-filer/src/entity_filer/filing_processors/admin_freeze.py index 149f4c6b9b..5607a66f64 100644 --- a/queue_services/entity-filer/src/entity_filer/filing_processors/admin_freeze.py +++ b/queue_services/entity-filer/src/entity_filer/filing_processors/admin_freeze.py @@ -18,7 +18,7 @@ import dpath from business_model import Filing, LegalEntity -from entity_filer.exceptions import DefaultException, logger +from entity_filer.exceptions import DefaultException from entity_filer.filing_meta import FilingMeta diff --git a/queue_services/entity-filer/src/entity_filer/filing_processors/change_of_directors.py b/queue_services/entity-filer/src/entity_filer/filing_processors/change_of_directors.py index 52c0a958f1..2ead88356b 100644 --- a/queue_services/entity-filer/src/entity_filer/filing_processors/change_of_directors.py +++ b/queue_services/entity-filer/src/entity_filer/filing_processors/change_of_directors.py @@ -17,7 +17,7 @@ from business_model import LegalEntity, PartyRole -from entity_filer.exceptions import DefaultException, logger +from entity_filer.exceptions import DefaultException from entity_filer.filing_meta import FilingMeta from entity_filer.filing_processors.filing_components import create_role, merge_party, update_director diff --git a/queue_services/entity-filer/src/entity_filer/filing_processors/put_back_on.py b/queue_services/entity-filer/src/entity_filer/filing_processors/put_back_on.py index 11d923d50d..29cf452a59 100644 --- a/queue_services/entity-filer/src/entity_filer/filing_processors/put_back_on.py +++ b/queue_services/entity-filer/src/entity_filer/filing_processors/put_back_on.py @@ -19,7 +19,7 @@ import dpath from business_model import Filing, LegalEntity -from entity_filer.exceptions import DefaultException, logger +from entity_filer.exceptions import DefaultException from entity_filer.filing_meta import FilingMeta from entity_filer.filing_processors.filing_components import filings diff --git a/queue_services/entity-filer/tests/conftest.py b/queue_services/entity-filer/tests/conftest.py index 9765060793..bec1f3cada 100644 --- a/queue_services/entity-filer/tests/conftest.py +++ b/queue_services/entity-filer/tests/conftest.py @@ -12,26 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. """Common setup and fixtures for the pytest suite used by this service.""" -import asyncio import datetime -import json import os import random -import time from contextlib import contextmanager, suppress import business_model_migrations +import psycopg2 import pytest -import requests import sqlalchemy from business_model import db as _db -from flask import Flask, current_app from flask_migrate import Migrate, upgrade - -# from legal_api import db as _db -# from legal_api import jwt as _jwt -from sqlalchemy import event, text -from sqlalchemy.schema import DropConstraint, MetaData +from sqlalchemy import text +from sqlalchemy.orm import scoped_session, sessionmaker from entity_filer import create_app from entity_filer.config import Testing @@ -39,6 +32,78 @@ from . import FROZEN_DATETIME +def create_test_db( + user: str = None, + password: str = None, + database: str = None, + host: str = "localhost", + port: int = 1521, + database_uri: str = None, +) -> bool: + """Create the database in our .devcontainer launched postgres DB. + + Parameters + ------------ + user: str + A datbase user that has create database privledges + password: str + The users password + database: str + The name of the database to create + host: str, Optional + The network name of the server + port: int, Optional + The numeric port number + Return + ----------- + : bool + If the create database succeeded. + """ + if database_uri: + DATABASE_URI = database_uri + else: + DATABASE_URI = f"postgresql://{user}:{password}@{host}:{port}/{user}" + + DATABASE_URI = DATABASE_URI[: DATABASE_URI.rfind("/")] + "/postgres" + + try: + with sqlalchemy.create_engine(DATABASE_URI, isolation_level="AUTOCOMMIT").connect() as conn: + conn.execute(text(f"CREATE DATABASE {database}")) + + return True + except sqlalchemy.exc.ProgrammingError as err: + print(err) # used in the test suite, so on failure print something + return False + + +def drop_test_db( + user: str = None, + password: str = None, + database: str = None, + host: str = "localhost", + port: int = 1521, + database_uri: str = None, +) -> bool: + """Delete the database in our .devcontainer launched postgres DB.""" + if database_uri: + DATABASE_URI = database_uri + else: + DATABASE_URI = f"postgresql://{user}:{password}@{host}:{port}/{user}" + + DATABASE_URI = DATABASE_URI[: DATABASE_URI.rfind("/")] + "/postgres" + + close_all = f""" + SELECT pg_terminate_backend(pg_stat_activity.pid) + FROM pg_stat_activity + WHERE pg_stat_activity.datname = '{database}' + AND pid <> pg_backend_pid(); + """ + with suppress(sqlalchemy.exc.ProgrammingError, psycopg2.OperationalError, Exception): + with sqlalchemy.create_engine(DATABASE_URI, isolation_level="AUTOCOMMIT").connect() as conn: + conn.execute(text(close_all)) + conn.execute(text(f"DROP DATABASE {database}")) + + @contextmanager def not_raises(exception): """Corallary to the pytest raises builtin. @@ -67,7 +132,6 @@ def utcnow(cls): @pytest.fixture(scope="session") def app(): """Return a session-wide application configured in TEST mode.""" - # _app = create_app('testing') app = create_app(Testing) return app @@ -207,7 +271,7 @@ def db(app): # pylint: disable=redefined-outer-name, invalid-name dir_path = os.path.dirname(business_model_migrations.__file__) - migrate = Migrate(app, _db, directory=dir_path, **{"dialect_name": "postgres"}) # noqa F841 + Migrate(app, _db, directory=dir_path) upgrade() yield _db @@ -229,31 +293,16 @@ def session(app, db): # pylint: disable=redefined-outer-name, invalid-name txn = conn.begin() try: - options = dict(bind=conn, binds={}) - # sess = db.create_scoped_session(options=options) - sess = db._make_scoped_session(options=options) + sess = scoped_session( + session_factory=sessionmaker( + bind=conn, + join_transaction_mode="create_savepoint", + ) + ) except Exception as err: print(err) print("done") - # For those who have local databases on bare metal in local time. - # Otherwise some of the returns will come back in local time and unit tests will fail. - # The current DEV database uses UTC. - sess.execute("SET TIME ZONE 'UTC';") - sess.commit() - - # establish a SAVEPOINT just before beginning the test - # (http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html#using-savepoint) - sess.begin_nested() - - @event.listens_for(sess(), "after_transaction_end") - def restart_savepoint(sess2, trans): # pylint: disable=unused-variable - # Detecting whether this is indeed the nested transaction of the test - if trans.nested and not trans._parent.nested: # pylint: disable=protected-access - # Handle where test DOESN'T session.commit(), - sess2.expire_all() - sess.begin_nested() - db.session = sess sql = text("select 1") @@ -263,6 +312,7 @@ def restart_savepoint(sess2, trans): # pylint: disable=unused-variable # Cleanup sess.remove() + db.session.close() # This instruction rollsback any commit that were executed in the tests. txn.rollback() conn.close() @@ -352,75 +402,3 @@ def restart_savepoint(sess2, trans): # pylint: disable=unused-variable # docker_services.start('minio') # docker_services.wait_for_service('minio', 9000) # time.sleep(10) - - -def create_test_db( - user: str = None, - password: str = None, - database: str = None, - host: str = "localhost", - port: int = 1521, - database_uri: str = None, -) -> bool: - """Create the database in our .devcontainer launched postgres DB. - - Parameters - ------------ - user: str - A datbase user that has create database privledges - password: str - The users password - database: str - The name of the database to create - host: str, Optional - The network name of the server - port: int, Optional - The numeric port number - Return - ----------- - : bool - If the create database succeeded. - """ - if database_uri: - DATABASE_URI = database_uri - else: - DATABASE_URI = f"postgresql://{user}:{password}@{host}:{port}/{user}" - - DATABASE_URI = DATABASE_URI[: DATABASE_URI.rfind("/")] + "/postgres" - - try: - with sqlalchemy.create_engine(DATABASE_URI, isolation_level="AUTOCOMMIT").connect() as conn: - conn.execute(text(f"CREATE DATABASE {database}")) - - return True - except sqlalchemy.exc.ProgrammingError as err: - print(err) # used in the test suite, so on failure print something - return False - - -def drop_test_db( - user: str = None, - password: str = None, - database: str = None, - host: str = "localhost", - port: int = 1521, - database_uri: str = None, -) -> bool: - """Delete the database in our .devcontainer launched postgres DB.""" - if database_uri: - DATABASE_URI = database_uri - else: - DATABASE_URI = f"postgresql://{user}:{password}@{host}:{port}/{user}" - - DATABASE_URI = DATABASE_URI[: DATABASE_URI.rfind("/")] + "/postgres" - - close_all = f""" - SELECT pg_terminate_backend(pg_stat_activity.pid) - FROM pg_stat_activity - WHERE pg_stat_activity.datname = '{database}' - AND pid <> pg_backend_pid(); - """ - with suppress(sqlalchemy.exc.ProgrammingError, Exception): - with sqlalchemy.create_engine(DATABASE_URI, isolation_level="AUTOCOMMIT").connect() as conn: - conn.execute(text(close_all)) - conn.execute(text(f"DROP DATABASE {database}")) diff --git a/queue_services/entity-filer/tests/unit/__init__.py b/queue_services/entity-filer/tests/unit/__init__.py index 7be1400587..006fdceb27 100644 --- a/queue_services/entity-filer/tests/unit/__init__.py +++ b/queue_services/entity-filer/tests/unit/__init__.py @@ -402,8 +402,8 @@ def create_business(identifier, legal_type=None, legal_name=None): business = LegalEntity() business.identifier = identifier - business.entity_type = legal_type - business.legal_name = legal_name + business._entity_type = legal_type + business._legal_name = legal_name business = create_business_address(business, Address.DELIVERY) # business = create_business_address(business, Address.MAILING) business.save() @@ -460,11 +460,11 @@ def create_entity(identifier, legal_type, legal_name): from business_model import Address, LegalEntity legal_entity = LegalEntity() - legal_entity.entity_type = legal_type + legal_entity._entity_type = legal_type if legal_entity.entity_type == LegalEntity.EntityTypes.PERSON.value: legal_entity.first_name = "my" legal_entity.last_name = "self" - legal_entity.legal_name = legal_name + legal_entity._legal_name = legal_name legal_entity.identifier = identifier legal_entity.save() return legal_entity @@ -518,7 +518,7 @@ def create_entity_person(party_json): first_name=party_json["officer"].get("firstName", "").upper(), last_name=party_json["officer"].get("lastName", "").upper(), middle_initial=party_json["officer"].get("middleInitial", "").upper(), - entity_type=LegalEntity.EntityTypes.PERSON, + _entity_type=LegalEntity.EntityTypes.PERSON, ) if party_json.get("mailingAddress"): mailing_address = Address( diff --git a/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_business_info.py b/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_business_info.py index d334dba558..87a33b8d45 100644 --- a/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_business_info.py +++ b/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_business_info.py @@ -38,7 +38,7 @@ def test_set_corp_type( """Assert that the corp type is set correctly.""" new_data = {"legalType": new_legal_type} - legal_entity = LegalEntity(entity_type=original_legal_type) + legal_entity = LegalEntity(_entity_type=original_legal_type) err = legal_entity_info.set_corp_type(legal_entity, new_data) assert legal_entity.entity_type == expected_legal_type diff --git a/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_parties_entity_roles.py b/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_parties_entity_roles.py index 98e2c81691..9af2318fdb 100644 --- a/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_parties_entity_roles.py +++ b/queue_services/entity-filer/tests/unit/filing_processors/filing_components/test_parties_entity_roles.py @@ -160,7 +160,7 @@ def helper_create_person(person_dict: dict) -> LegalEntity: first_name=person_dict.get("officer", {}).get("firstName"), last_name=person_dict.get("officer", {}).get("lastName"), middle_initial=person_dict.get("officer", {}).get("middleName"), - entity_type=LegalEntity.EntityTypes.PERSON, + _entity_type=LegalEntity.EntityTypes.PERSON, ) mail = Address(address_type=Address.MAILING) mail.save() diff --git a/queue_services/entity-filer/tests/unit/filing_processors/test_alteration.py b/queue_services/entity-filer/tests/unit/filing_processors/test_alteration.py index 46e2c73019..61bbda8222 100644 --- a/queue_services/entity-filer/tests/unit/filing_processors/test_alteration.py +++ b/queue_services/entity-filer/tests/unit/filing_processors/test_alteration.py @@ -42,7 +42,7 @@ def test_alteration_process(app, session, orig_legal_type, new_legal_type): # setup identifier = "BC1234567" business = create_business(identifier) - business.entity_type = orig_legal_type + business._entity_type = orig_legal_type alteration_filing = copy.deepcopy(FILING_HEADER) alteration_filing["filing"]["business"]["legalType"] = orig_legal_type @@ -119,7 +119,7 @@ def test_alteration_legal_name(app, session, mocker, test_name, legal_name, new_ """Assert the worker process calls the alteration correctly.""" identifier = "BC1234567" business = create_business(identifier) - business.legal_name = legal_name + business._legal_name = legal_name business.save() filing = copy.deepcopy(ALTERATION_FILING_TEMPLATE) if test_name == "numbered_to_name": @@ -214,7 +214,7 @@ def test_alteration_coop_association_type(app, session, new_association_type): # setup identifier = "CP1234567" business = create_business(identifier) - business.entity_type = LegalEntity.EntityTypes.COOP.value + business._entity_type = LegalEntity.EntityTypes.COOP.value alteration_filing = copy.deepcopy(FILING_HEADER) alteration_filing["filing"]["business"]["legalType"] = LegalEntity.EntityTypes.COOP.value @@ -242,7 +242,7 @@ def test_alteration_coop_rules_and_memorandum(app, session): # setup identifier = "CP1234567" business = create_business(identifier) - business.entity_type = LegalEntity.EntityTypes.COOP.value + business._entity_type = LegalEntity.EntityTypes.COOP.value alteration_filing = copy.deepcopy(FILING_HEADER) alteration_filing["filing"]["business"]["legalType"] = LegalEntity.EntityTypes.COOP.value diff --git a/queue_services/entity-filer/tests/unit/filing_processors/test_change_of_name.py b/queue_services/entity-filer/tests/unit/filing_processors/test_change_of_name.py index d37530f3d0..cc779da5c7 100644 --- a/queue_services/entity-filer/tests/unit/filing_processors/test_change_of_name.py +++ b/queue_services/entity-filer/tests/unit/filing_processors/test_change_of_name.py @@ -25,7 +25,7 @@ def test_change_of_name_process(app, session): con = {"changeOfName": {"legalName": new_name}} business = create_business(identifier) - business.legal_name = "original name" + business._legal_name = "original name" filing_meta = FilingMeta() @@ -52,7 +52,7 @@ def test_change_of_name_with_nr_process(app, session): } business = create_business(identifier) - business.legal_name = "original name" + business._legal_name = "original name" filing_meta = FilingMeta() diff --git a/queue_services/entity-filer/tests/unit/filing_processors/test_dissolution.py b/queue_services/entity-filer/tests/unit/filing_processors/test_dissolution.py index 4d9004cf97..a79437e745 100644 --- a/queue_services/entity-filer/tests/unit/filing_processors/test_dissolution.py +++ b/queue_services/entity-filer/tests/unit/filing_processors/test_dissolution.py @@ -70,7 +70,7 @@ def test_dissolution(app, session, legal_type, identifier, dissolution_type): last_name="Crane", middle_initial="Joe", title="VP", - entity_type=LegalEntity.EntityTypes.PERSON.value, + _entity_type=LegalEntity.EntityTypes.PERSON.value, ) member.save() # sanity check @@ -170,7 +170,7 @@ def test_administrative_dissolution(app, session, legal_type, identifier, dissol last_name="Crane", middle_initial="Joe", title="VP", - entity_type=LegalEntity.EntityTypes.PERSON.value, + _entity_type=LegalEntity.EntityTypes.PERSON.value, ) member.save() # sanity check diff --git a/queue_services/entity-filer/tests/unit/worker/test_restoration.py b/queue_services/entity-filer/tests/unit/worker/test_restoration.py index 308f344cc2..b30b089106 100644 --- a/queue_services/entity-filer/tests/unit/worker/test_restoration.py +++ b/queue_services/entity-filer/tests/unit/worker/test_restoration.py @@ -304,7 +304,7 @@ def test_update_party(app, session, mocker): last_name="Crane", middle_initial="Joe", title="VP", - entity_type=LegalEntity.EntityTypes.PERSON, + _entity_type=LegalEntity.EntityTypes.PERSON, ) member.save() assert member.id From 39be8232e053a1f6fbca62512cd684f77ad21072 Mon Sep 17 00:00:00 2001 From: Vysakh Menon Date: Fri, 19 Jan 2024 12:40:30 -0800 Subject: [PATCH 005/113] 19374 & 19375 amalgamation validaton fixes (#2397) --- .../resources/v2/business/business.py | 7 ++++-- legal-api/src/legal_api/services/__init__.py | 5 ++-- legal-api/src/legal_api/services/authz.py | 1 - .../validations/amalgamation_application.py | 13 ++++++---- .../test_amalgamation_application.py | 24 +++++++++---------- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/legal-api/src/legal_api/resources/v2/business/business.py b/legal-api/src/legal_api/resources/v2/business/business.py index 1553d73a5d..a6397d7bf9 100644 --- a/legal-api/src/legal_api/resources/v2/business/business.py +++ b/legal-api/src/legal_api/resources/v2/business/business.py @@ -93,8 +93,11 @@ def get_businesses(identifier: str): account_response, ) if orgs := account_response.get("orgs"): - if str(orgs[0].get("id")) == q_account: - business_json["accountId"] = orgs[0].get("id") + # A business can be affiliated in multiple accounts (in user account as well as in gov staff account's) + # AccountService.get_account_by_affiliated_identifier will fetch all of it + # check one of it has `q_account` + if any(str(org.get('id')) == q_account for org in orgs): + business_json['accountId'] = q_account return jsonify(business=business_json) diff --git a/legal-api/src/legal_api/services/__init__.py b/legal-api/src/legal_api/services/__init__.py index e80d79ba2c..8c61deea4b 100644 --- a/legal-api/src/legal_api/services/__init__.py +++ b/legal-api/src/legal_api/services/__init__.py @@ -20,16 +20,15 @@ from legal_api.models import LegalEntity from legal_api.utils.datetime import datetime -from .authz import ( +from .authz import ( # noqa: I001; ACCOUNT_IDENTITY, BASIC_USER, COLIN_SVC_ROLE, STAFF_ROLE, SYSTEM_ROLE, authorized, - get_account_by_affiliated_identifier, has_roles, -) +) # noqa: I001; from .bootstrap import AccountService, RegistrationBootstrapService from .business_details_version import VersionedBusinessDetailsService from .business_service import BusinessService diff --git a/legal-api/src/legal_api/services/authz.py b/legal-api/src/legal_api/services/authz.py index b727549631..d88b234a77 100644 --- a/legal-api/src/legal_api/services/authz.py +++ b/legal-api/src/legal_api/services/authz.py @@ -19,7 +19,6 @@ from urllib.parse import urljoin import jwt as pyjwt -import requests from flask import current_app from flask_jwt_oidc import JwtManager from requests import Session, exceptions diff --git a/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py b/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py index 4377a6946b..75d54fc19f 100644 --- a/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py +++ b/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py @@ -124,9 +124,9 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m "path": amalgamating_businesses_path, } ) - elif _has_future_effective_filing(amalgamating_business): + elif _has_pending_filing(amalgamating_business): msg.append( - {"error": f"{identifier} has a future effective filing.", "path": amalgamating_businesses_path} + {"error": f"{identifier} has a draft, pending or future effective filing.", "path": amalgamating_businesses_path} ) if not is_staff: @@ -217,14 +217,17 @@ def _is_business_affliated(identifier, account_id): if ( (account_response := AccountService.get_account_by_affiliated_identifier(identifier)) and (orgs := account_response.get("orgs")) - and str(orgs[0].get("id")) == account_id + and any(str(org.get('id')) == account_id for org in orgs) ): return True return False -def _has_future_effective_filing(amalgamating_business: any): - if Filing.get_filings_by_status(amalgamating_business, [Filing.Status.PAID.value, Filing.Status.PENDING.value]): +def _has_pending_filing(amalgamating_business: any): + if Filing.get_filings_by_status(amalgamating_business.id, [ + Filing.Status.DRAFT.value, + Filing.Status.PENDING.value, + Filing.Status.PAID.value]): return True return False diff --git a/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py b/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py index 59d26c6142..091d96e715 100644 --- a/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py +++ b/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py @@ -1608,7 +1608,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch("legal_api.models.legal_entity.LegalEntity.find_by_identifier", side_effect=mock_find_by_identifier) @@ -1632,10 +1632,10 @@ def mock_find_by_identifier(identifier): @pytest.mark.parametrize( "test_status, expected_code, expected_msg", - [("FAIL", HTTPStatus.BAD_REQUEST, "BC1234567 has a future effective filing."), ("SUCCESS", None, None)], + [('FAIL', HTTPStatus.BAD_REQUEST, 'BC1234567 has a draft, pending or future effective filing.'), ("SUCCESS", None, None)], ) -def test_has_future_effective_filing(mocker, app, session, jwt, test_status, expected_code, expected_msg): - """Assert valid amalgamating businesses has future effective filing.""" +def test_has_pending_filing(mocker, app, session, jwt, test_status, expected_code, expected_msg): + """Assert valid amalgamating businesses has draft, pending or future effective filing.""" filing = {"filing": {}} filing["filing"]["header"] = { "name": "amalgamationApplication", @@ -1697,7 +1697,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch("legal_api.models.legal_entity.LegalEntity.find_by_identifier", side_effect=mock_find_by_identifier) @@ -1760,7 +1760,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch( @@ -1812,7 +1812,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch( @@ -1864,7 +1864,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch( @@ -1926,7 +1926,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch( @@ -1991,7 +1991,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch( @@ -2054,7 +2054,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch( @@ -2114,7 +2114,7 @@ def mock_find_by_identifier(identifier): "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] ) mocker.patch( - "legal_api.services.filings.validations.amalgamation_application._has_future_effective_filing", + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False, ) mocker.patch( From 86335e78ae0c3cf50f00490b542391684425113a Mon Sep 17 00:00:00 2001 From: Shaoyun Tong <144159934+tshyun24@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:47:50 -0800 Subject: [PATCH 006/113] 11550 - AmalgamaTING and TED Business Summary PDF (#2398) * AmalTED pdf * Amalgamating pdf * remove Dissolution/Restoration Information section * fix lint error * lint with flake8 * lint --- .../report-templates/businessSummary.html | 1 + .../business-summary/amalgamating.html | 24 ++++++++++++++ .../business-summary/amalgamations.html | 6 ++-- .../business-summary/stateTransition.html | 2 +- .../legal_api/reports/business_document.py | 32 ++++++++++++++++++- 5 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 legal-api/report-templates/template-parts/business-summary/amalgamating.html diff --git a/legal-api/report-templates/businessSummary.html b/legal-api/report-templates/businessSummary.html index 0ffab74604..23b91fcdd5 100644 --- a/legal-api/report-templates/businessSummary.html +++ b/legal-api/report-templates/businessSummary.html @@ -35,6 +35,7 @@ [[business-summary/stateTransition.html]] [[business-summary/recordKeeper.html]] [[business-summary/amalgamations.html]] + [[business-summary/amalgamating.html]] [[common/addresses.html]] {% if business.legalType in ['GP', 'SP'] %} [[business-summary/parties.html]] diff --git a/legal-api/report-templates/template-parts/business-summary/amalgamating.html b/legal-api/report-templates/template-parts/business-summary/amalgamating.html new file mode 100644 index 0000000000..fd4a948ab4 --- /dev/null +++ b/legal-api/report-templates/template-parts/business-summary/amalgamating.html @@ -0,0 +1,24 @@ +{% if business.isAmalgamating %} +
+
+
Amalgamated Into
+
+ +
+ Name of Amalgamated Company: + {% if business.amalgamatedInto is defined %} + {{business.amalgamatedInto.legalName}} + {% else %} + Not Available + {% endif %} +
+ +
+ Incorporation Number: + {% if business.amalgamatedInto is defined %} + {{business.amalgamatedInto.identifier}} + {% else %} + Not Available + {% endif %} +
+{% endif %} \ No newline at end of file diff --git a/legal-api/report-templates/template-parts/business-summary/amalgamations.html b/legal-api/report-templates/template-parts/business-summary/amalgamations.html index 461475f50e..a9dda9be2c 100644 --- a/legal-api/report-templates/template-parts/business-summary/amalgamations.html +++ b/legal-api/report-templates/template-parts/business-summary/amalgamations.html @@ -1,15 +1,15 @@ {% if business.amalgamatedEntity %}
-
Amalgamating {{ entityShortDescription }}s Information
+
Amalgamating Corporation(s) Information
{% for entity in amalgamatedEntities %} diff --git a/legal-api/report-templates/template-parts/business-summary/stateTransition.html b/legal-api/report-templates/template-parts/business-summary/stateTransition.html index 2b0405368d..818141f0c7 100644 --- a/legal-api/report-templates/template-parts/business-summary/stateTransition.html +++ b/legal-api/report-templates/template-parts/business-summary/stateTransition.html @@ -1,4 +1,4 @@ -{% if stateFilings|length > 0 %} +{% if stateFilings|length > 0 and not business.isAmalgamating %}
diff --git a/legal-api/src/legal_api/reports/business_document.py b/legal-api/src/legal_api/reports/business_document.py index 0f605eddfb..e1cd40709d 100644 --- a/legal-api/src/legal_api/reports/business_document.py +++ b/legal-api/src/legal_api/reports/business_document.py @@ -22,6 +22,7 @@ from flask import current_app, jsonify from legal_api.models import AlternateName, CorpType, Filing, LegalEntity +from legal_api.models.amalgamation import Amalgamation from legal_api.reports.registrar_meta import RegistrarInfo from legal_api.resources.v2.business import get_addresses, get_directors from legal_api.resources.v2.business.business_parties import get_parties @@ -83,6 +84,7 @@ def _substitute_template_parts(template_code): template_parts = [ "business-summary/alterations", "business-summary/amalgamations", + "business-summary/amalgamating", "business-summary/businessDetails", "business-summary/liquidation", "business-summary/nameChanges", @@ -133,6 +135,7 @@ def _get_template_data(self, get_json=False): self._set_name_translations(business_json) self._set_business_changes(business_json) self._set_amalgamation_details(business_json) + self._set_amalgamating_details(business_json) self._set_liquidation_details(business_json) if self._legal_entity.entity_type in ["SP", "GP"]: @@ -326,6 +329,14 @@ def _set_business_state_changes(self, legal_entity: dict): ], ): state_filings.append(self._format_state_filing(filing)) + # If it is amalgamating business + if ((legal_entity.get("business").get("state") == "HISTORICAL") + and (legal_entity.get("business").get("amalgamatedInto"))): + amalgamating_business_temp = LegalEntity.find_by_identifier(legal_entity.get("business").get("identifier")) + amalgamating_business = amalgamating_business_temp.amalgamating_businesses.one_or_none() + amalgamation = Amalgamation.find_by_id(amalgamating_business.amalgamation_id) + filing = Filing.find_by_id(amalgamation.filing_id) + state_filings.append(self._format_state_filing(filing)) legal_entity["stateFilings"] = state_filings def _set_record_keepers(self, legal_entity: dict): @@ -440,6 +451,8 @@ def _format_state_filing(self, filing: Filing) -> dict: filing_meta["continuationOut"]["continuationOutDate"] ) filing_info["continuationOutDate"] = continuation_out_date.strftime(OUTPUT_DATE_FORMAT) + elif filing.filing_type == "amalgamationApplication": + filing_info["filingName"] = "Amalgamation" else: filing_info["filingName"] = BusinessDocument._get_summary_display_name(filing.filing_type, None, None) return filing_info @@ -450,10 +463,27 @@ def _set_amalgamation_details(self, legal_entity: dict): amalgamation_application = Filing.get_filings_by_types(self._legal_entity, ["amalgamationApplication"]) if amalgamation_application: legal_entity["business"]["amalgamatedEntity"] = True - # else condition will have to be added when we do amalgamation in the new system + amalgamation_json = amalgamation_application[0].filing_json.get("filing", {})\ + .get("amalgamationApplication", {}) + # if it's future effective if self._epoch_filing_date and amalgamation_application[0].effective_date < self._epoch_filing_date: amalgamated_businesses_info = {"legalName": NOT_AVAILABLE, "identifier": NOT_AVAILABLE} amalgamated_businesses.append(amalgamated_businesses_info) + else: + amalgamating_businesses = amalgamation_json.get("amalgamatingBusinesses", {}) + while amalgamating_businesses: + if len(amalgamating_businesses[0].get("foreignJurisdiction", {})) == 0: + identifier = amalgamating_businesses[0].get("identifier", {}) + else: + identifier = amalgamating_businesses[0].get("corpNumber", {}) + amalgamating_business = legal_entity.find_by_identifier(identifier) + business_legal_name = amalgamating_business.legal_name + amalgamated_businesses_info = { + "legalName": business_legal_name, + "identifier": identifier + } + amalgamated_businesses.append(amalgamated_businesses_info) + amalgamating_businesses.remove(amalgamating_businesses[0]) legal_entity["amalgamatedEntities"] = amalgamated_businesses def _set_liquidation_details(self, legal_entity: dict): From 2f2e255a1ccc4f6a295384fc127b4d604f8a9609 Mon Sep 17 00:00:00 2001 From: leodube-aot <122323255+leodube-aot@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:16:37 -0800 Subject: [PATCH 007/113] Add not in good standing blocker to amalgamations (#2402) --- legal-api/src/legal_api/services/authz.py | 18 ++++++++++++------ .../tests/unit/services/test_authorization.py | 6 ------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/legal-api/src/legal_api/services/authz.py b/legal-api/src/legal_api/services/authz.py index d88b234a77..3df546bf70 100644 --- a/legal-api/src/legal_api/services/authz.py +++ b/legal-api/src/legal_api/services/authz.py @@ -156,7 +156,8 @@ def get_allowable_filings_dict(): "regular": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN], + "business": [BusinessBlocker.BUSINESS_FROZEN, + BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -166,7 +167,8 @@ def get_allowable_filings_dict(): "vertical": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN], + "business": [BusinessBlocker.BUSINESS_FROZEN, + BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -176,7 +178,8 @@ def get_allowable_filings_dict(): "horizontal": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN], + "business": [BusinessBlocker.BUSINESS_FROZEN, + BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -317,7 +320,8 @@ def get_allowable_filings_dict(): "regular": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN], + "business": [BusinessBlocker.BUSINESS_FROZEN, + BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -327,7 +331,8 @@ def get_allowable_filings_dict(): "vertical": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN], + "business": [BusinessBlocker.BUSINESS_FROZEN, + BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -337,7 +342,8 @@ def get_allowable_filings_dict(): "horizontal": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN], + "business": [BusinessBlocker.BUSINESS_FROZEN, + BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, diff --git a/legal-api/tests/unit/services/test_authorization.py b/legal-api/tests/unit/services/test_authorization.py index 650a3b29fe..3af05a21af 100644 --- a/legal-api/tests/unit/services/test_authorization.py +++ b/legal-api/tests/unit/services/test_authorization.py @@ -1702,9 +1702,6 @@ def mock_auth(one, two): # pylint: disable=unused-argument; mocks of library me FilingKey.AGM_EXTENSION, FilingKey.AGM_LOCATION_CHANGE, FilingKey.ALTERATION, - FilingKey.AMALGAMATION_REGULAR, - FilingKey.AMALGAMATION_VERTICAL, - FilingKey.AMALGAMATION_HORIZONTAL, FilingKey.AR_CORPS, FilingKey.COA_CORPS, FilingKey.COD_CORPS, @@ -1765,9 +1762,6 @@ def mock_auth(one, two): # pylint: disable=unused-argument; mocks of library me FilingKey.AGM_EXTENSION, FilingKey.AGM_LOCATION_CHANGE, FilingKey.ALTERATION, - FilingKey.AMALGAMATION_REGULAR, - FilingKey.AMALGAMATION_VERTICAL, - FilingKey.AMALGAMATION_HORIZONTAL, FilingKey.AR_CORPS, FilingKey.COA_CORPS, FilingKey.COD_CORPS, From a054dc5c6e5f30686cb8bafa5d5486aa030d334c Mon Sep 17 00:00:00 2001 From: Hongjing <60866283+chenhongjing@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:02:09 -0800 Subject: [PATCH 008/113] 19154 Update TING validation rules (#2403) * 19154 Signed-off-by: Hongjing Chen * fix linting Signed-off-by: Hongjing Chen * update error messages Signed-off-by: Hongjing Chen --------- Signed-off-by: Hongjing Chen --- .../validations/amalgamation_application.py | 35 ++++++- .../test_amalgamation_application.py | 94 +++++++++++++++++++ 2 files changed, 124 insertions(+), 5 deletions(-) diff --git a/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py b/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py index 75d54fc19f..0953d33c57 100644 --- a/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py +++ b/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py @@ -84,6 +84,7 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m is_any_ulc = False is_any_expro_a = False amalgamating_businesses = {} + duplicate_businesses = [] for amalgamating_business_json in amalgamating_businesses_json: if identifier := amalgamating_business_json.get("identifier"): if ( @@ -97,6 +98,8 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m if not (business := BusinessService.fetch_business(identifier)): continue + if identifier in amalgamating_businesses: + duplicate_businesses.append(identifier) amalgamating_businesses[identifier] = business if business.entity_type == BusinessCommon.EntityTypes.BCOMP.value: @@ -107,7 +110,16 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m is_any_ccc = True elif business.entity_type == BusinessCommon.EntityTypes.BC_ULC_COMPANY.value: is_any_ulc = True - + elif corp_number := amalgamating_business_json.get("corpNumber"): + if corp_number in amalgamating_businesses: + duplicate_businesses.append(corp_number) + amalgamating_businesses[corp_number] = amalgamating_business_json + + if (corp_number.startswith("A") and + (foreign_jurisdiction := amalgamating_business_json.get("foreignJurisdiction")) and + foreign_jurisdiction.get("country") == "CA" and + foreign_jurisdiction.get("region") == "BC"): + is_any_expro_a = True is_any_bc_company = is_any_ben or is_any_limited or is_any_ccc or is_any_ulc for amalgamating_business_json in amalgamating_businesses_json: @@ -181,9 +193,22 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m "A BC Unlimited Liability Company cannot amalgamate with " f"a foreign company {foreign_legal_name}." ), - "path": amalgamating_businesses_path, - } - ) + "path": amalgamating_businesses_path + }) + + if duplicate_businesses: + error_msg = "Duplicate amalgamating business entry found in list: " + \ + ", ".join(duplicate_businesses) + "." + msg.append({ + "error": error_msg, + "path": amalgamating_businesses_path + }) + + if len(amalgamating_businesses) < 2: + msg.append({ + "error": "Two or more amalgamating businesses required.", + "path": amalgamating_businesses_path, + }) if entity_type == BusinessCommon.EntityTypes.BC_CCC.value and not is_any_ccc: msg.append( @@ -217,7 +242,7 @@ def _is_business_affliated(identifier, account_id): if ( (account_response := AccountService.get_account_by_affiliated_identifier(identifier)) and (orgs := account_response.get("orgs")) - and any(str(org.get('id')) == account_id for org in orgs) + and any(str(org.get("id")) == account_id for org in orgs) ): return True return False diff --git a/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py b/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py index 091d96e715..4f6fca0055 100644 --- a/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py +++ b/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py @@ -2136,3 +2136,97 @@ def mock_find_by_identifier(identifier): else: assert HTTPStatus.BAD_REQUEST == err.code assert any(x["error"] == expected_msg for x in err.msg) + + +@pytest.mark.parametrize( + 'test_status, amalgamating_businesses, expected_code, expected_msg', + [ + ('FAIL_BC', [ + {'role': 'amalgamating','identifier': 'BC1234567'}, + {'role': 'amalgamating','identifier': 'BC1234567'}, + {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'} + ], HTTPStatus.BAD_REQUEST, 'Duplicate amalgamating business entry found in list: BC1234567.'), + ('FAIL_EXPRO', [ + {'role': 'amalgamating','identifier': 'BC1234567'}, + {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'}, + {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'} + ], HTTPStatus.BAD_REQUEST, 'Duplicate amalgamating business entry found in list: 123456.'), + ('SUCCESS', [ + {'role': 'amalgamating','identifier': 'BC1234567'}, + {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'} + ], None, None) + ] +) +def test_duplicate_amalgamating_businesses(mocker, app, session, jwt, test_status, amalgamating_businesses, + expected_code, expected_msg): + """Assert duplicate amalgamating businesses.""" + account_id = '123456' + filing = {'filing': {}} + filing['filing']['header'] = {'name': 'amalgamationApplication', 'date': '2019-04-08', + 'certifiedBy': 'full name', 'email': 'no_one@never.get', 'filingId': 1} + filing['filing']['amalgamationApplication'] = copy.deepcopy(AMALGAMATION_APPLICATION) + filing['filing']['amalgamationApplication']['amalgamatingBusinesses'] = amalgamating_businesses + + def mock_find_by_identifier(identifier): + return LegalEntity(identifier=identifier, + legal_type=LegalEntity.EntityTypes.BCOMP.value) + + mocker.patch('legal_api.services.filings.validations.amalgamation_application.validate_name_request', + return_value=[]) + mocker.patch('legal_api.services.filings.validations.amalgamation_application._has_pending_filing', + return_value=False) + mocker.patch("legal_api.models.legal_entity.LegalEntity.find_by_identifier", side_effect=mock_find_by_identifier) + + mocker.patch('legal_api.utils.auth.jwt.validate_roles', return_value=True) # Staff + + err = validate(None, filing, account_id) + + # validate outcomes + if test_status == 'SUCCESS': + assert not err + else: + assert expected_code == err.code + assert expected_msg == err.msg[0]['error'] + + +@pytest.mark.parametrize( + 'test_status, expected_code, expected_msg', + [ + ('FAIL', HTTPStatus.BAD_REQUEST, 'Two or more amalgamating businesses required.'), + ('SUCCESS', None, None) + ] +) +def test_amalgamating_businesses_number(mocker, app, session, jwt, test_status, expected_code, expected_msg): + """Assert two or more amalgamating businesses required.""" + account_id = '123456' + filing = {'filing': {}} + filing['filing']['header'] = {'name': 'amalgamationApplication', 'date': '2019-04-08', + 'certifiedBy': 'full name', 'email': 'no_one@never.get', 'filingId': 1} + filing['filing']['amalgamationApplication'] = copy.deepcopy(AMALGAMATION_APPLICATION) + + if test_status == 'FAIL': + filing['filing']['amalgamationApplication']['amalgamatingBusinesses'] = [] + else: + filing['filing']['amalgamationApplication']['amalgamatingBusinesses'][1]['corpNumber'] + + + def mock_find_by_identifier(identifier): + return LegalEntity(identifier=identifier, + legal_type=LegalEntity.LegalTypes.BCOMP.value) + + mocker.patch('legal_api.services.filings.validations.amalgamation_application.validate_name_request', + return_value=[]) + mocker.patch('legal_api.services.filings.validations.amalgamation_application._has_pending_filing', + return_value=False) + mocker.patch('legal_api.models.legal_entity.LegalEntity.find_by_identifier', side_effect=mock_find_by_identifier) + + mocker.patch('legal_api.utils.auth.jwt.validate_roles', return_value=True) # Staff + + err = validate(None, filing, account_id) + + # validate outcomes + if test_status == 'SUCCESS': + assert not err + else: + assert expected_code == err.code + assert expected_msg == err.msg[0]['error'] From 133f31e21ab65f8a63253c54870fc109c2d0870d Mon Sep 17 00:00:00 2001 From: Shaoyun Tong <144159934+tshyun24@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:44:31 -0800 Subject: [PATCH 009/113] 11550 - fix spacing and TING (#2404) * fix spacing and TING * retrive to the previous output --- .../business-summary/amalgamations.html | 14 +++++++------- .../template-parts/common/style.html | 10 ---------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/legal-api/report-templates/template-parts/business-summary/amalgamations.html b/legal-api/report-templates/template-parts/business-summary/amalgamations.html index a9dda9be2c..28956fc30c 100644 --- a/legal-api/report-templates/template-parts/business-summary/amalgamations.html +++ b/legal-api/report-templates/template-parts/business-summary/amalgamations.html @@ -11,20 +11,20 @@
- - {% for entity in amalgamatedEntities %} - + + {% for entity in amalgamatedEntities %} + - - {% endfor %} + + {% endfor %} {% endif %} diff --git a/legal-api/report-templates/template-parts/common/style.html b/legal-api/report-templates/template-parts/common/style.html index 7636d2f3e6..08c373d572 100644 --- a/legal-api/report-templates/template-parts/common/style.html +++ b/legal-api/report-templates/template-parts/common/style.html @@ -508,16 +508,6 @@ word-wrap: break-word; } - /* vertical padding to upper border */ - .amalgamation-table tr:not(:first-child):nth-child(odd) td { - padding-top: 0.25rem; - } - - /* vertical padding to lower border */ - .amalgamation-table tr:not(:last-child) td { - padding-bottom: 0.25rem; - } - .footer-mocs { border-top: 1px solid #234075; bottom: 0; From 8d6ca0f2c9276a6a4568035beb7f6dda61eb374a Mon Sep 17 00:00:00 2001 From: Paul <144158015+PaulGarewal@users.noreply.github.com> Date: Tue, 23 Jan 2024 09:10:48 -0800 Subject: [PATCH 010/113] 18802 amalgamation outputs (#2399) * added first draft of outputs * testing adding folder * added draft amalgamation outputs * cleaned up application syntax * fixed typo * added data formatting and noa * added dates for certificate of amalgamation * repeated effective_date_time in business details for amalgamation application * fixed lint issue * fixed typo * fixed notice of articles and removed amalgamation/nameRequest * removed amalgamations.html from business-summary.html * reestablished amalgamations.html * removed completingParty from amalgamations and added from incorp * removed incorp/bencompany from noa in amalgamationApp --- .../amalgamationApplication.html | 52 +++++++++++++++---- .../certificateOfAmalgamation.html | 48 +++++++++++++++++ .../report-templates/noticeOfArticles.html | 3 +- .../amalgamation/amalgamatingCorp.html | 29 +++++++++++ .../amalgamation/amalgamationName.html | 4 ++ .../amalgamation/amalgamationStmt.html | 11 ++++ .../amalgamation/approvalType.html | 17 ++++++ .../amalgamation/effectiveDate.html | 11 ++++ .../common/businessDetails.html | 13 +++++ legal-api/src/legal_api/reports/report.py | 42 +++++++++++++-- 10 files changed, 215 insertions(+), 15 deletions(-) create mode 100644 legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html create mode 100644 legal-api/report-templates/template-parts/amalgamation/amalgamationName.html create mode 100644 legal-api/report-templates/template-parts/amalgamation/amalgamationStmt.html create mode 100644 legal-api/report-templates/template-parts/amalgamation/approvalType.html create mode 100644 legal-api/report-templates/template-parts/amalgamation/effectiveDate.html diff --git a/legal-api/report-templates/amalgamationApplication.html b/legal-api/report-templates/amalgamationApplication.html index cb19b9c7a9..d26e729fa0 100644 --- a/legal-api/report-templates/amalgamationApplication.html +++ b/legal-api/report-templates/amalgamationApplication.html @@ -1,13 +1,47 @@ [[macros.html]] - - - Amalgamation Application - - - [[common/style.html]] - - - + + Amalgamation Application + + + [[common/style.html]] + + +
+ + + + + + +
+ +
+
+ [[common/businessDetails.html]] +
+
AMALGAMATION APPLICATION
+
+ [[incorporation-application/nameRequest.html]] + [[amalgamation/effectiveDate.html]] + [[amalgamation/approvalType.html]] + [[amalgamation/amalgamatingCorp.html]] + [[amalgamation/amalgamationStmt.html]] + [[incorporation-application/completingParty.html]] + +
NOTICE OF ARTICLES
+
+ [[amalgamation/amalgamationName.html]] + [[common/statement.html]] + [[common/addresses.html]] + [[common/directors.html]] + [[common/shareStructure.html]] +
+ \ No newline at end of file diff --git a/legal-api/report-templates/certificateOfAmalgamation.html b/legal-api/report-templates/certificateOfAmalgamation.html index a41bff288b..f323b52b95 100644 --- a/legal-api/report-templates/certificateOfAmalgamation.html +++ b/legal-api/report-templates/certificateOfAmalgamation.html @@ -9,6 +9,54 @@ [[common/certificateStyle.html]] +
+
+
Incorporation Number: {{ business.identifier }}
+ [[common/correctedOnCertificate.html]] +
+ +
+ [[common/certificateLogo.html]] + +
+
Certificate of
+
AMALGAMATION
+
{{ entityAct }}
+
+ +
+
I hereby certify that the following companies were amalgamated under the name
+
{{ business.legalName }}
+
on {{ effective_date_time }}
+
 
+ {% for entity in amalgamatingBusinesses %} + {% if entity == amalgamatingBusinesses[-1] %} + + +
+ and {{ entity.name }} ({{ entity.identifier }}) +
+ + + {%else%} + + +
+ {{ entity.name }} + ({{ entity.identifier }}), +
+ + + {%endif%} + {% endfor %} +
+
+
Issued under my hand at Victoria, British Columbia
+
on {{ report_date_time }}
+
+
+
+
[[common/certificateFooter.html]] \ No newline at end of file diff --git a/legal-api/report-templates/noticeOfArticles.html b/legal-api/report-templates/noticeOfArticles.html index b0cd684b98..cbcfc3bd75 100644 --- a/legal-api/report-templates/noticeOfArticles.html +++ b/legal-api/report-templates/noticeOfArticles.html @@ -16,7 +16,7 @@
NOTICE OF ARTICLES
-
{{entityDescription}} - Business Corporations Act
+
{{entityDescription}} - {{ entityAct }}
@@ -27,6 +27,7 @@ [[common/businessDetails.html]]
NOTICE OF ARTICLES
+ [[amalgamation/amalgamationName.html]] [[common/statement.html]] [[common/benefitCompanyStmt.html]] [[common/addresses.html]] diff --git a/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html new file mode 100644 index 0000000000..8ea50f34f8 --- /dev/null +++ b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html @@ -0,0 +1,29 @@ + +
+
+
Amalgamating Corporation(s) Information
+
+ + + + + + {% for entity in amalgamatingBusinesses %} + + + + + {% endfor %} + diff --git a/legal-api/report-templates/template-parts/amalgamation/amalgamationName.html b/legal-api/report-templates/template-parts/amalgamation/amalgamationName.html new file mode 100644 index 0000000000..4896638a2d --- /dev/null +++ b/legal-api/report-templates/template-parts/amalgamation/amalgamationName.html @@ -0,0 +1,4 @@ +{% if amalgamationApplication %} + Name of Amalgamated Company: {{business.legalName}} +
+{%endif%} diff --git a/legal-api/report-templates/template-parts/amalgamation/amalgamationStmt.html b/legal-api/report-templates/template-parts/amalgamation/amalgamationStmt.html new file mode 100644 index 0000000000..ae4a756f8e --- /dev/null +++ b/legal-api/report-templates/template-parts/amalgamation/amalgamationStmt.html @@ -0,0 +1,11 @@ +
+
+
+ Amalgamation Statement +
+
+ This amalgamation has been effected without court approval. A copy of all of the required affidavits under section 277(1) have been obtained and the affidavit + obtained from each amalgamating company has been deposited in that company's records office. +
+ +
\ No newline at end of file diff --git a/legal-api/report-templates/template-parts/amalgamation/approvalType.html b/legal-api/report-templates/template-parts/amalgamation/approvalType.html new file mode 100644 index 0000000000..d250982cc5 --- /dev/null +++ b/legal-api/report-templates/template-parts/amalgamation/approvalType.html @@ -0,0 +1,17 @@ +
+
+
+ Approval Type +
+ {% if courtApproval is none %} +
+ N/A +
+ {% else %} + {% if courtApproval == True %} +
+ The restoration was approved by a court order. +
+ {%endif%} + {% endif %} +
diff --git a/legal-api/report-templates/template-parts/amalgamation/effectiveDate.html b/legal-api/report-templates/template-parts/amalgamation/effectiveDate.html new file mode 100644 index 0000000000..b122eba3f0 --- /dev/null +++ b/legal-api/report-templates/template-parts/amalgamation/effectiveDate.html @@ -0,0 +1,11 @@ +
+
+
Amalgamation Effective Date
+
+ {% if header.isFutureEffective %} + {{header.effective_date_time}} + {% else %} + The amalgamation is to take effect at the time that this application is filed with the Registrar. + {% endif %} +
+
\ No newline at end of file diff --git a/legal-api/report-templates/template-parts/common/businessDetails.html b/legal-api/report-templates/template-parts/common/businessDetails.html index 1984065db7..5ec4ad2b99 100644 --- a/legal-api/report-templates/template-parts/common/businessDetails.html +++ b/legal-api/report-templates/template-parts/common/businessDetails.html @@ -50,6 +50,19 @@ {% endif %}
+ {% elif header.reportType == 'amalgamationApplication' %} + +
Incorporation Number:
+
Issued Date and Time:
+
Recognition Date and Time:
+
Retrieved Date and Time:
+ + +
{{business.identifier}}
+
{{effective_date_time}}
+
{{recognition_date_time}}
+
{{report_date_time}}
+ {% elif header.reportType == 'noticeOfArticles' %}
Incorporation Number:
diff --git a/legal-api/src/legal_api/reports/report.py b/legal-api/src/legal_api/reports/report.py index 66baef424d..055d0bb94a 100644 --- a/legal-api/src/legal_api/reports/report.py +++ b/legal-api/src/legal_api/reports/report.py @@ -118,6 +118,11 @@ def _substitute_template_parts(template_code): """ template_path = current_app.config.get("REPORT_TEMPLATE_PATH") template_parts = [ + "amalgamation/amalgamatingCorp", + "amalgamation/amalgamationName", + "amalgamation/amalgamationStmt", + "amalgamation/approvalType", + "amalgamation/effectiveDate", "bc-annual-report/legalObligations", "bc-address-change/addresses", "bc-director-change/directors", @@ -688,13 +693,40 @@ def _format_alteration_data(self, filing): ) filing["newLegalTypeDescription"] = self._get_legal_type_description(new_legal_type) if new_legal_type else None - def _format_amalgamation_data(self, filling): - # FUTURE: format logic for amalgamation application - return + def _format_amalgamation_data(self, filing): + amalgamation = filing["amalgamationApplication"] + + # Formatting addresses for registered and records office + self._format_address(amalgamation["offices"]["registeredOffice"]["deliveryAddress"]) + self._format_address(amalgamation["offices"]["registeredOffice"]["mailingAddress"]) + if "recordsOffice" in amalgamation["offices"]: + self._format_address(amalgamation["offices"]["recordsOffice"]["deliveryAddress"]) + self._format_address(amalgamation["offices"]["recordsOffice"]["mailingAddress"]) + + # Formatting parties + self._format_directors(amalgamation["parties"]) + + # Creating helper lists and extracting other details + filing["nameRequest"] = amalgamation.get("nameRequest", {}) + filing["listOfTranslations"] = amalgamation.get("nameTranslations", []) + filing["offices"] = amalgamation["offices"] + filing["parties"] = amalgamation["parties"] + filing["contactPoint"] = amalgamation.get("contactPoint", {}) + filing["courtApproval"] = amalgamation.get("courtApproval") + + if "shareStructure" in amalgamation: + filing["shareClasses"] = amalgamation["shareStructure"].get("shareClasses", []) + else: + filing["shareClasses"] = amalgamation.get("shareClasses", []) + + filing["amalgamatingBusinesses"] = amalgamation.get("amalgamatingBusinesses", []) + filing["incorporationAgreement"] = amalgamation.get("incorporationAgreement", {}) def _format_certificate_of_amalgamation_data(self, filing): - # FUTURE: format logic for certificate of amalgamation - return + amalgamation = filing["amalgamationApplication"] + + filing["nameRequest"] = amalgamation.get("nameRequest", {}) + filing["amalgamatingBusinesses"] = amalgamation.get("amalgamatingBusinesses", []) def _format_change_of_registration_data( self, filing, filing_type From 7007942ab5686890a989a5610b6200655a369866 Mon Sep 17 00:00:00 2001 From: Kevin Zhang <54437031+kzdev420@users.noreply.github.com> Date: Wed, 24 Jan 2024 05:24:17 +0800 Subject: [PATCH 011/113] 18803 Add amalgamation email (#2406) * 18803 add amalgamation email * fix small * fix lint issue * fix small * fix the get_filing parts * fix small * fix the test * fix lint issue * fix lint issue * update version --- .../amalgamation_notification.py | 181 ++++++++++++++++++ .../email_templates/AMALGA-COMPLETED.html | 41 ++++ .../email_templates/AMALGA-PAID.html | 50 +++++ .../entity-emailer/tests/unit/__init__.py | 36 ++++ .../test_amalgamation_notification.py | 51 +++++ 5 files changed, 359 insertions(+) create mode 100644 queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py create mode 100644 queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-COMPLETED.html create mode 100644 queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-PAID.html create mode 100644 queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py diff --git a/queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py b/queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py new file mode 100644 index 0000000000..014893931d --- /dev/null +++ b/queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py @@ -0,0 +1,181 @@ +# Copyright © 2024 Province of British Columbia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Email processing rules and actions for Amalgamation notifications.""" +from __future__ import annotations + +import base64 +import re +from http import HTTPStatus +from pathlib import Path + +import requests +from entity_queue_common.service_utils import logger +from flask import current_app +from jinja2 import Template +from legal_api.models import Filing + +from entity_emailer.email_processors import get_filing_info, get_recipients, substitute_template_parts + + +def _get_pdfs( + status: str, + token: str, + business: dict, + filing: Filing, + filing_date_time: str, + effective_date: str) -> list: + # pylint: disable=too-many-locals, too-many-branches, too-many-statements, too-many-arguments + """Get the outputs for the amalgamation notification.""" + pdfs = [] + attach_order = 1 + headers = { + 'Accept': 'application/pdf', + 'Authorization': f'Bearer {token}' + } + + if status == Filing.Status.PAID.value: + # add filing pdf + filing_pdf = requests.get( + f'{current_app.config.get("LEGAL_API_URL")}/businesses/{business["identifier"]}/filings/{filing.id}', + headers=headers + ) + if filing_pdf.status_code != HTTPStatus.OK: + logger.error('Failed to get pdf for filing: %s', filing.id) + else: + filing_pdf_encoded = base64.b64encode(filing_pdf.content) + pdfs.append( + { + 'fileName': 'Amalgamation Application.pdf', + 'fileBytes': filing_pdf_encoded.decode('utf-8'), + 'fileUrl': '', + 'attachOrder': attach_order + } + ) + attach_order += 1 + + corp_name = business.get('legalName') + receipt = requests.post( + f'{current_app.config.get("PAY_API_URL")}/{filing.payment_token}/receipts', + json={ + 'corpName': corp_name, + 'filingDateTime': filing_date_time, + 'effectiveDateTime': effective_date if effective_date != filing_date_time else '', + 'filingIdentifier': str(filing.id), + 'businessNumber': business.get('taxId', '') + }, + headers=headers + ) + if receipt.status_code != HTTPStatus.CREATED: + logger.error('Failed to get receipt pdf for filing: %s', filing.id) + else: + receipt_encoded = base64.b64encode(receipt.content) + pdfs.append( + { + 'fileName': 'Receipt.pdf', + 'fileBytes': receipt_encoded.decode('utf-8'), + 'fileUrl': '', + 'attachOrder': attach_order + } + ) + attach_order += 1 + elif status == Filing.Status.COMPLETED.value: + # add certificate of amalgamation + certificate = requests.get( + f'{current_app.config.get("LEGAL_API_URL")}/businesses/{business["identifier"]}/filings/{filing.id}' + '?type=certificateOfAmalgamation', + headers=headers + ) + if certificate.status_code != HTTPStatus.OK: + logger.error('Failed to get corrected registration statement pdf for filing: %s', filing.id) + else: + certificate_encoded = base64.b64encode(certificate.content) + pdfs.append( + { + 'fileName': 'Certificate Of Amalgamation.pdf', + 'fileBytes': certificate_encoded.decode('utf-8'), + 'fileUrl': '', + 'attachOrder': attach_order + } + ) + attach_order += 1 + # add notice of articles + noa = requests.get( + f'{current_app.config.get("LEGAL_API_URL")}/businesses/{business["identifier"]}/filings/{filing.id}' + '?type=noticeOfArticles', + headers=headers + ) + if noa.status_code != HTTPStatus.OK: + logger.error('Failed to get noa pdf for filing: %s', filing.id) + else: + noa_encoded = base64.b64encode(noa.content) + pdfs.append( + { + 'fileName': 'Notice of Articles.pdf', + 'fileBytes': noa_encoded.decode('utf-8'), + 'fileUrl': '', + 'attachOrder': attach_order + } + ) + attach_order += 1 + return pdfs + + +def process(email_info: dict, token: str) -> dict: # pylint: disable=too-many-locals, , too-many-branches + """Build the email for Amalgamation notification.""" + logger.debug('filing_notification: %s', email_info) + # get template and fill in parts + filing_type, status = email_info['type'], email_info['option'] + # get template vars from filing + filing, business, leg_tmz_filing_date, leg_tmz_effective_date = get_filing_info(email_info['filingId']) + filing_name = filing.filing_type[0].upper() + ' '.join(re.findall('[a-zA-Z][^A-Z]*', filing.filing_type[1:])) + + template = Path(f'{current_app.config.get("TEMPLATE_PATH")}/AMALGA-{status}.html').read_text() + filled_template = substitute_template_parts(template) + # render template with vars + jnja_template = Template(filled_template, autoescape=True) + filing_data = (filing.json)['filing'][f'{filing_type}'] + html_out = jnja_template.render( + business=business, + filing=filing_data, + header=(filing.json)['filing']['header'], + filing_date_time=leg_tmz_filing_date, + effective_date_time=leg_tmz_effective_date, + entity_dashboard_url=current_app.config.get('DASHBOARD_URL') + business.get('identifier', ''), + email_header=filing_name.upper(), + filing_type=filing_type + ) + + # get attachments + pdfs = _get_pdfs(status, token, business, filing, leg_tmz_filing_date, leg_tmz_effective_date) + + # get recipients + recipients = get_recipients(status, filing.filing_json, token, filing_type) + if not recipients: + return {} + + # assign subject + legal_name = business.get('legalName', None) + subject = f'{legal_name} - Amalgamation' + if status == Filing.Status.COMPLETED.value: + subject = f'{legal_name} - Confirmation of Amalgamation' + + return { + 'recipients': recipients, + 'requestBy': 'BCRegistries@gov.bc.ca', + 'content': { + 'subject': subject, + 'body': f'{html_out}', + 'attachments': pdfs + } + } diff --git a/queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-COMPLETED.html b/queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-COMPLETED.html new file mode 100644 index 0000000000..cbd752b8bb --- /dev/null +++ b/queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-COMPLETED.html @@ -0,0 +1,41 @@ + + + + + + + + + Confirmation of amalgamation + [[style.html]] + + + + + + + + + + diff --git a/queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-PAID.html b/queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-PAID.html new file mode 100644 index 0000000000..1f1f06b809 --- /dev/null +++ b/queue_services/entity-emailer/src/entity_emailer/email_templates/AMALGA-PAID.html @@ -0,0 +1,50 @@ + + + + + + + + + Amalgamation + [[style.html]] + + + + + + + + + + diff --git a/queue_services/entity-emailer/tests/unit/__init__.py b/queue_services/entity-emailer/tests/unit/__init__.py index 47c2e319c4..87c3df9f9f 100644 --- a/queue_services/entity-emailer/tests/unit/__init__.py +++ b/queue_services/entity-emailer/tests/unit/__init__.py @@ -45,6 +45,7 @@ AGM_LOCATION_CHANGE, ALTERATION, ALTERATION_FILING_TEMPLATE, + AMALGAMATION_APPLICATION, ANNUAL_REPORT, CHANGE_OF_DIRECTORS, CHANGE_OF_REGISTRATION, @@ -603,6 +604,41 @@ def prep_cp_special_resolution_correction_upload_memorandum_filing( return filing +def prep_amalgamation_filing(session, identifier, payment_id, option, legal_name): + """Return a new incorp filing prepped for email notification.""" + business = create_business(identifier, legal_type=Business.LegalTypes.BCOMP.value, legal_name=legal_name) + filing_template = copy.deepcopy(FILING_HEADER) + filing_template['filing']['header']['name'] = 'amalgamationApplication' + + filing_template['filing']['amalgamationApplication'] = copy.deepcopy(AMALGAMATION_APPLICATION) + filing_template['filing']['business'] = { + 'identifier': business.identifier, + 'legalType': Business.LegalTypes.BCOMP.value, + 'legalName': legal_name + } + filing_template['filing']['business'] = {'identifier': business.identifier} + for party in filing_template['filing']['amalgamationApplication']['parties']: + for role in party['roles']: + if role['roleType'] == 'Completing Party': + party['officer']['email'] = 'comp_party@email.com' + filing_template['filing']['amalgamationApplication']['contactPoint']['email'] = 'test@test.com' + + temp_identifier = 'Tb31yQIuBw' + temp_reg = RegistrationBootstrap() + temp_reg._identifier = temp_identifier + temp_reg.save() + filing = create_filing(token=payment_id, filing_json=filing_template, + business_id=business.id, bootstrap_id=temp_identifier) + filing.payment_completion_date = filing.filing_date + filing.save() + if option == Filing.Status.COMPLETED.value: + uow = versioning_manager.unit_of_work(session) + transaction = uow.create_transaction(session) + filing.transaction_id = transaction.id + filing.save() + return filing + + class Obj: """Make a custom object hook used by dict_to_obj.""" diff --git a/queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py b/queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py new file mode 100644 index 0000000000..12ef2506ab --- /dev/null +++ b/queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py @@ -0,0 +1,51 @@ +# Copyright © 2024 Province of British Columbia +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""The Unit Tests for the Amalgamation email processor.""" +from unittest.mock import patch + +import pytest +from legal_api.models import Filing + +from entity_emailer.email_processors import amalgamation_notification +from tests.unit import prep_amalgamation_filing + + +@pytest.mark.parametrize('status', [ + (Filing.Status.PAID.value), + (Filing.Status.COMPLETED.value) +]) +def test_amalgamation_notification(app, session, status): + """Assert Amalgamation notification is created.""" + # setup filing + business for email + legal_name = 'test business' + filing = prep_amalgamation_filing(session, 'BC1234567', '1', status, legal_name) + token = 'token' + # test processor + with patch.object(amalgamation_notification, '_get_pdfs', return_value=[]) as mock_get_pdfs: + email = amalgamation_notification.process( + {'filingId': filing.id, 'type': 'amalgamationApplication', 'option': status}, token) + + assert 'test@test.com' in email['recipients'] + if status == Filing.Status.PAID.value: + assert email['content']['subject'] == legal_name + ' - Amalgamation' + assert 'comp_party@email.com' in email['recipients'] + else: + assert email['content']['subject'] == legal_name + ' - Confirmation of Amalgamation' + + assert email['content']['body'] + assert email['content']['attachments'] == [] + assert mock_get_pdfs.call_args[0][0] == status + assert mock_get_pdfs.call_args[0][1] == token + assert mock_get_pdfs.call_args[0][2]['identifier'] == 'BC1234567' + assert mock_get_pdfs.call_args[0][3] == filing From 408a0720d62975559a338cb0b6c68e4e39f7abab Mon Sep 17 00:00:00 2001 From: JazzarKarim Date: Thu, 7 Mar 2024 14:24:34 -0800 Subject: [PATCH 012/113] 18803 Add amalgamation email cherry pick fixes --- .../entity-emailer/src/entity_emailer/resources/worker.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/queue_services/entity-emailer/src/entity_emailer/resources/worker.py b/queue_services/entity-emailer/src/entity_emailer/resources/worker.py index 88a5e13810..ea7ff6b08e 100644 --- a/queue_services/entity-emailer/src/entity_emailer/resources/worker.py +++ b/queue_services/entity-emailer/src/entity_emailer/resources/worker.py @@ -47,6 +47,7 @@ affiliation_notification, agm_extension_notification, agm_location_change_notification, + amalgamation_notification, ar_reminder_notification, bn_notification, change_of_registration_notification, @@ -195,6 +196,8 @@ def process_email(email_msg: dict, token: str): # pylint: disable=too-many-bran email = continuation_out_notification.process(email_msg["email"], token) elif etype == "specialResolution": email = special_resolution_notification.process(email_msg["email"], token) + elif etype == 'amalgamationApplication': + email = amalgamation_notification.process(email_msg['email'], token) # pylint: disable-next=consider-iterating-dictionary elif etype in filing_notification.FILING_TYPE_CONVERTER.keys(): if etype == "annualReport" and option == Filing.Status.COMPLETED.value: From 40daa19e76084d701885aee5b82ff6312b89d645 Mon Sep 17 00:00:00 2001 From: JazzarKarim Date: Thu, 7 Mar 2024 15:57:17 -0800 Subject: [PATCH 013/113] 18803 Add amalgamation email cherry pick fixes 2 --- .../amalgamation_notification.py | 92 +++++++++---------- .../test_amalgamation_notification.py | 26 +++--- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py b/queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py index 014893931d..5c3f0bd177 100644 --- a/queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py +++ b/queue_services/entity-emailer/src/entity_emailer/email_processors/amalgamation_notification.py @@ -40,8 +40,8 @@ def _get_pdfs( pdfs = [] attach_order = 1 headers = { - 'Accept': 'application/pdf', - 'Authorization': f'Bearer {token}' + "Accept": "application/pdf", + "Authorization": f"Bearer {token}" } if status == Filing.Status.PAID.value: @@ -51,41 +51,41 @@ def _get_pdfs( headers=headers ) if filing_pdf.status_code != HTTPStatus.OK: - logger.error('Failed to get pdf for filing: %s', filing.id) + logger.error("Failed to get pdf for filing: %s", filing.id) else: filing_pdf_encoded = base64.b64encode(filing_pdf.content) pdfs.append( { - 'fileName': 'Amalgamation Application.pdf', - 'fileBytes': filing_pdf_encoded.decode('utf-8'), - 'fileUrl': '', - 'attachOrder': attach_order + "fileName": "Amalgamation Application.pdf", + "fileBytes": filing_pdf_encoded.decode("utf-8"), + "fileUrl": "", + "attachOrder": attach_order } ) attach_order += 1 - corp_name = business.get('legalName') + corp_name = business.get("legalName") receipt = requests.post( f'{current_app.config.get("PAY_API_URL")}/{filing.payment_token}/receipts', json={ - 'corpName': corp_name, - 'filingDateTime': filing_date_time, - 'effectiveDateTime': effective_date if effective_date != filing_date_time else '', - 'filingIdentifier': str(filing.id), - 'businessNumber': business.get('taxId', '') + "corpName": corp_name, + "filingDateTime": filing_date_time, + "effectiveDateTime": effective_date if effective_date != filing_date_time else "", + "filingIdentifier": str(filing.id), + "businessNumber": business.get("taxId", "") }, headers=headers ) if receipt.status_code != HTTPStatus.CREATED: - logger.error('Failed to get receipt pdf for filing: %s', filing.id) + logger.error("Failed to get receipt pdf for filing: %s", filing.id) else: receipt_encoded = base64.b64encode(receipt.content) pdfs.append( { - 'fileName': 'Receipt.pdf', - 'fileBytes': receipt_encoded.decode('utf-8'), - 'fileUrl': '', - 'attachOrder': attach_order + "fileName": "Receipt.pdf", + "fileBytes": receipt_encoded.decode("utf-8"), + "fileUrl": "", + "attachOrder": attach_order } ) attach_order += 1 @@ -93,38 +93,38 @@ def _get_pdfs( # add certificate of amalgamation certificate = requests.get( f'{current_app.config.get("LEGAL_API_URL")}/businesses/{business["identifier"]}/filings/{filing.id}' - '?type=certificateOfAmalgamation', + "?type=certificateOfAmalgamation", headers=headers ) if certificate.status_code != HTTPStatus.OK: - logger.error('Failed to get corrected registration statement pdf for filing: %s', filing.id) + logger.error("Failed to get corrected registration statement pdf for filing: %s", filing.id) else: certificate_encoded = base64.b64encode(certificate.content) pdfs.append( { - 'fileName': 'Certificate Of Amalgamation.pdf', - 'fileBytes': certificate_encoded.decode('utf-8'), - 'fileUrl': '', - 'attachOrder': attach_order + "fileName": "Certificate Of Amalgamation.pdf", + "fileBytes": certificate_encoded.decode("utf-8"), + "fileUrl": "", + "attachOrder": attach_order } ) attach_order += 1 # add notice of articles noa = requests.get( f'{current_app.config.get("LEGAL_API_URL")}/businesses/{business["identifier"]}/filings/{filing.id}' - '?type=noticeOfArticles', + "?type=noticeOfArticles", headers=headers ) if noa.status_code != HTTPStatus.OK: - logger.error('Failed to get noa pdf for filing: %s', filing.id) + logger.error("Failed to get noa pdf for filing: %s", filing.id) else: noa_encoded = base64.b64encode(noa.content) pdfs.append( { - 'fileName': 'Notice of Articles.pdf', - 'fileBytes': noa_encoded.decode('utf-8'), - 'fileUrl': '', - 'attachOrder': attach_order + "fileName": "Notice of Articles.pdf", + "fileBytes": noa_encoded.decode("utf-8"), + "fileUrl": "", + "attachOrder": attach_order } ) attach_order += 1 @@ -133,25 +133,25 @@ def _get_pdfs( def process(email_info: dict, token: str) -> dict: # pylint: disable=too-many-locals, , too-many-branches """Build the email for Amalgamation notification.""" - logger.debug('filing_notification: %s', email_info) + logger.debug("filing_notification: %s", email_info) # get template and fill in parts - filing_type, status = email_info['type'], email_info['option'] + filing_type, status = email_info["type"], email_info["option"] # get template vars from filing - filing, business, leg_tmz_filing_date, leg_tmz_effective_date = get_filing_info(email_info['filingId']) - filing_name = filing.filing_type[0].upper() + ' '.join(re.findall('[a-zA-Z][^A-Z]*', filing.filing_type[1:])) + filing, business, leg_tmz_filing_date, leg_tmz_effective_date = get_filing_info(email_info["filingId"]) + filing_name = filing.filing_type[0].upper() + " ".join(re.findall("[a-zA-Z][^A-Z]*", filing.filing_type[1:])) template = Path(f'{current_app.config.get("TEMPLATE_PATH")}/AMALGA-{status}.html').read_text() filled_template = substitute_template_parts(template) # render template with vars jnja_template = Template(filled_template, autoescape=True) - filing_data = (filing.json)['filing'][f'{filing_type}'] + filing_data = (filing.json)["filing"][f'{filing_type}'] html_out = jnja_template.render( business=business, filing=filing_data, - header=(filing.json)['filing']['header'], + header=(filing.json)["filing"]["header"], filing_date_time=leg_tmz_filing_date, effective_date_time=leg_tmz_effective_date, - entity_dashboard_url=current_app.config.get('DASHBOARD_URL') + business.get('identifier', ''), + entity_dashboard_url=current_app.config.get("DASHBOARD_URL") + business.get("identifier", ""), email_header=filing_name.upper(), filing_type=filing_type ) @@ -165,17 +165,17 @@ def process(email_info: dict, token: str) -> dict: # pylint: disable=too-many-l return {} # assign subject - legal_name = business.get('legalName', None) - subject = f'{legal_name} - Amalgamation' + legal_name = business.get("legalName", None) + subject = f"{legal_name} - Amalgamation" if status == Filing.Status.COMPLETED.value: - subject = f'{legal_name} - Confirmation of Amalgamation' + subject = f"{legal_name} - Confirmation of Amalgamation" return { - 'recipients': recipients, - 'requestBy': 'BCRegistries@gov.bc.ca', - 'content': { - 'subject': subject, - 'body': f'{html_out}', - 'attachments': pdfs + "recipients": recipients, + "requestBy": "BCRegistries@gov.bc.ca", + "content": { + "subject": subject, + "body": f"{html_out}", + "attachments": pdfs } } diff --git a/queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py b/queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py index 12ef2506ab..900d9f6b63 100644 --- a/queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py +++ b/queue_services/entity-emailer/tests/unit/email_processors/test_amalgamation_notification.py @@ -21,31 +21,31 @@ from tests.unit import prep_amalgamation_filing -@pytest.mark.parametrize('status', [ +@pytest.mark.parametrize("status", [ (Filing.Status.PAID.value), (Filing.Status.COMPLETED.value) ]) def test_amalgamation_notification(app, session, status): """Assert Amalgamation notification is created.""" # setup filing + business for email - legal_name = 'test business' - filing = prep_amalgamation_filing(session, 'BC1234567', '1', status, legal_name) - token = 'token' + legal_name = "test business" + filing = prep_amalgamation_filing(session, "BC1234567", "1", status, legal_name) + token = "token" # test processor - with patch.object(amalgamation_notification, '_get_pdfs', return_value=[]) as mock_get_pdfs: + with patch.object(amalgamation_notification, "_get_pdfs", return_value=[]) as mock_get_pdfs: email = amalgamation_notification.process( - {'filingId': filing.id, 'type': 'amalgamationApplication', 'option': status}, token) + {"filingId": filing.id, "type": "amalgamationApplication", "option": status}, token) - assert 'test@test.com' in email['recipients'] + assert "test@test.com" in email["recipients"] if status == Filing.Status.PAID.value: - assert email['content']['subject'] == legal_name + ' - Amalgamation' - assert 'comp_party@email.com' in email['recipients'] + assert email["content"]["subject"] == legal_name + " - Amalgamation" + assert "comp_party@email.com" in email["recipients"] else: - assert email['content']['subject'] == legal_name + ' - Confirmation of Amalgamation' + assert email["content"]["subject"] == legal_name + " - Confirmation of Amalgamation" - assert email['content']['body'] - assert email['content']['attachments'] == [] + assert email["content"]["body"] + assert email["content"]["attachments"] == [] assert mock_get_pdfs.call_args[0][0] == status assert mock_get_pdfs.call_args[0][1] == token - assert mock_get_pdfs.call_args[0][2]['identifier'] == 'BC1234567' + assert mock_get_pdfs.call_args[0][2]["identifier"] == "BC1234567" assert mock_get_pdfs.call_args[0][3] == filing From cc0227bfea729e70d91c5774c7cfabe7c1f1b223 Mon Sep 17 00:00:00 2001 From: JazzarKarim Date: Thu, 7 Mar 2024 16:27:31 -0800 Subject: [PATCH 014/113] ran lint on legal api --- .../legal_api/reports/business_document.py | 15 +- .../resources/v2/business/business.py | 4 +- legal-api/src/legal_api/services/authz.py | 18 +- .../validations/amalgamation_application.py | 45 ++--- .../test_amalgamation_application.py | 169 +++++++++++------- 5 files changed, 147 insertions(+), 104 deletions(-) diff --git a/legal-api/src/legal_api/reports/business_document.py b/legal-api/src/legal_api/reports/business_document.py index e1cd40709d..94766a2c07 100644 --- a/legal-api/src/legal_api/reports/business_document.py +++ b/legal-api/src/legal_api/reports/business_document.py @@ -330,8 +330,9 @@ def _set_business_state_changes(self, legal_entity: dict): ): state_filings.append(self._format_state_filing(filing)) # If it is amalgamating business - if ((legal_entity.get("business").get("state") == "HISTORICAL") - and (legal_entity.get("business").get("amalgamatedInto"))): + if (legal_entity.get("business").get("state") == "HISTORICAL") and ( + legal_entity.get("business").get("amalgamatedInto") + ): amalgamating_business_temp = LegalEntity.find_by_identifier(legal_entity.get("business").get("identifier")) amalgamating_business = amalgamating_business_temp.amalgamating_businesses.one_or_none() amalgamation = Amalgamation.find_by_id(amalgamating_business.amalgamation_id) @@ -463,8 +464,9 @@ def _set_amalgamation_details(self, legal_entity: dict): amalgamation_application = Filing.get_filings_by_types(self._legal_entity, ["amalgamationApplication"]) if amalgamation_application: legal_entity["business"]["amalgamatedEntity"] = True - amalgamation_json = amalgamation_application[0].filing_json.get("filing", {})\ - .get("amalgamationApplication", {}) + amalgamation_json = ( + amalgamation_application[0].filing_json.get("filing", {}).get("amalgamationApplication", {}) + ) # if it's future effective if self._epoch_filing_date and amalgamation_application[0].effective_date < self._epoch_filing_date: amalgamated_businesses_info = {"legalName": NOT_AVAILABLE, "identifier": NOT_AVAILABLE} @@ -478,10 +480,7 @@ def _set_amalgamation_details(self, legal_entity: dict): identifier = amalgamating_businesses[0].get("corpNumber", {}) amalgamating_business = legal_entity.find_by_identifier(identifier) business_legal_name = amalgamating_business.legal_name - amalgamated_businesses_info = { - "legalName": business_legal_name, - "identifier": identifier - } + amalgamated_businesses_info = {"legalName": business_legal_name, "identifier": identifier} amalgamated_businesses.append(amalgamated_businesses_info) amalgamating_businesses.remove(amalgamating_businesses[0]) legal_entity["amalgamatedEntities"] = amalgamated_businesses diff --git a/legal-api/src/legal_api/resources/v2/business/business.py b/legal-api/src/legal_api/resources/v2/business/business.py index a6397d7bf9..4f39ccee1f 100644 --- a/legal-api/src/legal_api/resources/v2/business/business.py +++ b/legal-api/src/legal_api/resources/v2/business/business.py @@ -96,8 +96,8 @@ def get_businesses(identifier: str): # A business can be affiliated in multiple accounts (in user account as well as in gov staff account's) # AccountService.get_account_by_affiliated_identifier will fetch all of it # check one of it has `q_account` - if any(str(org.get('id')) == q_account for org in orgs): - business_json['accountId'] = q_account + if any(str(org.get("id")) == q_account for org in orgs): + business_json["accountId"] = q_account return jsonify(business=business_json) diff --git a/legal-api/src/legal_api/services/authz.py b/legal-api/src/legal_api/services/authz.py index 3df546bf70..3b5f7c862c 100644 --- a/legal-api/src/legal_api/services/authz.py +++ b/legal-api/src/legal_api/services/authz.py @@ -156,8 +156,7 @@ def get_allowable_filings_dict(): "regular": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN, - BusinessBlocker.NOT_IN_GOOD_STANDING], + "business": [BusinessBlocker.BUSINESS_FROZEN, BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -167,8 +166,7 @@ def get_allowable_filings_dict(): "vertical": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN, - BusinessBlocker.NOT_IN_GOOD_STANDING], + "business": [BusinessBlocker.BUSINESS_FROZEN, BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -178,8 +176,7 @@ def get_allowable_filings_dict(): "horizontal": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN, - BusinessBlocker.NOT_IN_GOOD_STANDING], + "business": [BusinessBlocker.BUSINESS_FROZEN, BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -320,8 +317,7 @@ def get_allowable_filings_dict(): "regular": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN, - BusinessBlocker.NOT_IN_GOOD_STANDING], + "business": [BusinessBlocker.BUSINESS_FROZEN, BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -331,8 +327,7 @@ def get_allowable_filings_dict(): "vertical": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN, - BusinessBlocker.NOT_IN_GOOD_STANDING], + "business": [BusinessBlocker.BUSINESS_FROZEN, BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, @@ -342,8 +337,7 @@ def get_allowable_filings_dict(): "horizontal": { "legalTypes": ["BEN", "BC", "ULC", "CC"], "blockerChecks": { - "business": [BusinessBlocker.BUSINESS_FROZEN, - BusinessBlocker.NOT_IN_GOOD_STANDING], + "business": [BusinessBlocker.BUSINESS_FROZEN, BusinessBlocker.NOT_IN_GOOD_STANDING], "futureEffectiveFilings": [ filing_types_compact.DISSOLUTION_VOLUNTARY, filing_types_compact.DISSOLUTION_ADMINISTRATIVE, diff --git a/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py b/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py index 0953d33c57..ce5fb3277b 100644 --- a/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py +++ b/legal-api/src/legal_api/services/filings/validations/amalgamation_application.py @@ -115,10 +115,12 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m duplicate_businesses.append(corp_number) amalgamating_businesses[corp_number] = amalgamating_business_json - if (corp_number.startswith("A") and - (foreign_jurisdiction := amalgamating_business_json.get("foreignJurisdiction")) and - foreign_jurisdiction.get("country") == "CA" and - foreign_jurisdiction.get("region") == "BC"): + if ( + corp_number.startswith("A") + and (foreign_jurisdiction := amalgamating_business_json.get("foreignJurisdiction")) + and foreign_jurisdiction.get("country") == "CA" + and foreign_jurisdiction.get("region") == "BC" + ): is_any_expro_a = True is_any_bc_company = is_any_ben or is_any_limited or is_any_ccc or is_any_ulc @@ -138,7 +140,10 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m ) elif _has_pending_filing(amalgamating_business): msg.append( - {"error": f"{identifier} has a draft, pending or future effective filing.", "path": amalgamating_businesses_path} + { + "error": f"{identifier} has a draft, pending or future effective filing.", + "path": amalgamating_businesses_path, + } ) if not is_staff: @@ -193,22 +198,21 @@ def validate_amalgamating_businesses( # pylint: disable=too-many-branches,too-m "A BC Unlimited Liability Company cannot amalgamate with " f"a foreign company {foreign_legal_name}." ), - "path": amalgamating_businesses_path - }) + "path": amalgamating_businesses_path, + } + ) if duplicate_businesses: - error_msg = "Duplicate amalgamating business entry found in list: " + \ - ", ".join(duplicate_businesses) + "." - msg.append({ - "error": error_msg, - "path": amalgamating_businesses_path - }) + error_msg = "Duplicate amalgamating business entry found in list: " + ", ".join(duplicate_businesses) + "." + msg.append({"error": error_msg, "path": amalgamating_businesses_path}) if len(amalgamating_businesses) < 2: - msg.append({ - "error": "Two or more amalgamating businesses required.", - "path": amalgamating_businesses_path, - }) + msg.append( + { + "error": "Two or more amalgamating businesses required.", + "path": amalgamating_businesses_path, + } + ) if entity_type == BusinessCommon.EntityTypes.BC_CCC.value and not is_any_ccc: msg.append( @@ -249,10 +253,9 @@ def _is_business_affliated(identifier, account_id): def _has_pending_filing(amalgamating_business: any): - if Filing.get_filings_by_status(amalgamating_business.id, [ - Filing.Status.DRAFT.value, - Filing.Status.PENDING.value, - Filing.Status.PAID.value]): + if Filing.get_filings_by_status( + amalgamating_business.id, [Filing.Status.DRAFT.value, Filing.Status.PENDING.value, Filing.Status.PAID.value] + ): return True return False diff --git a/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py b/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py index 4f6fca0055..a4401a6408 100644 --- a/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py +++ b/legal-api/tests/unit/services/filings/validations/test_amalgamation_application.py @@ -1632,7 +1632,10 @@ def mock_find_by_identifier(identifier): @pytest.mark.parametrize( "test_status, expected_code, expected_msg", - [('FAIL', HTTPStatus.BAD_REQUEST, 'BC1234567 has a draft, pending or future effective filing.'), ("SUCCESS", None, None)], + [ + ("FAIL", HTTPStatus.BAD_REQUEST, "BC1234567 has a draft, pending or future effective filing."), + ("SUCCESS", None, None), + ], ) def test_has_pending_filing(mocker, app, session, jwt, test_status, expected_code, expected_msg): """Assert valid amalgamating businesses has draft, pending or future effective filing.""" @@ -2139,94 +2142,138 @@ def mock_find_by_identifier(identifier): @pytest.mark.parametrize( - 'test_status, amalgamating_businesses, expected_code, expected_msg', - [ - ('FAIL_BC', [ - {'role': 'amalgamating','identifier': 'BC1234567'}, - {'role': 'amalgamating','identifier': 'BC1234567'}, - {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'} - ], HTTPStatus.BAD_REQUEST, 'Duplicate amalgamating business entry found in list: BC1234567.'), - ('FAIL_EXPRO', [ - {'role': 'amalgamating','identifier': 'BC1234567'}, - {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'}, - {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'} - ], HTTPStatus.BAD_REQUEST, 'Duplicate amalgamating business entry found in list: 123456.'), - ('SUCCESS', [ - {'role': 'amalgamating','identifier': 'BC1234567'}, - {'role': 'amalgamating','legalName': 'Foreign Co.','foreignJurisdiction': {'country': 'CA'},'corpNumber': '123456'} - ], None, None) - ] + "test_status, amalgamating_businesses, expected_code, expected_msg", + [ + ( + "FAIL_BC", + [ + {"role": "amalgamating", "identifier": "BC1234567"}, + {"role": "amalgamating", "identifier": "BC1234567"}, + { + "role": "amalgamating", + "legalName": "Foreign Co.", + "foreignJurisdiction": {"country": "CA"}, + "corpNumber": "123456", + }, + ], + HTTPStatus.BAD_REQUEST, + "Duplicate amalgamating business entry found in list: BC1234567.", + ), + ( + "FAIL_EXPRO", + [ + {"role": "amalgamating", "identifier": "BC1234567"}, + { + "role": "amalgamating", + "legalName": "Foreign Co.", + "foreignJurisdiction": {"country": "CA"}, + "corpNumber": "123456", + }, + { + "role": "amalgamating", + "legalName": "Foreign Co.", + "foreignJurisdiction": {"country": "CA"}, + "corpNumber": "123456", + }, + ], + HTTPStatus.BAD_REQUEST, + "Duplicate amalgamating business entry found in list: 123456.", + ), + ( + "SUCCESS", + [ + {"role": "amalgamating", "identifier": "BC1234567"}, + { + "role": "amalgamating", + "legalName": "Foreign Co.", + "foreignJurisdiction": {"country": "CA"}, + "corpNumber": "123456", + }, + ], + None, + None, + ), + ], ) -def test_duplicate_amalgamating_businesses(mocker, app, session, jwt, test_status, amalgamating_businesses, - expected_code, expected_msg): +def test_duplicate_amalgamating_businesses( + mocker, app, session, jwt, test_status, amalgamating_businesses, expected_code, expected_msg +): """Assert duplicate amalgamating businesses.""" - account_id = '123456' - filing = {'filing': {}} - filing['filing']['header'] = {'name': 'amalgamationApplication', 'date': '2019-04-08', - 'certifiedBy': 'full name', 'email': 'no_one@never.get', 'filingId': 1} - filing['filing']['amalgamationApplication'] = copy.deepcopy(AMALGAMATION_APPLICATION) - filing['filing']['amalgamationApplication']['amalgamatingBusinesses'] = amalgamating_businesses + account_id = "123456" + filing = {"filing": {}} + filing["filing"]["header"] = { + "name": "amalgamationApplication", + "date": "2019-04-08", + "certifiedBy": "full name", + "email": "no_one@never.get", + "filingId": 1, + } + filing["filing"]["amalgamationApplication"] = copy.deepcopy(AMALGAMATION_APPLICATION) + filing["filing"]["amalgamationApplication"]["amalgamatingBusinesses"] = amalgamating_businesses def mock_find_by_identifier(identifier): - return LegalEntity(identifier=identifier, - legal_type=LegalEntity.EntityTypes.BCOMP.value) + return LegalEntity(identifier=identifier, legal_type=LegalEntity.EntityTypes.BCOMP.value) - mocker.patch('legal_api.services.filings.validations.amalgamation_application.validate_name_request', - return_value=[]) - mocker.patch('legal_api.services.filings.validations.amalgamation_application._has_pending_filing', - return_value=False) + mocker.patch( + "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] + ) + mocker.patch( + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False + ) mocker.patch("legal_api.models.legal_entity.LegalEntity.find_by_identifier", side_effect=mock_find_by_identifier) - mocker.patch('legal_api.utils.auth.jwt.validate_roles', return_value=True) # Staff + mocker.patch("legal_api.utils.auth.jwt.validate_roles", return_value=True) # Staff err = validate(None, filing, account_id) - + # validate outcomes - if test_status == 'SUCCESS': + if test_status == "SUCCESS": assert not err else: assert expected_code == err.code - assert expected_msg == err.msg[0]['error'] + assert expected_msg == err.msg[0]["error"] @pytest.mark.parametrize( - 'test_status, expected_code, expected_msg', - [ - ('FAIL', HTTPStatus.BAD_REQUEST, 'Two or more amalgamating businesses required.'), - ('SUCCESS', None, None) - ] + "test_status, expected_code, expected_msg", + [("FAIL", HTTPStatus.BAD_REQUEST, "Two or more amalgamating businesses required."), ("SUCCESS", None, None)], ) def test_amalgamating_businesses_number(mocker, app, session, jwt, test_status, expected_code, expected_msg): """Assert two or more amalgamating businesses required.""" - account_id = '123456' - filing = {'filing': {}} - filing['filing']['header'] = {'name': 'amalgamationApplication', 'date': '2019-04-08', - 'certifiedBy': 'full name', 'email': 'no_one@never.get', 'filingId': 1} - filing['filing']['amalgamationApplication'] = copy.deepcopy(AMALGAMATION_APPLICATION) - - if test_status == 'FAIL': - filing['filing']['amalgamationApplication']['amalgamatingBusinesses'] = [] + account_id = "123456" + filing = {"filing": {}} + filing["filing"]["header"] = { + "name": "amalgamationApplication", + "date": "2019-04-08", + "certifiedBy": "full name", + "email": "no_one@never.get", + "filingId": 1, + } + filing["filing"]["amalgamationApplication"] = copy.deepcopy(AMALGAMATION_APPLICATION) + + if test_status == "FAIL": + filing["filing"]["amalgamationApplication"]["amalgamatingBusinesses"] = [] else: - filing['filing']['amalgamationApplication']['amalgamatingBusinesses'][1]['corpNumber'] - + filing["filing"]["amalgamationApplication"]["amalgamatingBusinesses"][1]["corpNumber"] def mock_find_by_identifier(identifier): - return LegalEntity(identifier=identifier, - legal_type=LegalEntity.LegalTypes.BCOMP.value) + return LegalEntity(identifier=identifier, legal_type=LegalEntity.LegalTypes.BCOMP.value) - mocker.patch('legal_api.services.filings.validations.amalgamation_application.validate_name_request', - return_value=[]) - mocker.patch('legal_api.services.filings.validations.amalgamation_application._has_pending_filing', - return_value=False) - mocker.patch('legal_api.models.legal_entity.LegalEntity.find_by_identifier', side_effect=mock_find_by_identifier) + mocker.patch( + "legal_api.services.filings.validations.amalgamation_application.validate_name_request", return_value=[] + ) + mocker.patch( + "legal_api.services.filings.validations.amalgamation_application._has_pending_filing", return_value=False + ) + mocker.patch("legal_api.models.legal_entity.LegalEntity.find_by_identifier", side_effect=mock_find_by_identifier) - mocker.patch('legal_api.utils.auth.jwt.validate_roles', return_value=True) # Staff + mocker.patch("legal_api.utils.auth.jwt.validate_roles", return_value=True) # Staff err = validate(None, filing, account_id) # validate outcomes - if test_status == 'SUCCESS': + if test_status == "SUCCESS": assert not err else: assert expected_code == err.code - assert expected_msg == err.msg[0]['error'] + assert expected_msg == err.msg[0]["error"] From cb7a7dc4615b73c25f3c99a42867ea314461a2e5 Mon Sep 17 00:00:00 2001 From: James Date: Tue, 23 Jan 2024 13:30:22 -0800 Subject: [PATCH 015/113] 19292-TING-amalgamation-alert-for-future-effective-dated --- .../warnings/business/business_checks/__init__.py | 1 + .../warnings/business/business_checks/business.py | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/legal-api/src/legal_api/services/warnings/business/business_checks/__init__.py b/legal-api/src/legal_api/services/warnings/business/business_checks/__init__.py index eef42d5e66..a7b5def643 100644 --- a/legal-api/src/legal_api/services/warnings/business/business_checks/__init__.py +++ b/legal-api/src/legal_api/services/warnings/business/business_checks/__init__.py @@ -19,6 +19,7 @@ class WarningType(str, Enum): """Render an Enum of the Warning Types.""" MISSING_REQUIRED_BUSINESS_INFO = "MISSING_REQUIRED_BUSINESS_INFO" + FUTURE_EFFECTIVE_AMALGAMATION = "FUTURE_EFFECTIVE_AMALGAMATION" class BusinessWarningCodes(str, Enum): diff --git a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py index 4c4845aa5b..b30e63500a 100644 --- a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py +++ b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py @@ -14,7 +14,7 @@ """Service to check compliancy for a LegalEntity.""" from .firms import check_business as firms_check # noqa: I003 - +from legal_api.services.warnings.business.business_checks import WarningType def check_business(business: any) -> list: """Check business for warnings.""" @@ -23,4 +23,16 @@ def check_business(business: any) -> list: if business.is_firm: result = firms_check(business) + ting_info = Business.check_if_ting(business.identifier) + if ting_info: + result =[ + { + "code": "AMALGAMATING_BUSINESS", + "message": "This business is part of a future effective amalgamation.", + "warningType": WarningType.FUTURE_EFFECTIVE_AMALGAMATION, + "data": { + "amalgamationDate": ting_info + } + } + ] return result From 7aade07b83dec19d632f4d54a2ea8ff273f7f8a5 Mon Sep 17 00:00:00 2001 From: JazzarKarim Date: Fri, 8 Mar 2024 10:51:41 -0800 Subject: [PATCH 016/113] 19292-TING-amalgamation-alert-for-future-effective-dated cherry pick fixes --- .../src/legal_api/models/legal_entity.py | 19 +++++++++++++++++++ .../business/business_checks/business.py | 3 ++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/legal-api/src/legal_api/models/legal_entity.py b/legal-api/src/legal_api/models/legal_entity.py index 81167ab316..158bded971 100644 --- a/legal-api/src/legal_api/models/legal_entity.py +++ b/legal-api/src/legal_api/models/legal_entity.py @@ -27,6 +27,7 @@ from sqlalchemy.exc import OperationalError, ResourceClosedError from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import backref +from sqlalchemy.sql.expression import text from legal_api.exceptions import BusinessException from legal_api.utils.base import BaseMeta @@ -565,6 +566,24 @@ def name(self) -> str: return " ".join((self.first_name, self.middle_initial, self.last_name)).strip().upper() return " ".join((self.first_name, self.last_name)).strip().upper() return self._legal_name + + @classmethod + def check_if_ting(cls, business_identifier): + # Construct a JSON containment check clause for the SQL query + where_clause = text( + "filing_json->'filing'->'amalgamationApplication'->'amalgamatingBusinesses'" + + f' @>\'[{{"identifier": "{business_identifier}"}}]\'') + + # Query the database to find amalgamation filings + filing = db.session.query(Filing). \ + filter( Filing._status == Filing.Status.PAID.value, + Filing._filing_type == 'amalgamationApplication', # Check for the filing type + where_clause # Apply the JSON containment check + ).one_or_none() + + # Check if a matching filing was found and if its effective date is greater than payment completion date + if filing and filing.effective_date > filing.payment_completion_date: + return filing.effective_date @classmethod def find_by_legal_name(cls, legal_name: str = None): diff --git a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py index b30e63500a..3cbb4883cd 100644 --- a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py +++ b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py @@ -15,6 +15,7 @@ """Service to check compliancy for a LegalEntity.""" from .firms import check_business as firms_check # noqa: I003 from legal_api.services.warnings.business.business_checks import WarningType +from legal_api.models import LegalEntity def check_business(business: any) -> list: """Check business for warnings.""" @@ -23,7 +24,7 @@ def check_business(business: any) -> list: if business.is_firm: result = firms_check(business) - ting_info = Business.check_if_ting(business.identifier) + ting_info = LegalEntity.check_if_ting(business.identifier) if ting_info: result =[ { From f75e40fce905638d0dae81dd4e8ae6a53835eb29 Mon Sep 17 00:00:00 2001 From: Paul <144158015+PaulGarewal@users.noreply.github.com> Date: Tue, 23 Jan 2024 13:31:42 -0800 Subject: [PATCH 017/113] added spacing to amalgamating corp information (#2408) --- .../template-parts/amalgamation/amalgamatingCorp.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html index 8ea50f34f8..8f5feb96c9 100644 --- a/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html +++ b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html @@ -15,12 +15,12 @@ {% for entity in amalgamatingBusinesses %} -
+
{{ entity.name }}
-
+
{{ entity.identifier }}
From 587853e8f313db2149a1f9ac1a9328d3bf00811c Mon Sep 17 00:00:00 2001 From: Karim El Jazzar <122301442+JazzarKarim@users.noreply.github.com> Date: Wed, 24 Jan 2024 11:31:42 -0800 Subject: [PATCH 018/113] bump version numbers up for release 20.1b (#2412) --- legal-api/src/legal_api/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legal-api/src/legal_api/version.py b/legal-api/src/legal_api/version.py index 1117e16b9d..cdb0ed0ee3 100644 --- a/legal-api/src/legal_api/version.py +++ b/legal-api/src/legal_api/version.py @@ -22,4 +22,4 @@ Development release segment: .devN """ -__version__ = "2.100.0" # pylint: disable=invalid-name +__version__ = '2.101.0' # pylint: disable=invalid-name From 192110b18284db3c0e1afd7fc2d67deee2b469d3 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 24 Jan 2024 14:06:11 -0800 Subject: [PATCH 019/113] Fixed lint errors and updated code to folow existing pattern --- .../business/business_checks/business.py | 11 +++- .../business/business_checks/corps.py | 55 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 legal-api/src/legal_api/services/warnings/business/business_checks/corps.py diff --git a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py index 3cbb4883cd..91704176ce 100644 --- a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py +++ b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py @@ -16,6 +16,7 @@ from .firms import check_business as firms_check # noqa: I003 from legal_api.services.warnings.business.business_checks import WarningType from legal_api.models import LegalEntity +from .corps import check_business as corps_check def check_business(business: any) -> list: """Check business for warnings.""" @@ -23,10 +24,16 @@ def check_business(business: any) -> list: if business.is_firm: result = firms_check(business) + elif business.legal_type in \ + (LegalEntity.EntityTypes.BC_CCC, + LegalEntity.EntityTypes.BC_ULC_COMPANY.value, + LegalEntity.EntityTypes.COMP.value, + LegalEntity.EntityTypes.BCOMP.value): + result = corps_check(business) ting_info = LegalEntity.check_if_ting(business.identifier) if ting_info: - result =[ + result = [ { "code": "AMALGAMATING_BUSINESS", "message": "This business is part of a future effective amalgamation.", @@ -35,5 +42,5 @@ def check_business(business: any) -> list: "amalgamationDate": ting_info } } - ] + ] return result diff --git a/legal-api/src/legal_api/services/warnings/business/business_checks/corps.py b/legal-api/src/legal_api/services/warnings/business/business_checks/corps.py new file mode 100644 index 0000000000..ce52a5a36a --- /dev/null +++ b/legal-api/src/legal_api/services/warnings/business/business_checks/corps.py @@ -0,0 +1,55 @@ +# Copyright © 2022 Province of British Columbia +# +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from sqlalchemy.sql.expression import text # noqa: I001 + +from legal_api.models import Business, Filing, db +from legal_api.services.warnings.business.business_checks import WarningType + +def check_business(business: Business) -> list: + """Check for missing business data.""" + result = [] + + result.extend(check_amalgamating_business(business)) + + return result + +def check_amalgamating_business(business: Business) -> list: + """Check if business is currently pending amalgamation.""" + result = [] + + # Construct a JSON containment check clause for the SQL query + where_clause = text( + "filing_json->'filing'->'amalgamationApplication'->'amalgamatingBusinesses'" + + f' @>\'[{{"identifier": "{business.identifier}"}}]\'') + + # Query the database to find amalgamation filings + filing = db.session.query(Filing). \ + filter( Filing._status == Filing.Status.PAID.value, + Filing._filing_type == 'amalgamationApplication', # Check for the filing type + where_clause # Apply the JSON containment check + ).one_or_none() + + # Check if a matching filing was found and if its effective date is greater than payment completion date + if filing and filing.effective_date > filing.payment_completion_date: + result.append({ + "code": "AMALGAMATING_BUSINESS", + "message": "This business is part of a future effective amalgamation.", + "warningType": WarningType.FUTURE_EFFECTIVE_AMALGAMATION, + "data": { + "amalgamationDate": filing.effective_date + } + }) + + return result From ae58a4a32581640e880fe257d6dacd54fbecf086 Mon Sep 17 00:00:00 2001 From: JazzarKarim Date: Tue, 12 Mar 2024 11:32:27 -0700 Subject: [PATCH 020/113] Fixed lint errors and updated code to folow existing pattern cherry pick fixes --- .../src/legal_api/models/legal_entity.py | 19 ------------------- .../business/business_checks/business.py | 12 ------------ .../business/business_checks/corps.py | 10 +++++----- 3 files changed, 5 insertions(+), 36 deletions(-) diff --git a/legal-api/src/legal_api/models/legal_entity.py b/legal-api/src/legal_api/models/legal_entity.py index 158bded971..81167ab316 100644 --- a/legal-api/src/legal_api/models/legal_entity.py +++ b/legal-api/src/legal_api/models/legal_entity.py @@ -27,7 +27,6 @@ from sqlalchemy.exc import OperationalError, ResourceClosedError from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import backref -from sqlalchemy.sql.expression import text from legal_api.exceptions import BusinessException from legal_api.utils.base import BaseMeta @@ -566,24 +565,6 @@ def name(self) -> str: return " ".join((self.first_name, self.middle_initial, self.last_name)).strip().upper() return " ".join((self.first_name, self.last_name)).strip().upper() return self._legal_name - - @classmethod - def check_if_ting(cls, business_identifier): - # Construct a JSON containment check clause for the SQL query - where_clause = text( - "filing_json->'filing'->'amalgamationApplication'->'amalgamatingBusinesses'" + - f' @>\'[{{"identifier": "{business_identifier}"}}]\'') - - # Query the database to find amalgamation filings - filing = db.session.query(Filing). \ - filter( Filing._status == Filing.Status.PAID.value, - Filing._filing_type == 'amalgamationApplication', # Check for the filing type - where_clause # Apply the JSON containment check - ).one_or_none() - - # Check if a matching filing was found and if its effective date is greater than payment completion date - if filing and filing.effective_date > filing.payment_completion_date: - return filing.effective_date @classmethod def find_by_legal_name(cls, legal_name: str = None): diff --git a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py index 91704176ce..e4c412d7a4 100644 --- a/legal-api/src/legal_api/services/warnings/business/business_checks/business.py +++ b/legal-api/src/legal_api/services/warnings/business/business_checks/business.py @@ -31,16 +31,4 @@ def check_business(business: any) -> list: LegalEntity.EntityTypes.BCOMP.value): result = corps_check(business) - ting_info = LegalEntity.check_if_ting(business.identifier) - if ting_info: - result = [ - { - "code": "AMALGAMATING_BUSINESS", - "message": "This business is part of a future effective amalgamation.", - "warningType": WarningType.FUTURE_EFFECTIVE_AMALGAMATION, - "data": { - "amalgamationDate": ting_info - } - } - ] return result diff --git a/legal-api/src/legal_api/services/warnings/business/business_checks/corps.py b/legal-api/src/legal_api/services/warnings/business/business_checks/corps.py index ce52a5a36a..d8fc144862 100644 --- a/legal-api/src/legal_api/services/warnings/business/business_checks/corps.py +++ b/legal-api/src/legal_api/services/warnings/business/business_checks/corps.py @@ -14,25 +14,25 @@ from sqlalchemy.sql.expression import text # noqa: I001 -from legal_api.models import Business, Filing, db +from legal_api.models import LegalEntity, Filing, db from legal_api.services.warnings.business.business_checks import WarningType -def check_business(business: Business) -> list: +def check_business(legal_entity: LegalEntity) -> list: """Check for missing business data.""" result = [] - result.extend(check_amalgamating_business(business)) + result.extend(check_amalgamating_business(legal_entity)) return result -def check_amalgamating_business(business: Business) -> list: +def check_amalgamating_business(legal_entity: LegalEntity) -> list: """Check if business is currently pending amalgamation.""" result = [] # Construct a JSON containment check clause for the SQL query where_clause = text( "filing_json->'filing'->'amalgamationApplication'->'amalgamatingBusinesses'" + - f' @>\'[{{"identifier": "{business.identifier}"}}]\'') + f' @>\'[{{"identifier": "{legal_entity.identifier}"}}]\'') # Query the database to find amalgamation filings filing = db.session.query(Filing). \ From decbd5836c3c11326f8e9703c532abdfafd1c3b6 Mon Sep 17 00:00:00 2001 From: Paul <144158015+PaulGarewal@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:36:14 -0800 Subject: [PATCH 021/113] 19432 changed name in various amalgamation outputs from corporation(s) to business(es) (#2414) --- legal-api/report-templates/certificateOfAmalgamation.html | 2 +- .../template-parts/amalgamation/amalgamatingCorp.html | 4 ++-- .../template-parts/business-summary/amalgamating.html | 2 +- .../template-parts/business-summary/amalgamations.html | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/legal-api/report-templates/certificateOfAmalgamation.html b/legal-api/report-templates/certificateOfAmalgamation.html index f323b52b95..2cf69d1adf 100644 --- a/legal-api/report-templates/certificateOfAmalgamation.html +++ b/legal-api/report-templates/certificateOfAmalgamation.html @@ -25,7 +25,7 @@
-
I hereby certify that the following companies were amalgamated under the name
+
I hereby certify that the following businesses were amalgamated under the name
{{ business.legalName }}
on {{ effective_date_time }}
 
diff --git a/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html index 8f5feb96c9..bc15a458de 100644 --- a/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html +++ b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html @@ -1,12 +1,12 @@
-
Amalgamating Corporation(s) Information
+
Amalgamating Businesses Information
@@ -42,8 +46,13 @@ diff --git a/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html index bc15a458de..1eab605137 100644 --- a/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html +++ b/legal-api/report-templates/template-parts/amalgamation/amalgamatingCorp.html @@ -16,7 +16,11 @@