Ejemplo n.º 1
0
    def _process_colin_filing(identifier: str, filing: Filing,
                              business: Business) -> Tuple[dict, int]:
        try:
            if not filing.colin_event_ids:
                raise KeyError

            if (epoch_filing :=
                    Filing.get_filings_by_status(business_id=business.id, status=[Filing.Status.EPOCH.value])
                ) and \
                    ListFilingResource._is_before_epoch_filing(filing.filing_json, business):
                filing.transaction_id = epoch_filing[0].transaction_id
                filing.set_processed()
                filing.save()
            else:
Ejemplo n.º 2
0
def historic_filings_exist(business_id):
    filings = Filing.get_filings_by_status(business_id,
                                           [Filing.Status.DRAFT.value])
    for possible_historic in filings:
        if possible_historic.json['filing']['header']['date'] < '2019-03-08':
            return True
    return False
Ejemplo n.º 3
0
def test_get_filings_by_status_before_go_live_date(session, test_type, days, expected, status):
    """Assert that a filing can be retrieved by status."""
    import copy
    uow = versioning_manager.unit_of_work(session)
    transaction = uow.create_transaction(session)
    business = factory_business('CP1234567')
    payment_token = '1000'
    ar = copy.deepcopy(ANNUAL_REPORT)

    go_live_date = datetime.date.fromisoformat(current_app.config.get('GO_LIVE_DATE'))
    filing_date = go_live_date + datetime.timedelta(days=days)

    filing = Filing()
    filing.filing_date = filing_date
    filing.business_id = business.id
    filing.filing_json = ar
    filing.payment_token = payment_token
    filing.transaction_id = transaction.id
    filing.payment_completion_date = datetime.datetime.utcnow()
    filing.save()

    rv = Filing.get_filings_by_status(business.id, [Filing.Status.COMPLETED.value], go_live_date)

    assert eval(expected)  # pylint: disable=eval-used; useful for parameterized tests
    if rv:
        assert rv[0].status == status
Ejemplo n.º 4
0
    def get(identifier, filing_id=None):
        """Return a JSON object with meta information about the Service."""
        business = Business.find_by_identifier(identifier)

        if not business:
            return jsonify({'message':
                            f'{identifier} not found'}), HTTPStatus.NOT_FOUND

        if filing_id:
            rv = db.session.query(Business, Filing). \
                filter(Business.id == Filing.business_id).\
                filter(Business.identifier == identifier).\
                filter(Filing.id == filing_id).\
                one_or_none()
            if not rv:
                return jsonify({'message': f'{identifier} no filings found'
                                }), HTTPStatus.NOT_FOUND

            if str(request.accept_mimetypes) == 'application/pdf':
                return legal_api.reports.get_pdf(rv[1])

            return jsonify(rv[1].json)

        # Does it make sense to get a PDF of all filings?
        if str(request.accept_mimetypes) == 'application/pdf':
            return jsonify({'message': _('Cannot return a single PDF of multiple filing submissions.')}),\
                HTTPStatus.NOT_ACCEPTABLE

        rv = []
        filings = Filing.get_filings_by_status(business.id,
                                               [Filing.Status.COMPLETED.value])
        for filing in filings:
            rv.append(filing.json)

        return jsonify(filings=rv)
Ejemplo n.º 5
0
 def _process_colin_filing(identifier: str, filing: Filing,
                           business: Business) -> Tuple[dict, int]:
     try:
         if not filing.colin_event_id:
             raise KeyError
         if not ListFilingResource._is_before_epoch_filing(
                 filing.filing_json, business):
             payload = {'filing': {'id': filing.id}}
             queue.publish_json(payload)
         else:
             epoch_filing = Filing.get_filings_by_status(
                 business_id=business.id,
                 status=[Filing.Status.EPOCH.value])
             filing.transaction_id = epoch_filing[0].transaction_id
             filing.save()
         return {'filing': {'id': filing.id}}, HTTPStatus.CREATED
     except KeyError:
         current_app.logger.error(
             'Business:%s missing filing/header/colinId, unable to post to queue',
             identifier)
         return {
             'errors': {
                 'message': 'missing filing/header/colinId'
             }
         }, HTTPStatus.BAD_REQUEST
     except Exception as err:  # pylint: disable=broad-except; final catch
         current_app.logger.error(
             'Business:%s unable to post to queue, err=%s', identifier, err)
         return {
             'errors': {
                 'message': 'unable to publish for post processing'
             }
         }, HTTPStatus.BAD_REQUEST
