Beispiel #1
0
def validate_resolution_date(business: Business,
                             filing_json: Dict) -> Optional[list]:
    """Validate resolution date."""
    msg = []
    resolution_date_path = '/filing/specialResolution/resolutionDate'
    resolution_date = get_date(filing_json, resolution_date_path)

    if not resolution_date:
        msg.append({
            'error': _('Resolution date is required.'),
            'path': resolution_date_path
        })
        return msg

    if resolution_date < business.founding_date.date():
        msg.append({
            'error':
            _('Resolution date cannot be earlier than the incorporation date.'
              ),
            'path':
            resolution_date_path
        })
        return msg

    if resolution_date > datetime.utcnow().date():
        msg.append({
            'error': _('Resolution date cannot be in the future.'),
            'path': resolution_date_path
        })
        return msg

    return msg
Beispiel #2
0
def validate_signing_date(filing_json: Dict) -> Optional[list]:
    """Validate signing date."""
    msg = []
    signing_date_path = '/filing/specialResolution/signingDate'
    signing_date = get_date(filing_json, signing_date_path)
    resolution_date_path = '/filing/specialResolution/resolutionDate'
    resolution_date = get_date(filing_json, resolution_date_path)

    if not signing_date:
        msg.append({
            'error': _('Signing date is required.'),
            'path': signing_date_path
        })
        return msg

    if signing_date > datetime.utcnow().date():
        msg.append({
            'error': _('Signing date cannot be in the future.'),
            'path': signing_date_path
        })
        return msg

    if not resolution_date:
        return msg

    if signing_date < resolution_date:
        msg.append({
            'error':
            _('Signing date cannot be before the resolution date.'),
            'path':
            signing_date_path
        })
        return msg

    return msg
Beispiel #3
0
def test_diff_of_stored_completed_filings(session):
    """Assert that the filing diff works correctly."""
    identifier = 'CP1234567'
    business = factory_business(identifier,
                                founding_date=(datetime.utcnow() -
                                               datedelta.YEAR))
    factory_business_mailing_address(business)
    json1 = copy.deepcopy(MINIMAL_FILING_JSON)
    original_filing = factory_completed_filing(business, json1)

    json2 = copy.deepcopy(CORRECTION_FILING_JSON)
    json2['filing']['correction']['correctedFilingId'] = str(
        original_filing.id)
    correction_filing = factory_completed_filing(business, json2)

    filing = Filing.find_by_id(correction_filing.id)
    filing_json = filing.json

    assert filing_json
    assert filing_json['filing']['correction']['diff'] == [{
        'newValue':
        'Be it resolved, and now it is.',
        'oldValue':
        'Be it resolved, that it is resolved to be resolved.',
        'path':
        RESOLUTION_PATH
    }]
Beispiel #4
0
def test_conversion_process_with_nr(app, session):
    """Assert that the incorporation object is correctly populated to model objects."""
    # setup
    filing = copy.deepcopy(CONVERSION_FILING_TEMPLATE)
    identifier = 'BC1234567'
    nr_num = 'NR 1234567'
    filing['filing']['business']['identifier'] = identifier
    filing['filing']['conversion']['nameRequest']['nrNumber'] = nr_num
    filing['filing']['conversion']['nameRequest']['legalName'] = 'Test'
    create_filing('123', filing)

    effective_date = datetime.utcnow()
    filing_rec = Filing(effective_date=effective_date, filing_json=filing)
    filing_meta = FilingMeta(application_date=effective_date)

    # test
    business, filing_rec = conversion.process(None, filing, filing_rec,
                                              filing_meta)

    # Assertions
    assert business.identifier == identifier
    assert business.founding_date == effective_date
    assert business.legal_type == filing['filing']['conversion'][
        'nameRequest']['legalType']
    assert business.legal_name == filing['filing']['conversion'][
        'nameRequest']['legalName']
    assert len(business.share_classes.all()) == 2
    assert len(business.offices.all()
               ) == 2  # One office is created in create_business method.
