Example #1
0
def consume_nr(
        business: Business,
        filing: Filing,
        nr_num_path='/filing/incorporationApplication/nameRequest/nrNumber'):
    """Update the nr to a consumed state."""
    try:
        # skip this if none (nrNumber will not be available for numbered company)
        if nr_num := get_str(filing.filing_json, nr_num_path):

            namex_svc_url = current_app.config.get('NAMEX_API')
            token = AccountService.get_bearer_token()

            # Create an entity record
            data = json.dumps({'consume': {'corpNum': business.identifier}})
            rv = requests.patch(
                url=''.join([namex_svc_url, nr_num]),
                headers={
                    **AccountService.CONTENT_TYPE_JSON, 'Authorization':
                    AccountService.BEARER + token
                },
                data=data,
                timeout=AccountService.timeout)
            if not rv.status_code == HTTPStatus.OK:
                raise QueueException

            # remove the NR from the account
            if filing.temp_reg and (bootstrap :=
                                    RegistrationBootstrap.find_by_identifier(
                                        filing.temp_reg)):
                AccountService.delete_affiliation(bootstrap.account, nr_num)
Example #2
0
def has_new_nr_for_alteration(business: Business, filing: dict):
    """Return whether a alteration filing has new NR."""
    nr_number = get_str(filing, '/filing/alteration/nameRequest/nrNumber')
    legal_name = get_str(filing, '/filing/alteration/nameRequest/legalName')
    if nr_number and legal_name:
        # legal api validates legal name in filing json, confirm both are different
        return legal_name.lower() != business.legal_name.lower()
    return False
Example #3
0
def consume_nr(
        business: Business,
        filing: Filing,
        nr_num_path='/filing/incorporationApplication/nameRequest/nrNumber'):
    """Update the nr to a consumed state."""
    try:
        nr_num = get_str(filing.filing_json, nr_num_path)
        # skip this if none (nrNumber will not be available for numbered company)
        if nr_num:
            bootstrap = RegistrationBootstrap.find_by_identifier(
                filing.temp_reg)
            namex_svc_url = current_app.config.get('NAMEX_API')
            token = AccountService.get_bearer_token()

            # Create an entity record
            data = json.dumps({'consume': {'corpNum': business.identifier}})
            rv = requests.patch(
                url=''.join([namex_svc_url, nr_num]),
                headers={
                    **AccountService.CONTENT_TYPE_JSON, 'Authorization':
                    AccountService.BEARER + token
                },
                data=data,
                timeout=AccountService.timeout)
            if not rv.status_code == HTTPStatus.OK:
                raise QueueException

            # remove the NR from the account
            AccountService.delete_affiliation(bootstrap.account, nr_num)
    except KeyError:
        pass  # return
    except Exception:  # pylint: disable=broad-except; note out any exception, but don't fail the call
        sentry_sdk.capture_message(
            f'Queue Error: Consume NR error for filing:{filing.id}',
            level='error')
Example #4
0
def test_get_str(f, p):
    """Assert the get_date extracts the date from the JSON file."""
    d = get_str(f, p)
    if not d:
        assert True
    else:
        assert isinstance(d, str)
Example #5
0
def share_structure_validation(filing):
    """Validate share structure."""
    share_structure_path: Final = '/filing/alteration/shareStructure'
    if get_str(filing, share_structure_path):
        err = validate_share_structure(filing, Filing.FilingTypes.ALTERATION.value)
        if err:
            return err
    return []
Example #6
0
def court_order_validation(filing):
    """Validate court order."""
    court_order_path: Final = '/filing/alteration/courtOrder'
    if get_str(filing, court_order_path):
        err = validate_court_order(court_order_path, filing['filing']['alteration']['courtOrder'])
        if err:
            return err
    return []