Ejemplo n.º 6
0
    def construct_task_list(business):
        """Return a task list object."""
        tasks = []
        order = 1
        todo_start_year = 2019  # If no filings exist in legal API db this year will be used as the start year.

        pending_filings = Filing.get_filings_by_status(business.id, [Filing.Status.DRAFT.value,
                                                                     Filing.Status.PENDING.value,
                                                                     Filing.Status.ERROR.value])
        for filing in pending_filings:
            task = {'task': filing.json, 'order': order, 'enabled': True}
            tasks.append(task)
            order += 1

        annual_report_filings = Filing.get_filings_by_type(business.id, 'annualReport')
        if annual_report_filings:
            last_filing = annual_report_filings[0].filing_json
            todo_start_year = datetime.strptime(last_filing['filing']['annualReport']['annualGeneralMeetingDate'],
                                                '%Y-%m-%d').year + 1

        if todo_start_year <= datetime.now().year:
            for todo_year in range(todo_start_year, datetime.now().year+1):
                enabled = not pending_filings and todo_year == todo_start_year
                tasks.append(TaskListResource.create_todo(business, todo_year, order, enabled))
                order += 1

        return tasks
Ejemplo n.º 7
0
    def construct_task_list(business):
        """
        Return all current pending tasks to do.

        First retrieves filings that are either drafts, or incomplete,
        then populate AR filings that have not been started for
        years that are due.

        Rules for AR filings:
            - Co-ops must file one AR per year. The next AR date must be AFTER the most recent
              AGM date. The calendar year of the filing is the first contiguous year following
              the last AGM date

            - Corporations must file one AR per year, on or after the anniversary of the founding date
        """
        tasks = []
        order = 1
        check_agm = validations.annual_report.requires_agm(business)
        # If no filings exist in legal API db this year will be used as the start year.
        todo_start_date = (datetime(
            2019, 1,
            1)).date() if check_agm else business.next_anniversary.date()

        # Retrieve filings that are either incomplete, or drafts
        pending_filings = Filing.get_filings_by_status(business.id, [
            Filing.Status.DRAFT.value, Filing.Status.PENDING.value,
            Filing.Status.ERROR.value
        ])
        # Create a todo item for each pending filing
        for filing in pending_filings:
            task = {'task': filing.json, 'order': order, 'enabled': True}
            tasks.append(task)
            order += 1

        # Retrieve all previous annual report filings. If there are existing AR filings, determine
        # the latest date of filing
        annual_report_filings = Filing.get_filings_by_type(
            business.id, 'annualReport')
        if annual_report_filings:

            if check_agm:
                last_ar_date = business.last_ar_date
                todo_start_date = (datetime(last_ar_date.year + 1, 1,
                                            1)).date()
            else:
                todo_start_date = business.next_anniversary.date()

        start_year = todo_start_date.year

        while todo_start_date <= datetime.now().date():
            enabled = not pending_filings and todo_start_date.year == start_year
            tasks.append(
                TaskListResource.create_todo(business, todo_start_date.year,
                                             order, enabled))
            todo_start_date += datedelta.YEAR
            order += 1
        return tasks
Ejemplo n.º 8
0
def history_needed(business: Business):
    """Check if there is history to load for this business."""
    if business.legal_type != Business.LegalTypes.COOP.value:
        return False
    filings = Filing.get_filings_by_status(business.id,
                                           [Filing.Status.COMPLETED.value])
    for possible_historic in filings:
        if possible_historic.json['filing']['header']['date'] < '2019-03-08':
            return False
    return True
Ejemplo n.º 9
0
 def _is_before_epoch_filing(filing_json: str, business: Business):
     if not business or not filing_json:
         return False
     epoch_filing = Filing.get_filings_by_status(business_id=business.id, status=[Filing.Status.EPOCH.value])
     if len(epoch_filing) != 1:
         current_app.logger.error('Business:%s either none or too many epoch filings', business.identifier)
         return False
     filing_date = datetime.datetime.fromisoformat(
         filing_json['filing']['header']['date']).replace(tzinfo=datetime.timezone.utc)
     return filing_date < epoch_filing[0].filing_date