def validate_incorporation_effective_date(incorporation_json) -> Error:
    """Return an error or warning message based on the effective date validation rules.

    Rules:
        - The effective date must be the correct format.
        - The effective date must be a minimum of 2 minutes in the future.
        - The effective date must be a maximum of 10 days in the future.
    """
    # Setup
    msg = []
    now = dt.utcnow()
    now_plus_2_minutes = now + timedelta(minutes=2)
    now_plus_10_days = now + timedelta(days=10)

    try:
        filing_effective_date = incorporation_json['filing']['header']['effectiveDate']
    except KeyError:
        return msg

    try:
        effective_date = dt.fromisoformat(filing_effective_date)
    except ValueError:
        msg.append({'error': babel('%s is an invalid ISO format for effective_date.') % filing_effective_date})
        return msg

    if effective_date < now_plus_2_minutes:
        msg.append({'error': babel('Invalid Datetime, effective date must be a minimum of 2 minutes ahead.')})

    if effective_date > now_plus_10_days:
        msg.append({'error': babel('Invalid Datetime, effective date must be a maximum of 10 days ahead.')})

    if msg:
        return msg

    return None
Beispiel #6
0
def validate_ar_year(*, business: Business, current_annual_report: Dict) -> Error:
    """Validate that the annual report year is valid."""
    ar_date = get_date(current_annual_report,
                       'filing/annualReport/annualReportDate')
    if not ar_date:
        return Error(HTTPStatus.BAD_REQUEST,
                     [{'error': _('Annual Report Date must be a valid date.'),
                       'path': 'filing/annualReport/annualReportDate'}])

    # The AR Date cannot be in the future (eg. before now() )
    if ar_date > datetime.utcnow().date():
        return Error(HTTPStatus.BAD_REQUEST,
                     [{'error': _('Annual Report Date cannot be in the future.'),
                       'path': 'filing/annualReport/annualReportDate'}])

    # The AR Date cannot be before the last AR Filed
    next_ar_year = (business.last_ar_year if business.last_ar_year else business.founding_date.year) + 1
    ar_min_date, ar_max_date = business.get_ar_dates(next_ar_year)

    if ar_date < ar_min_date:
        return Error(HTTPStatus.BAD_REQUEST,
                     [{'error': _('Annual Report Date cannot be before a previous Annual Report or the Founding Date.'),
                       'path': 'filing/annualReport/annualReportDate'}])

    # AR Date must be the next contiguous year, from either the last AR or foundingDate
    if ar_date > ar_max_date:
        return Error(HTTPStatus.BAD_REQUEST,
                     [{'error': _('Annual Report Date must be the next Annual Report in contiguous order.'),
                       'path': 'filing/annualReport/annualReportDate'}])

    return None
Beispiel #7
0
def test_conversion_coop_from_colin(app, session):
    """Assert that an existing coop incorporation is loaded corrrectly."""
    # setup
    identifier = 'CP0000001'
    colind_id = 1
    filing = copy.deepcopy(CONVERSION_FILING_TEMPLATE)

    # Change the template to be a CP == Cooperative
    filing['filing']['business']['legalType'] = 'CP'
    filing['filing']['business']['identifier'] = identifier
    filing['filing']['conversion']['nameRequest']['legalType'] = 'CP'
    filing['filing']['conversion'].pop('shareStructure')
    effective_date = datetime.utcnow()
    # Create the Filing obeject in the DB
    filing_rec = Filing(effective_date=effective_date,
                        filing_json=filing)
    colin_event = ColinEventId()
    colin_event.colin_event_id=colind_id
    filing_rec.colin_event_ids.append(colin_event)
    # Override the state setting mechanism
    filing_rec.skip_status_listener = True
    filing_rec._status = 'PENDING'
    filing_rec.save()

    # test
    business, filing_rec = conversion.process(None, filing, filing_rec)

    # Assertions
    assert business.identifier == identifier
    assert business.founding_date.replace(tzinfo=None) == effective_date.replace(tzinfo=None)
    assert business.legal_type == filing['filing']['conversion']['nameRequest']['legalType']
    assert business.legal_name == business.identifier[2:] + ' B.C. LTD.'
    assert len(business.offices.all()) == 2  # One office is created in create_business method.
Beispiel #8
0
 def good_standing(self):
     """Return true if in good standing, otherwise false."""
     # 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
     return last_ar_date + datedelta.datedelta(years=1, months=2,
                                               days=1) > datetime.utcnow()