Example #7
0
def type_change_validation(filing):
    """Validate type change."""
    msg = []
    legal_type_path: Final = '/filing/alteration/business/legalType'
    # you must alter to a bc benefit company
    if get_str(filing, legal_type_path) != Business.LegalTypes.BCOMP.value:
        msg.append({'error': babel('Your business type has not been updated to a BC Benefit Company.'),
                    'path': legal_type_path})
        return msg
    return []
Example #8
0
    def _create_invoice(business: Business,
                        filing: Filing,
                        filing_types: list,
                        user_jwt: JwtManager) \
            -> Tuple[int, dict, int]:
        """Create the invoice for the filing submission.

        Returns: {
            int: the paymentToken (id), or None
            dict: a dict of errors, or None
            int: the HTTPStatus error code, or None
        }
        """
        payment_svc_url = current_app.config.get('PAYMENT_SVC_URL')
        mailing_address = business.mailing_address.one_or_none()

        payload = {
            'paymentInfo': {'methodOfPayment': 'CC'},
            'businessInfo': {
                'businessIdentifier': f'{business.identifier}',
                'corpType': f'{business.identifier[:-7]}',
                'businessName': f'{business.legal_name}',
                'contactInfo': {'city': mailing_address.city,
                                'postalCode': mailing_address.postal_code,
                                'province': mailing_address.region,
                                'addressLine1': mailing_address.street,
                                'country': mailing_address.country}
            },
            'filingInfo': {
                'filingTypes': filing_types
            }
        }

        if user_jwt.validate_roles([STAFF_ROLE]):
            routing_slip_number = get_str(filing.filing_json, 'filing/header/routingSlipNumber')
            if routing_slip_number:
                payload['accountInfo'] = {'routingSlip': routing_slip_number}
        try:
            token = user_jwt.get_token_auth_header()
            headers = {'Authorization': 'Bearer ' + token}
            rv = requests.post(url=payment_svc_url,
                               json=payload,
                               headers=headers,
                               timeout=20.0)
        except (exceptions.ConnectionError, exceptions.Timeout) as err:
            current_app.logger.error(f'Payment connection failure for {business.identifier}: filing:{filing.id}', err)
            return {'message': 'unable to create invoice for payment.'}, HTTPStatus.PAYMENT_REQUIRED

        if rv.status_code == HTTPStatus.OK or rv.status_code == HTTPStatus.CREATED:
            pid = rv.json().get('id')
            filing.payment_token = pid
            filing.save()
            return None, None
        return {'message': 'unable to create invoice for payment.'}, HTTPStatus.PAYMENT_REQUIRED
Example #9
0
def company_name_validation(filing):
    """Validate share structure."""
    msg = []
    nr_path: Final = '/filing/alteration/nameRequest/nrNumber'
    if nr_number := get_str(filing, nr_path):
        # ensure NR is approved or conditionally approved
        nr_response = namex.query_nr_number(nr_number)
        validation_result = namex.validate_nr(nr_response)

        if not nr_response['requestTypeCd'] in ('CCR', 'CCP', 'BEC'):
            msg.append({
                'error':
                babel(
                    'Alteration only available for Change of Name Name requests.'
                ),
                'path':
                nr_path
            })

        if not validation_result['is_approved']:
            msg.append({
                'error':
                babel('Alteration of Name Request is not approved.'),
                'path':
                nr_path
            })

        # ensure NR request has the same legal name
        legal_name_path: Final = '/filing/alteration/nameRequest/legalName'
        legal_name = get_str(filing, legal_name_path)
        nr_name = namex.get_approved_name(nr_response)
        if nr_name != legal_name:
            msg.append({
                'error':
                babel(
                    'Alteration of Name Request has a different legal name.'),
                'path':
                legal_name_path
            })