Ejemplo n.º 10
0
def test_get_filings_by_status__default_order(session):
    """Assert that a filing can be retrieved.

    by status and is returned in the default order.
    default order is submission_date, and then effective_date.
    """
    # setup
    base_filing = copy.deepcopy(FILING_HEADER)
    base_filing['specialResolution'] = SPECIAL_RESOLUTION
    uow = versioning_manager.unit_of_work(session)
    business = factory_business('CP1234567')

    completion_date = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc)

    # setup - create multiple filings on the same day & time
    filing_ids = []
    file_counter = -1
    with freeze_time(completion_date):
        for i in range(0, 5):
            transaction = uow.create_transaction(session)
            payment_token = str(i)
            effective_date = f'200{i}-04-15T00:00:00+00:00'

            base_filing['filing']['header']['effectiveDate'] = effective_date
            filing = Filing()
            filing._filing_date = completion_date
            filing.business_id = business.id
            filing.filing_json = base_filing
            filing.effective_date = datetime.datetime.fromisoformat(
                effective_date)
            filing.payment_token = payment_token
            filing.transaction_id = transaction.id
            filing.payment_completion_date = completion_date
            filing.save()

            filing_ids.append(filing.id)
            file_counter += 1

    # test
    rv = Filing.get_filings_by_status(business.id,
                                      [Filing.Status.COMPLETED.value])

    # check
    assert rv
    # filings should be in newest to oldest effective date order
    for filing in rv:
        assert filing.id == filing_ids[file_counter]
        file_counter -= 1
Ejemplo n.º 11
0
    def get(identifier):
        """Return a JSON object with meta information about the Service."""
        business = Business.find_by_identifier(identifier)
        is_nr = identifier.startswith('NR')

        # Check if this is a NR
        if is_nr:
            # Fetch NR Data
            nr_response = namex.query_nr_number(identifier)
            # Validate NR data
            validation_result = namex.validate_nr(nr_response.json())

            # Return error if the NR is not consumable (invalid)
            if not validation_result['is_consumable']:
                return jsonify({
                    'message': f'{identifier} is invalid',
                    'validation': validation_result
                }), HTTPStatus.FORBIDDEN

        if not business:
            # Create Incorporate using NR to-do item
            if is_nr:
                rv = []
                rv.append(
                    TaskListResource.create_incorporate_nr_todo(
                        nr_response.json(), 1, True))
            # business does not exist and not an nr so return empty task list
            else:
                rv = []
        else:
            rv = TaskListResource.construct_task_list(business)
            if not rv and is_nr:
                paid_completed_filings = Filing.get_filings_by_status(
                    business.id,
                    [Filing.Status.PAID.value, Filing.Status.COMPLETED.value])
                # Append NR todo if there are no tasks and PAID or COMPLETED filings
                if not paid_completed_filings:
                    rv.append(
                        TaskListResource.create_incorporate_nr_todo(
                            nr_response.json(), 1, True))
            elif rv == 'pay_connection_error':
                return {
                    'message':
                    'Failed to get payment details for a filing. Please try again later.'
                }, HTTPStatus.SERVICE_UNAVAILABLE

        return jsonify(tasks=rv)
Ejemplo n.º 12
0
def test_get_filings_by_status(session):
    """Assert that a filing can be retrieved by status."""
    uow = versioning_manager.unit_of_work(session)
    transaction = uow.create_transaction(session)
    business = factory_business('CP1234567')
    payment_token = '1000'
    filing = Filing()
    filing.business_id = business.id
    filing.filing_json = ANNUAL_REPORT
    filing.payment_token = payment_token
    filing.transaction_id = transaction.id
    filing.payment_completion_date = datetime.datetime.utcnow()
    filing.save()

    rv = Filing.get_filings_by_status(business.id, [Filing.Status.COMPLETED.value])

    assert rv
    assert rv[0].status == Filing.Status.COMPLETED.value
Ejemplo n.º 13
0
    def get(identifier, filing_id=None):
        """Return a JSON object with meta information about the Service."""
        business = Business.find_by_identifier(identifier)

        if not business:
            return jsonify({'message':
                            f'{identifier} not found'}), HTTPStatus.NOT_FOUND

        if filing_id:
            rv = db.session.query(Business, Filing). \
                filter(Business.id == Filing.business_id).\
                filter(Business.identifier == identifier).\
                filter(Filing.id == filing_id).\
                one_or_none()
            if not rv:
                return jsonify({'message': f'{identifier} no filings found'
                                }), HTTPStatus.NOT_FOUND

            if str(request.accept_mimetypes) == 'application/pdf':
                return legal_api.reports.get_pdf(rv[1])

            return jsonify(rv[1].json)

        # Does it make sense to get a PDF of all filings?
        if str(request.accept_mimetypes) == 'application/pdf':
            return 'Please specify a single filing', HTTPStatus.NOT_ACCEPTABLE

        rv = []
        go_live_date = datetime.date.fromisoformat(
            current_app.config.get('GO_LIVE_DATE'))
        filings = Filing.get_filings_by_status(business.id,
                                               [Filing.Status.COMPLETED.value],
                                               go_live_date)
        for filing in filings:
            rv.append(filing.json)

        return jsonify(filings=rv)