Beispiel #9
0
def test_simple_ledger_search(session):
    """Assert that the ledger returns values for all the expected keys."""
    # setup
    identifier = 'BC1234567'
    founding_date = datetime.utcnow() - datedelta.datedelta(
        months=len(Filing.FILINGS.keys()))
    business = factory_business(identifier=identifier,
                                founding_date=founding_date,
                                last_ar_date=None,
                                entity_type=Business.LegalTypes.BCOMP.value)
    num_of_files = load_ledger(business, founding_date)

    # test
    ledger = CoreFiling.ledger(business.id)

    # Did we get the full set
    assert len(ledger) == num_of_files

    # Fully examine 1 filing - alteration
    alteration = next((f for f in ledger if f.get('name') == 'alteration'),
                      None)

    assert alteration
    assert 15 == len(alteration.keys())
    assert 'availableOnPaperOnly' in alteration
    assert 'effectiveDate' in alteration
    assert 'filingId' in alteration
    assert 'name' in alteration
    assert 'paymentStatusCode' in alteration
    assert 'status' in alteration
    assert 'submittedDate' in alteration
    assert 'submitter' in alteration
def validate_effective_date(business: Business, cod: Dict) -> List:
    """Return an error or warning message based on the effective date validation rules.

    Rules:
        - The effective date of change cannot be in the future.
        - The effective date cannot be a date prior to their Incorporation Date
        - The effective date of change cannot be a date that is farther in the past
            as a previous COD filing (Standalone or AR).
        - The effective date can be the same effective date as another COD filing
            (standalone OR AR). If this is the case:
        - COD filing that was filed most recently as the most current director information.
    """
    try:
        filing_effective_date = cod['filing']['header']['effectiveDate']
    except KeyError:
        try:
            # we'll assume the filing is at 0 hours UTC
            filing_effective_date = cod['filing']['header'][
                'date'] + 'T00:00:00+00:00'
        except KeyError:
            return {
                'error': babel('No effective_date or filing date provided.')
            }

    try:
        effective_date = datetime.fromisoformat(filing_effective_date)
    except ValueError:
        return {
            'error':
            babel('Invalid ISO format for effective_date or filing date.')
        }

    msg = []

    # The effective date of change cannot be in the future
    if effective_date > datetime.utcnow():
        msg.append(
            {'error': babel('Filing cannot have a future effective date.')})

    # The effective date cannot be a date prior to their Incorporation Date
    if effective_date < business.founding_date:
        msg.append({
            'error':
            babel('Filing cannot be before a businesses founding date.')
        })

    last_cod_filing = Filing.get_most_recent_legal_filing(
        business.id, Filing.FILINGS['changeOfDirectors']['name'])
    if last_cod_filing:
        if effective_date < last_cod_filing.effective_date:
            msg.append({
                'error':
                babel(
                    "Filing's effective date cannot be before another Change of Director filing."
                )
            })

    return msg
Beispiel #11
0
    def get_ar_dates(self, next_ar_year):
        """Get ar min and max date for the specific year."""
        ar_min_date = datetime(next_ar_year, 1, 1).date()
        ar_max_date = datetime(next_ar_year, 12, 31).date()

        if self.legal_type == self.LegalTypes.COOP.value:
            # This could extend by moving it into a table with start and end date against each year when extension
            # is required. We need more discussion to understand different scenario's which can come across in future.
            if next_ar_year == 2020:
                # For year 2020, set the max date as October 31th next year (COVID extension).
                ar_max_date = datetime(next_ar_year + 1, 10, 31).date()
            else:
                # If this is a CO-OP, set the max date as April 30th next year.
                ar_max_date = datetime(next_ar_year + 1, 4, 30).date()
        elif self.legal_type == self.LegalTypes.BCOMP.value:
            # For BCOMP min date is next anniversary date.
            ar_min_date = datetime(next_ar_year, self.founding_date.month,
                                   self.founding_date.day).date()
            ar_max_date = ar_min_date + datedelta.datedelta(days=60)

        if ar_max_date > datetime.utcnow().date():
            ar_max_date = datetime.utcnow().date()

        return ar_min_date, ar_max_date