Example #10
0
def validate(business: Business, filing_json: Dict) -> Error:  # pylint: disable=too-many-branches
    """Validate the filing JSON."""
    err = validate_against_schema(filing_json)
    if err:
        return err

    err = None

    # check if this is a correction - if yes, ignore all other filing types in the filing since they will be validated
    # differently in a future version of corrections
    if 'correction' in filing_json['filing'].keys():
        err = correction_validate(business, filing_json)
        if err:
            return err

        # For now the correction validators will get called here, these might be the same rules
        # so these 2 sections could get collapsed
        for k in filing_json['filing'].keys():
            # Check if the JSON key exists in the FILINGS reference Dictionary
            if Filing.FILINGS.get(k, None):

                if k == Filing.FILINGS['changeOfAddress'].get('name'):
                    err = coa_validate(business, filing_json)

                elif k == Filing.FILINGS['incorporationApplication'].get(
                        'name'):
                    err = validate_correction_ia(filing_json)

        if err:
            return err
    elif 'dissolution' in filing_json['filing'].keys() \
            and (dissolution_type := filing_json['filing']['dissolution'].get('dissolutionType', None)) \
            and dissolution_type == 'voluntary':
        err = dissolution_validate(business, filing_json)
        if err:
            return err

        legal_type = get_str(filing_json, '/filing/business/legalType')
        if legal_type == Business.LegalTypes.COOP.value:
            if 'specialResolution' in filing_json['filing'].keys():
                err = special_resolution_validate(business, filing_json)
            else:
                err = Error(
                    HTTPStatus.BAD_REQUEST,
                    [{
                        'error': babel('Special Resolution is required.'),
                        'path': '/filing/specialResolution'
                    }])
        if err:
            return err