Ejemplo n.º 14
0
    def construct_task_list(business):  # pylint: disable=too-many-locals; only 2 extra
        """
        Return all current pending tasks to do.

        First retrieves filings that are either drafts, or incomplete,
        then populate AR filings that have not been started for
        years that are due.

        Rules for AR filings:
            - Co-ops must file one AR per year. The next AR date must be AFTER the most recent
              AGM date. The calendar year of the filing is the first contiguous year following
              the last AGM date

            - Corporations must file one AR per year, on or after the anniversary of the founding date
        """
        tasks = []
        order = 1

        # Retrieve filings that are either incomplete, or drafts
        pending_filings = Filing.get_filings_by_status(business.id, [
            Filing.Status.DRAFT.value, Filing.Status.PENDING.value,
            Filing.Status.PENDING_CORRECTION.value, Filing.Status.ERROR.value
        ])
        # Create a todo item for each pending filing
        for filing in pending_filings:
            filing_json = filing.json
            if filing.payment_status_code == 'CREATED' and filing.payment_token:
                # get current pay details from pay-api
                try:
                    headers = {
                        'Authorization':
                        f'Bearer {jwt.get_token_auth_header()}',
                        'Content-Type': 'application/json'
                    }
                    pay_response = requests.get(
                        url=
                        f'{current_app.config.get("PAYMENT_SVC_URL")}/{filing.payment_token}',
                        headers=headers)
                    pay_details = {
                        'isPaymentActionRequired':
                        pay_response.json().get('isPaymentActionRequired',
                                                False),
                        'paymentMethod':
                        pay_response.json().get('paymentMethod', '')
                    }
                    filing_json['filing']['header'].update(pay_details)

                except (exceptions.ConnectionError, exceptions.Timeout) as err:
                    current_app.logger.error(
                        f'Payment connection failure for {business.identifier} task list. ',
                        err)
                    return 'pay_connection_error'

            task = {'task': filing_json, 'order': order, 'enabled': True}
            tasks.append(task)
            order += 1

        # If this is the first calendar year since incorporation, there is no previous ar year.
        next_ar_year = (business.last_ar_year if business.last_ar_year else
                        business.founding_date.year) + 1
        start_date = (business.last_ar_date if business.last_ar_date else
                      business.founding_date).date()

        # Checking for pending ar
        annual_report_filings = Filing.get_filings_by_type(
            business.id, 'annualReport')
        if annual_report_filings:
            # Consider each filing as each year and add to find next ar year
            next_ar_year += len(annual_report_filings)
            start_date = datetime(next_ar_year, 1, 1).date()

        ar_min_date, ar_max_date = validations.annual_report.get_ar_dates(
            business, start_date, next_ar_year)

        start_year = next_ar_year
        while ar_min_date <= datetime.utcnow().date():
            # while next_ar_year <= datetime.utcnow().date():
            enabled = not pending_filings and ar_min_date.year == start_year
            tasks.append(
                TaskListResource.create_todo(business, next_ar_year,
                                             ar_min_date, ar_max_date, order,
                                             enabled))

            # Include all ar's to todo from last ar filing
            next_ar_year += 1
            start_date = datetime(next_ar_year, 1, 1).date()
            ar_min_date, ar_max_date = validations.annual_report.get_ar_dates(
                business, start_date, next_ar_year)
            order += 1
        return tasks