def validate_effective_date(business: Business, cod: Dict) -> List:
    """Return an error or warning message based on the effective date validation rules.

    Rules: (text from the BA rules document)
        - The effective date of change cannot be in the future.
        - The effective date cannot be a date prior to their Incorporation Date.
        - The effective date of change cannot be a date that is farther in the past
            than a previous COD filing (standalone or AR).
        - The effective date can be the same effective date as another COD filing
            (standalone or AR). If this is the case:
        - COD filing that was filed most recently is the most current director information.
    """
    msg = []

    # get effective datetime string from filing
    try:
        effective_datetime_str = cod['filing']['header']['effectiveDate']
    except KeyError:
        return {'error': babel('No effective date provided.')}

    # convert string to datetime
    try:
        effective_datetime_utc = datetime.fromisoformat(effective_datetime_str)
    except ValueError:
        return {'error': babel('Invalid ISO format for effective date.')}

    # check if effective datetime is in the future
    if effective_datetime_utc > datetime.utcnow():
        msg.append({'error': babel('Filing cannot have a future effective date.')})

    # convert to legislation timezone and then get date only
    effective_date_leg = LegislationDatetime.as_legislation_timezone(effective_datetime_utc).date()

    # check if effective date is before their incorporation date
    founding_date_leg = LegislationDatetime.as_legislation_timezone(business.founding_date).date()
    if effective_date_leg < founding_date_leg:
        msg.append({'error': babel('Effective date cannot be before businesses founding date.')})

    # check if effective date is before their most recent COD or AR date
    last_cod_filing = Filing.get_most_recent_legal_filing(business.id,
                                                          Filing.FILINGS['changeOfDirectors']['name'])
    if last_cod_filing:
        last_cod_date_leg = LegislationDatetime.as_legislation_timezone(last_cod_filing.effective_date).date()
        if effective_date_leg < last_cod_date_leg:
            msg.append({'error': babel('Effective date cannot be before another Change of Director filing.')})

    return msg
Beispiel #13
0
async def publish_event(business: Business, filing: Filing):
    """Publish the filing message onto the NATS filing subject."""
    try:
        payload = {
            'specversion':
            '1.x-wip',
            'type':
            'bc.registry.business.' + filing.filing_type,
            'source':
            ''.join([
                APP_CONFIG.LEGAL_API_URL, '/business/', business.identifier,
                '/filing/',
                str(filing.id)
            ]),
            'id':
            str(uuid.uuid4()),
            'time':
            datetime.utcnow().isoformat(),
            'datacontenttype':
            'application/json',
            'identifier':
            business.identifier,
            'data': {
                'filing': {
                    'header': {
                        'filingId': filing.id,
                        'effectiveDate': filing.effective_date.isoformat()
                    },
                    'business': {
                        'identifier': business.identifier
                    },
                    'legalFilings': get_filing_types(filing.filing_json)
                }
            }
        }
        if filing.temp_reg:
            payload['tempidentifier'] = filing.temp_reg
        subject = APP_CONFIG.ENTITY_EVENT_PUBLISH_OPTIONS['subject']
        await qsm.service.publish(subject, payload)
    except Exception as err:  # pylint: disable=broad-except; we don't want to fail out the filing, so ignore all.
        capture_message('Queue Publish Event Error: filing.id=' +
                        str(filing.id) + str(err),
                        level='error')
        logger.error('Queue Publish Event Error: filing.id=%s',
                     filing.id,
                     exc_info=True)
Beispiel #14
0
def test_conversion_bc_company_from_colin(app, session, legal_type):
    """Assert that an existing bc company(LTD, ULC, CCC) incorporation is loaded corrrectly."""
    # setup
    identifier = 'BC0000001'
    colind_id = 1
    filing = copy.deepcopy(CONVERSION_FILING_TEMPLATE)

    # Change the template to be LTD, ULC or CCC
    filing['filing']['business']['legalType'] = legal_type
    filing['filing']['business']['identifier'] = identifier
    filing['filing']['conversion']['nameRequest']['legalType'] = legal_type
    effective_date = datetime.utcnow()
    # Create the Filing object in the DB
    filing_rec = Filing(effective_date=effective_date, filing_json=filing)
    colin_event = ColinEventId()
    colin_event.colin_event_id = colind_id
    filing_rec.colin_event_ids.append(colin_event)
    # Override the state setting mechanism
    filing_rec.skip_status_listener = True
    filing_rec._status = 'PENDING'
    filing_rec.save()
    filing_meta = FilingMeta(application_date=effective_date)

    # test
    business, filing_rec = conversion.process(None, filing, filing_rec,
                                              filing_meta)

    # Assertions
    assert business.identifier == identifier
    assert business.founding_date.replace(
        tzinfo=None) == effective_date.replace(tzinfo=None)
    assert business.legal_type == filing['filing']['conversion'][
        'nameRequest']['legalType']
    assert business.legal_name == business.identifier[2:] + ' B.C. LTD.'
    assert len(business.offices.all()
               ) == 2  # One office is created in create_business method.
    assert len(business.share_classes.all()) == 2
    assert len(business.party_roles.all()) == 3