Example #11
0
        # ensure NR request has the same legal name
        legal_name_path: Final = '/filing/alteration/nameRequest/legalName'
        legal_name = get_str(filing, legal_name_path)
        nr_name = namex.get_approved_name(nr_response)
        if nr_name != legal_name:
            msg.append({
                'error':
                babel(
                    'Alteration of Name Request has a different legal name.'),
                'path':
                legal_name_path
            })
    else:
        # ensure legalType is valid
        legal_type_path: Final = '/filing/business/legalType'
        if get_str(filing, legal_type_path) not in ('ULC', 'BC', 'BEN'):
            msg.append({
                'error':
                babel('Alteration not valid for selected Legal Type.'),
                'path':
                legal_type_path
            })

        # ensure company is named if being altered to numbered
        legal_name_path: Final = '/filing/business/legalName'
        if not get_str(filing, legal_name_path):
            msg.append({
                'error':
                babel(
                    'Alteration to Numbered Company can only be done for a Named Company.'
                ),
Example #12
0
    def _create_invoice(business: Business,  # pylint: disable=too-many-locals
                        filing: Filing,
                        filing_types: list,
                        user_jwt: JwtManager,
                        payment_account_id: str = None) \
            -> Tuple[int, dict, int]:
        """Create the invoice for the filing submission.

        Returns: {
            int: the paymentToken (id), or None
            dict: a dict of errors, or None
            int: the HTTPStatus error code, or None
        }
        """
        payment_svc_url = current_app.config.get('PAYMENT_SVC_URL')

        if filing.filing_type == Filing.FILINGS[
                'incorporationApplication'].get('name'):
            mailing_address = Address.create_address(
                filing.json['filing']['incorporationApplication']['offices']
                ['registeredOffice']['mailingAddress'])
            corp_type = filing.json['filing']['business'].get(
                'legalType', Business.LegalTypes.BCOMP.value)

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

        else:
            mailing_address = business.mailing_address.one_or_none()
            corp_type = business.legal_type if business.legal_type else \
                filing.json['filing']['business'].get('legalType')

        payload = {
            'businessInfo': {
                'businessIdentifier': f'{business.identifier}',
                'corpType': f'{corp_type}',
                'businessName': f'{business.legal_name}',
                'contactInfo': {
                    'city': mailing_address.city,
                    'postalCode': mailing_address.postal_code,
                    'province': mailing_address.region,
                    'addressLine1': mailing_address.street,
                    'country': mailing_address.country
                }
            },
            'filingInfo': {
                'filingTypes': filing_types
            }
        }

        folio_number = filing.json['filing']['header'].get('folioNumber', None)
        if folio_number:
            payload['filingInfo']['folioNumber'] = folio_number

        if user_jwt.validate_roles([STAFF_ROLE]) or \
                user_jwt.validate_roles([SYSTEM_ROLE]):
            account_info = {}
            routing_slip_number = get_str(filing.filing_json,
                                          'filing/header/routingSlipNumber')
            if routing_slip_number:
                account_info['routingSlip'] = routing_slip_number
            bcol_account_number = get_str(filing.filing_json,
                                          'filing/header/bcolAccountNumber')
            if bcol_account_number:
                account_info['bcolAccountNumber'] = bcol_account_number
            dat_number = get_str(filing.filing_json, 'filing/header/datNumber')
            if dat_number:
                account_info['datNumber'] = dat_number

            if account_info:
                payload['accountInfo'] = account_info
        try:
            token = user_jwt.get_token_auth_header()
            headers = {
                'Authorization': 'Bearer ' + token,
                'Content-Type': 'application/json'
            }
            rv = requests.post(url=payment_svc_url,
                               json=payload,
                               headers=headers,
                               timeout=20.0)
        except (exceptions.ConnectionError, exceptions.Timeout) as err:
            current_app.logger.error(
                f'Payment connection failure for {business.identifier}: filing:{filing.id}',
                err)
            return {
                'message': 'unable to create invoice for payment.'
            }, HTTPStatus.PAYMENT_REQUIRED

        if rv.status_code in (HTTPStatus.OK, HTTPStatus.CREATED):
            pid = rv.json().get('id')
            filing.payment_token = pid
            filing.payment_status_code = rv.json().get('statusCode', '')
            filing.payment_account = payment_account_id
            filing.save()
            return {
                'isPaymentActionRequired':
                rv.json().get('isPaymentActionRequired', False)
            }, HTTPStatus.CREATED

        if rv.status_code == HTTPStatus.BAD_REQUEST:
            # Set payment error type used to retrieve error messages from pay-api
            error_type = rv.json().get('type')
            filing.payment_status_code = error_type
            filing.save()

            return {
                'payment_error_type': error_type,
                'message': rv.json().get('detail')
            }, HTTPStatus.PAYMENT_REQUIRED

        return {
            'message': 'unable to create invoice for payment.'
        }, HTTPStatus.PAYMENT_REQUIRED
Example #13
0
            msg.append({'error': babel('Alteration only available for Change of Name Name requests.'), 'path': nr_path})

        if not validation_result['is_consumable']:
            msg.append({'error': babel('Alteration of Name Request is not approved.'), 'path': nr_path})

        # ensure NR request has the same legal name
        legal_name_path: Final = '/filing/alteration/nameRequest/legalName'
        legal_name = get_str(filing, legal_name_path)
        nr_name = namex.get_approved_name(nr_response)
        if nr_name != legal_name:
            msg.append({'error': babel('Alteration of Name Request has a different legal name.'),
                        'path': legal_name_path})
    else:
        # ensure legalType is valid
        legal_type_path: Final = '/filing/business/legalType'
        if get_str(filing, legal_type_path) not in \
                (Business.LegalTypes.BC_ULC_COMPANY.value,
                 Business.LegalTypes.COMP.value,
                 Business.LegalTypes.BCOMP.value):
            msg.append({'error': babel('Alteration not valid for selected Legal Type.'), 'path': legal_type_path})

        # ensure company is named if being altered to numbered
        legal_name_path: Final = '/filing/business/legalName'
        if not get_str(filing, legal_name_path):
            msg.append({'error': babel('Alteration to Numbered Company can only be done for a Named Company.'),
                        'path': legal_name_path})

    return msg


def type_change_validation(filing):