Ejemplo n.º 15
0
    def construct_task_list(business):
        """
        Return all current pending tasks to do.

        First retrieves filings that are either drafts, or incomplete,
        then populate AR filings that have not been started for
        years that are due.

        Rules for AR filings:
            - Co-ops must file one AR per year. The next AR date must be AFTER the most recent
              AGM date. The calendar year of the filing is the first contiguous year following
              the last AGM date

            - Corporations must file one AR per year, on or after the anniversary of the founding date
        """
        tasks = []
        order = 1
        check_agm = validations.annual_report.requires_agm(business)

        # If no filings exist in legal API db (set after this line), use the business' next anniversary date
        todo_start_date = business.next_anniversary.date()

        # Retrieve filings that are either incomplete, or drafts
        pending_filings = Filing.get_filings_by_status(business.id, [
            Filing.Status.DRAFT.value, Filing.Status.PENDING.value,
            Filing.Status.PENDING_CORRECTION.value, Filing.Status.ERROR.value
        ])
        # Create a todo item for each pending filing
        for filing in pending_filings:
            task = {'task': filing.json, 'order': order, 'enabled': True}
            tasks.append(task)
            order += 1

        last_ar_date = business.last_ar_date
        if check_agm:
            # If this is a CO-OP, set the start date to the first day of the year, since an AR filing
            # is available as of Jan/01
            if last_ar_date:
                todo_start_date = (datetime(last_ar_date.year + 1, 1,
                                            1)).date()
            else:
                # If this is the first calendar year since incorporation, there is no
                # previous ar date. Use the next anniversary year.
                todo_start_date = (datetime(todo_start_date.year, 1, 1)).date()

        # Retrieve all previous annual report filings. If there are existing AR filings, determine
        # the latest date of filing
        annual_report_filings = Filing.get_filings_by_type(
            business.id, 'annualReport')
        if annual_report_filings:
            # get last AR date from annualReportDate; if not present in json, try annualGeneralMeetingDate and
            # finally filing date
            last_ar_date = \
                annual_report_filings[0].filing_json['filing']['annualReport'].get('annualReportDate', None)
            if not last_ar_date:
                last_ar_date = annual_report_filings[0].filing_json['filing']['annualReport']\
                    .get('annualGeneralMeetingDate', None)
            if not last_ar_date:
                last_ar_date = annual_report_filings[0].filing_date
            last_ar_date = datetime.fromisoformat(last_ar_date)
            if check_agm:
                todo_start_date = (datetime(last_ar_date.year + 1, 1,
                                            1)).date()
            else:
                todo_start_date = (last_ar_date + datedelta.YEAR).date()

        start_year = todo_start_date.year

        while todo_start_date <= datetime.now().date():
            enabled = not pending_filings and todo_start_date.year == start_year
            tasks.append(
                TaskListResource.create_todo(business, todo_start_date.year,
                                             order, enabled))
            todo_start_date += datedelta.YEAR
            order += 1
        return tasks
Ejemplo n.º 16
0
    def get(identifier, filing_id=None):  # pylint: disable=too-many-return-statements;
        # fix this while refactoring this whole module
        """Return a JSON object with meta information about the Service."""
        if identifier.startswith('T'):
            q = db.session.query(Filing). \
                filter(Filing.temp_reg == identifier)

            if filing_id:
                q = q.filter(Filing.id == filing_id)

            rv = q.one_or_none()

            if not rv:
                return jsonify({'message': f'{identifier} no filings found'
                                }), HTTPStatus.NOT_FOUND
            if str(request.accept_mimetypes
                   ) == 'application/pdf' and filing_id:
                if rv.filing_type == 'incorporationApplication':
                    return legal_api.reports.get_pdf(rv, None)
            filing_json = rv.json
            filing_json['filing']['documents'] = document_meta.get_documents(
                filing_json)
            return jsonify(filing_json)

        business = Business.find_by_identifier(identifier)

        if not business:
            return jsonify(filings=[]), HTTPStatus.NOT_FOUND

        if filing_id:
            rv = db.session.query(Business, Filing). \
                filter(Business.id == Filing.business_id).\
                filter(Business.identifier == identifier).\
                filter(Filing.id == filing_id).\
                one_or_none()
            if not rv:
                return jsonify({'message': f'{identifier} no filings found'
                                }), HTTPStatus.NOT_FOUND

            if str(request.accept_mimetypes) == 'application/pdf':
                report_type = request.args.get('type', None)
                if rv[1].filing_type == 'incorporationApplication':
                    ListFilingResource._populate_business_info_to_filing(
                        rv[1], business)
                return legal_api.reports.get_pdf(rv[1], report_type)
            return jsonify(rv[1].json)

        # Does it make sense to get a PDF of all filings?
        if str(request.accept_mimetypes) == 'application/pdf':
            return jsonify({'message': _('Cannot return a single PDF of multiple filing submissions.')}),\
                HTTPStatus.NOT_ACCEPTABLE

        rv = []
        filings = Filing.get_filings_by_status(
            business.id,
            [Filing.Status.COMPLETED.value, Filing.Status.PAID.value])
        for filing in filings:
            filing_json = filing.json
            filing_json['filing']['documents'] = document_meta.get_documents(
                filing_json)
            rv.append(filing_json)

        return jsonify(filings=rv)