Example #1
0
    def reset_dirs_by_events(cls, cursor, event_ids: List):
        """Delete all parties created with given events and make all parties ended on given events active."""
        # get address ids of parties that will be deleted
        addrs_to_delete = Address.get_addresses_by_event(cursor=cursor,
                                                         event_ids=event_ids,
                                                         table='corp_party')

        # delete parties created on these events
        delete_from_table_by_event_ids(cursor=cursor,
                                       event_ids=event_ids,
                                       table='corp_party')

        # delete parties created on these events
        delete_from_table_by_event_ids(cursor=cursor,
                                       event_ids=event_ids,
                                       table='completing_party',
                                       column='event_id')

        # delete addresses associated with parties that were deleted
        Address.delete(cursor=cursor, address_ids=addrs_to_delete)

        # reset parties ended on these events
        try:
            cursor.execute(f"""
                UPDATE corp_party
                SET end_event_id = null, cessation_dt = null
                WHERE end_event_id in ({stringify_list(event_ids)})
            """)
        except Exception as err:
            current_app.logger.error(
                f'Error in corp_party: Failed to reset ended parties for events {event_ids}'
            )
            raise err
Example #2
0
    def reset_offices_by_events(cls, cursor, event_ids: list):
        """Reset offices to what they were before the given event ids."""
        # get address ids of offices that will be deleted
        addrs_to_delete = Address.get_addresses_by_event(cursor=cursor,
                                                         event_ids=event_ids,
                                                         table='office')

        # delete offices created on these events
        delete_from_table_by_event_ids(cursor=cursor,
                                       event_ids=event_ids,
                                       table='office')

        # delete addresses associated with directors that were deleted
        Address.delete(cursor=cursor, address_ids=addrs_to_delete)

        # reset offices ended on these events
        try:
            cursor.execute(f"""
                UPDATE office
                SET end_event_id = null
                WHERE end_event_id in ({stringify_list(event_ids)})
            """)
        except Exception as err:
            current_app.logger.error(
                f'Error in Office: Failed reset ended offices for events {event_ids}'
            )
            raise err
Example #3
0
    def get_current(cls, identifier: str = None):
        """Return current registered office address."""
        if not identifier:
            return None

        querystring = ("""
            select start_event_id, mailing_addr_id, delivery_addr_id, office_typ_cd
            from office
            where corp_num=:identifier and end_event_id is null
            """)

        try:
            cursor = DB.connection.cursor()
            cursor.execute(querystring, identifier=identifier)

            office_info = cursor.fetchall()
            office_arr = {}

            if not office_info:
                raise OfficeNotFoundException(identifier=identifier)

            for office_item in office_info:

                office = dict(
                    zip([x[0].lower() for x in cursor.description],
                        office_item))
                office_obj = Office()
                office_obj.event_id = office['start_event_id']
                office_obj.delivery_address = Address.get_by_address_id(
                    office['delivery_addr_id']).as_dict()
                office_obj.office_type = office['office_typ_cd']

                if office['mailing_addr_id']:
                    office_obj.mailing_address = Address.get_by_address_id(
                        office['mailing_addr_id']).as_dict()
                else:
                    office_obj.mailing_address = office_obj.delivery_address

                for item in office_obj.office_codes:
                    k = office_obj.office_codes[item]['code']
                    if k == office_obj.office_type:
                        if item not in office_arr.keys():
                            office_arr[item] = office_obj.as_dict()
                        else:
                            current_app.logger.error(
                                'got more than 1 current registered office address for {}'
                                .format(identifier))
            return office_arr
        except Exception as err:
            current_app.logger.error(
                'error getting office for corp: {}'.format(identifier))
            raise err
Example #4
0
    def create_new_director(cls, cursor, event_id: int = None, director: dict = None, business: dict = None):
        """Insert new director into the corp_party table."""
        if not event_id:
            current_app.logger.error('Error in director: No event id given to create director.')
        if not director:
            current_app.logger.error('Error in director: No director data given to create director.')

        # create new address
        delivery_addr_id = Address.create_new_address(cursor=cursor, address_info=director['deliveryAddress'])
        mailing_addr_id = delivery_addr_id

        if 'mailingAddress' in director:
            mailing_addr_id = Address.create_new_address(cursor=cursor, address_info=director['mailingAddress'])
        # create new corp party entry
        try:
            cursor.execute("""select noncorp_party_seq.NEXTVAL from dual""")
            row = cursor.fetchone()
            corp_party_id = int(row[0])
        except Exception as err:
            current_app.logger.error('Error in director: Failed to get next corp_party_id.')
            raise err
        try:
            cursor.execute("""
                insert into corp_party (corp_party_id, mailing_addr_id, delivery_addr_id, corp_num, party_typ_cd,
                start_event_id, end_event_id, appointment_dt, cessation_dt, last_nme, middle_nme, first_nme,
                bus_company_num)
                values (:corp_party_id, :mailing_addr_id, :delivery_addr_id, :corp_num, :party_typ_cd, :start_event_id,
                :end_event_id, TO_DATE(:appointment_dt, 'YYYY-mm-dd'), TO_DATE(:cessation_dt, 'YYYY-mm-dd'), :last_nme,
                :middle_nme, :first_nme, :bus_company_num)
                """,
                           corp_party_id=corp_party_id,
                           mailing_addr_id=mailing_addr_id,
                           delivery_addr_id=delivery_addr_id,
                           corp_num=business['business']['identifier'],
                           party_typ_cd='DIR',
                           start_event_id=event_id,
                           end_event_id=event_id if director['cessationDate'] else None,
                           appointment_dt=str(datetime.datetime.strptime(director['appointmentDate'], '%Y-%m-%d'))[:10],
                           cessation_dt=str(datetime.datetime.strptime(director['cessationDate'], '%Y-%m-%d'))[:10]
                           if director['cessationDate'] else None,
                           last_nme=director['officer']['lastName'],
                           middle_nme=director['officer'].get('middleInitial', ''),
                           first_nme=director['officer']['firstName'],
                           bus_company_num=business['business']['businessNumber']
                           )
        except Exception as err:
            current_app.logger.error(f'Error in director: Failed create new director for event {event_id}')
            raise err

        return corp_party_id
Example #5
0
    def _build_parties_list(cls,
                            cursor,
                            corp_num: str,
                            event_id: int = None) -> Optional[List]:
        parties = cursor.fetchall()

        if not parties:
            return None

        completing_parties = {}
        party_list = []
        description = cursor.description
        for row in parties:
            party = Party()
            party.title = ''
            row = dict(zip([x[0].lower() for x in description], row))
            if not row['appointment_dt']:
                row['appointment_dt'] = Business.get_founding_date(
                    cursor=cursor, corp_num=corp_num)
            party.officer = cls._get_officer(row)
            if (row.get('party_typ_cd', None) == cls.role_types['Director']
                ) and not row['delivery_addr_id']:
                current_app.logger.error(
                    f"Bad director data for {party.officer.get('firstName')} {party.officer.get('lastName')} {corp_num}"
                )
            else:
                if row['delivery_addr_id']:
                    party.delivery_address = Address.get_by_address_id(
                        cursor, row['delivery_addr_id']).as_dict()
                party.mailing_address = Address.get_by_address_id(cursor, row['mailing_addr_id']).as_dict() \
                    if row['mailing_addr_id'] else party.delivery_address
                party.appointment_date =\
                    convert_to_json_date(row.get('appointment_dt', None))
                party.cessation_date = convert_to_json_date(
                    row.get('cessation_dt', None))
                party.start_event_id = (row.get('start_event_id', '')) or ''
                party.end_event_id = (row.get('end_event_id', '')) or ''
                party.role_type = (row.get('party_typ_cd', '')) or ''
                party.corp_party_id = row.get('corp_party_id', None)

                party_list.append(party)
        if event_id:
            completing_parties = cls.get_completing_parties(cursor, event_id)
        return cls.group_parties(party_list, completing_parties)
Example #6
0
    def _add_office_from_filing(cls, cursor,  # pylint: disable=too-many-arguments
                                event_id, corp_num, user_id, filing):
        office_desc = ''
        text = 'Change to the %s.'

        if filing.filing_type == 'incorporationApplication':
            text = 'Incorporation for %s.'

        for office_type in filing.body['offices']:
            office_arr = filing.body['offices'][office_type]
            delivery_addr_id = Address.create_new_address(cursor, office_arr['deliveryAddress'])
            mailing_addr_id = Address.create_new_address(cursor, office_arr['mailingAddress'])
            office_desc = (office_type.replace('O', ' O')).title()
            office_code = Office.OFFICE_TYPES_CODES[office_type]
            # update office table to include new addresses
            Office.update_office(cursor, event_id, corp_num, delivery_addr_id,
                                 mailing_addr_id, office_code)
        # create new ledger text for address change
        cls._add_ledger_text(cursor, event_id, text % (office_desc), user_id)
Example #7
0
    def get_current(cls, identifier: str = None):
        """Return current registered office address."""
        if not identifier:
            return None

        querystring = ("""
            select start_event_id, mailing_addr_id, delivery_addr_id
            from office
            where corp_num=:identifier and end_event_id is null and office_typ_cd='RG'
            """)

        try:
            cursor = DB.connection.cursor()
            cursor.execute(querystring, identifier=identifier)

            office_info = cursor.fetchone()
            if not office_info:
                raise OfficeNotFoundException(identifier=identifier)

            test_second_office = cursor.fetchone()
            if test_second_office:
                current_app.logger.error(
                    'got more than 1 current registered office address for {}'.
                    format(identifier))

            office_info = dict(
                zip([x[0].lower() for x in cursor.description], office_info))
            office_obj = Office()
            office_obj.event_id = office_info['start_event_id']
            office_obj.delivery_address = Address.get_by_address_id(
                office_info['delivery_addr_id']).as_dict()
            if office_info['mailing_addr_id']:
                office_obj.mailing_address = Address.get_by_address_id(
                    office_info['mailing_addr_id']).as_dict()
            else:
                office_obj.mailing_address = office_obj.delivery_address
            return office_obj

        except Exception as err:
            current_app.logger.error(
                'error getting office for corp: {}'.format(identifier))
            raise err
Example #8
0
    def create_new_office(cls, cursor, addresses: Dict, event_id: str,
                          corp_num: str, office_type: str):
        """Create row for new office and end old one.

        addresses.keys() = ['deliveryAddress', 'mailingAddress']
        """
        delivery_addr_id = Address.create_new_address(
            cursor, addresses['deliveryAddress'], corp_num=corp_num)
        mailing_addr_id = Address.create_new_address(
            cursor, addresses['mailingAddress'], corp_num=corp_num)
        office_code = Office.OFFICE_TYPES_CODES[office_type]

        # update office table to include new addresses and end old office
        update_dict = {
            'new_event_id': event_id,
            'corp_num': corp_num,
            'new_delivery_addr_id': delivery_addr_id,
            'new_mailing_addr_id': mailing_addr_id,
            'office_code': office_code
        }
        Office.update_office(cursor=cursor, office_info=update_dict)
Example #9
0
    def _build_directors_list(cls, cursor, event_id: int = None):

        directors = cursor.fetchall()
        if not directors:
            return None

        directors_list = []
        for row in directors:
            director = Director()
            director.title = ''
            row = dict(zip([x[0].lower() for x in cursor.description], row))
            director.officer = {
                'firstName':
                row['first_nme'].strip() if row['first_nme'] else '',
                'lastName': row['last_nme'].strip() if row['last_nme'] else '',
                'middleInitial': row['middle_nme'] if row['middle_nme'] else ''
            }

            director.delivery_address = Address.get_by_address_id(
                row['delivery_addr_id']).as_dict()
            director.mailing_address = Address.get_by_address_id(
                row['mailing_addr_id']).as_dict()
            director.appointment_date = convert_to_json_date(
                row['appointment_dt']) if row['appointment_dt'] else None
            director.cessation_date = convert_to_json_date(
                row['cessation_dt']) if row['cessation_dt'] else None
            director.start_event_id = row['start_event_id'] if row[
                'start_event_id'] else ''
            director.end_event_id = row['end_event_id'] if row[
                'end_event_id'] else ''

            # this is in case the director was not ceased during this event
            if event_id and director.end_event_id and director.end_event_id > event_id:
                director.cessation_date = None

            directors_list.append(director)

        return directors_list
Example #10
0
    def get_by_event(cls, event_id: str = None):
        """Return current registered office address."""
        if not event_id:
            return None

        querystring = ("""
            select start_event_id, mailing_addr_id, delivery_addr_id
            from office
            where start_event_id=:event_id and office_typ_cd='RG'
            """)

        try:
            cursor = DB.connection.cursor()
            cursor.execute(querystring, event_id=event_id)

            office_info = cursor.fetchone()
            if not office_info:
                raise OfficeNotFoundException(event_id=event_id)

            office_info = dict(
                zip([x[0].lower() for x in cursor.description], office_info))
            office_obj = Office()
            office_obj.event_id = office_info['start_event_id']
            office_obj.delivery_address = Address.get_by_address_id(
                office_info['delivery_addr_id']).as_dict()
            if office_info['mailing_addr_id']:
                office_obj.mailing_address = Address.get_by_address_id(
                    office_info['mailing_addr_id']).as_dict()
            else:
                office_obj.mailing_address = office_obj.delivery_address

            return office_obj

        except Exception as err:  # pylint: disable=broad-except; want to catch all errs
            current_app.logger.error(
                'error getting office from event : {}'.format(event_id))

            raise err
Example #11
0
    def _build_offices_list(cls,
                            cursor,
                            querystring: str,
                            identifier: str = None,
                            event_id: str = None) -> Optional[List]:
        """Return the office objects for the given query."""
        if not cursor:
            cursor = DB.connection.cursor()
        if identifier:
            cursor.execute(querystring, identifier=identifier)
        else:
            cursor.execute(querystring, event_id=event_id)
        office_info = cursor.fetchall()
        offices = []
        if not office_info:
            return None

        description = cursor.description
        for office_item in office_info:
            office = dict(zip([x[0].lower() for x in description],
                              office_item))
            office_obj = Office()
            office_obj.office_type = cls.OFFICE_TYPES_CODES.get(
                office['office_typ_cd'], None)
            if office_obj.office_type:
                office_obj.event_id = office['start_event_id']
                office_obj.end_event_id = office['end_event_id']
                office_obj.delivery_address = Address.get_by_address_id(
                    cursor, office['delivery_addr_id']).as_dict()
                office_obj.office_code = office['office_typ_cd']
                if office['mailing_addr_id']:
                    office_obj.mailing_address = Address.get_by_address_id(
                        cursor, office['mailing_addr_id']).as_dict()
                else:
                    office_obj.mailing_address = office_obj.delivery_address
                offices.append(office_obj)

        return offices
Example #12
0
    def add_filing(cls, filing):  # pylint: disable=too-many-locals,too-many-statements,too-many-branches;
        """Add new filing to COLIN tables.

        :param filing: Filing dict.
        :returns (int): the filing ID of the new filing.
        """
        try:
            corp_num = filing.get_corp_num()

            # get db connection and start a session, in case we need to roll back
            con = DB.connection
            con.begin()
            cursor = con.cursor()

            # create new event record, return event ID
            event_id = cls._get_event_id(cursor, corp_num, 'FILE')

            # create new filing user
            cls._create_filing_user(cursor, event_id, filing)
            if filing.filing_type == 'annualReport':
                ar_date = filing.body['annualReportDate']
                agm_date = filing.body['annualGeneralMeetingDate']
                filing_type_cd = 'OTANN'

                # create new filing
                cls._create_filing(cursor, event_id, corp_num, ar_date,
                                   agm_date, filing_type_cd)

                # update corporation record
                Business.update_corporation(cursor, corp_num, agm_date)

                # update corp_state TO ACT (active) if it is in good standing. From CRUD:
                # - the current corp_state != 'ACT' and,
                # - they just filed the last outstanding ARs
                if filing.business.business['corpState'] != 'ACT':
                    agm_year = int(ar_date[:4])
                    last_year = datetime.datetime.now().year - 1
                    if agm_year >= last_year:
                        Business.update_corp_state(cursor,
                                                   event_id,
                                                   corp_num,
                                                   state='ACT')

            elif filing.filing_type == 'changeOfAddress':
                # set date to last ar date + 1
                last_ar_date = filing.business.business['lastArDate']
                day = int(last_ar_date[-2:]) + 1
                try:
                    date = str(
                        datetime.datetime.strptime(
                            last_ar_date[:-2] + ('0' + str(day))[1:],
                            '%Y-%m-%d'))[:10]
                except ValueError:
                    try:
                        day = '-01'
                        month = int(last_ar_date[5:7]) + 1
                        date = str(
                            datetime.datetime.strptime(
                                last_ar_date[:5] + ('0' + str(month))[1:] +
                                day, '%Y-%m-%d'))[:10]
                    except ValueError:
                        mm_dd = '-01-01'
                        yyyy = int(last_ar_date[:4]) + 1
                        date = str(
                            datetime.datetime.strptime(
                                str(yyyy) + mm_dd, '%Y-%m-%d'))[:10]

                # create new filing
                filing_type_cd = 'OTADD'
                cls._create_filing(cursor, event_id, corp_num, date, None,
                                   filing_type_cd)

                # create new addresses for delivery + mailing, return address ids
                delivery_addr_id = Address.create_new_address(
                    cursor, filing.body['deliveryAddress'])
                mailing_addr_id = Address.create_new_address(
                    cursor, filing.body['mailingAddress'])

                # update office table to include new addresses
                Office.update_office(cursor, event_id, corp_num,
                                     delivery_addr_id, mailing_addr_id, 'RG')

                # create new ledger text for address change
                cls._add_ledger_text(
                    cursor, event_id,
                    f'Change to the Registered Office, effective on {date}')
                # update corporation record
                Business.update_corporation(cursor, corp_num)

            elif filing.filing_type == 'changeOfDirectors':
                # create new filing
                date = filing.business.business['lastArDate']
                filing_type_cd = 'OTCDR'
                cls._create_filing(cursor, event_id, corp_num, date, None,
                                   filing_type_cd)

                # create, cease, change directors
                changed_dirs = []
                for director in filing.body['directors']:
                    if 'appointed' in director['actions']:
                        Director.create_new_director(
                            cursor=cursor,
                            event_id=event_id,
                            director=director,
                            business=filing.business.as_dict())

                    if 'ceased' in director['actions'] and not any(
                            elem in ['nameChanged', 'addressChanged']
                            for elem in director['actions']):
                        Director.end_by_name(cursor=cursor,
                                             director=director,
                                             event_id=event_id,
                                             corp_num=corp_num)

                    elif 'nameChanged' in director[
                            'actions'] or 'addressChanged' in director[
                                'actions']:
                        if 'appointed' in director['actions']:
                            current_app.logger.error(
                                f'Director appointed with name/address change: {director}'
                            )
                        changed_dirs.append(director)
                        # end tmp copy of director with no cessation date (will be recreated with changes and cessation
                        # date - otherwise end up with two copies of ended director)
                        tmp = director.copy()
                        tmp['cessationDate'] = ''
                        Director.end_by_name(cursor=cursor,
                                             director=tmp,
                                             event_id=event_id,
                                             corp_num=corp_num)

                # add back changed directors as new row - if ceased director with changes this will add them with
                # cessation date + end event id filled
                for director in changed_dirs:
                    Director.create_new_director(
                        cursor=cursor,
                        event_id=event_id,
                        director=director,
                        business=filing.business.as_dict())

                # create new ledger text for address change
                cls._add_ledger_text(cursor=cursor,
                                     event_id=event_id,
                                     text=f'Director change.')
                # update corporation record
                Business.update_corporation(cursor=cursor, corp_num=corp_num)

            else:
                raise InvalidFilingTypeException(
                    filing_type=filing.filing_type)

            # success! commit the db changes
            con.commit()
            return event_id

        except Exception as err:
            # something went wrong, roll it all back
            current_app.logger.error(err.with_traceback(None))
            if con:
                con.rollback()

            raise err
Example #13
0
    def create_new_corp_party(cls,
                              cursor,
                              event_id: int = None,
                              party: dict = None,
                              business: dict = None):
        """Insert new party into the corp_party table."""
        query = """
                insert into corp_party (corp_party_id, mailing_addr_id, delivery_addr_id, corp_num, party_typ_cd,
                start_event_id, end_event_id, appointment_dt, cessation_dt, last_nme, middle_nme, first_nme,
                bus_company_num, business_nme)
                values (:corp_party_id, :mailing_addr_id, :delivery_addr_id, :corp_num, :party_typ_cd, :start_event_id,
                :end_event_id, TO_DATE(:appointment_dt, 'YYYY-mm-dd'), TO_DATE(:cessation_dt, 'YYYY-mm-dd'), :last_nme,
                :middle_nme, :first_nme, :bus_company_num, :business_name)
                """

        completing_party_query = """
                insert into completing_party (event_id, mailing_addr_id, last_nme,
                middle_nme, first_nme, email_req_address)
                values (:event_id, :mailing_addr_id, :last_nme,
                :middle_nme, :first_nme, :email)
                """

        if not event_id:
            current_app.logger.error(
                'Error in corp_party: No event id given to create party.')
        if not party:
            current_app.logger.error(
                'Error in corp_party: No party data given to create party.')

        # create new corp party entry
        corp_num = business['business']['identifier']
        try:
            if corp_num == 'CP':
                cursor.execute(
                    """select noncorp_party_seq.NEXTVAL from dual""")
                row = cursor.fetchone()
                corp_party_id = int(row[0])
            else:
                cursor.execute("""
                    SELECT id_num
                    FROM system_id
                    WHERE id_typ_cd = 'CP'
                    FOR UPDATE
                """)

                corp_party_id = int(cursor.fetchone()[0])

                if corp_party_id:
                    cursor.execute("""
                        UPDATE system_id
                        SET id_num = :new_num
                        WHERE id_typ_cd = 'CP'
                    """,
                                   new_num=corp_party_id + 1)

        except Exception as err:
            current_app.logger.error(
                'Error in corp_party: Failed to get next corp_party_id.')
            raise err
        try:
            role_type = party.get('role_type', 'DIR')

            delivery_info = party[
                'deliveryAddress'] if 'deliveryAddress' in party else party[
                    'mailingAddress']

            # create new address
            delivery_addr_id = Address.create_new_address(
                cursor=cursor, address_info=delivery_info, corp_num=corp_num)
            mailing_addr_id = delivery_addr_id

            if 'mailingAddress' in party:
                mailing_addr_id = Address.create_new_address(
                    cursor=cursor,
                    address_info=party['mailingAddress'],
                    corp_num=corp_num)

            if role_type == 'CPRTY':
                cursor.execute(completing_party_query,
                               event_id=event_id,
                               mailing_addr_id=mailing_addr_id,
                               last_nme=party['officer']['lastName'],
                               middle_nme=party['officer'].get(
                                   'middleInitial', ''),
                               first_nme=party['officer']['firstName'],
                               email=party['officer']['email'])
            else:
                cursor.execute(
                    query,
                    corp_party_id=corp_party_id,
                    mailing_addr_id=mailing_addr_id,
                    delivery_addr_id=delivery_addr_id,
                    corp_num=corp_num,
                    party_typ_cd=role_type,
                    start_event_id=event_id,
                    end_event_id=event_id
                    if party.get('cessationDate', '') else None,
                    appointment_dt=str(
                        datetime.datetime.strptime(party['appointmentDate'],
                                                   '%Y-%m-%d'))[:10],
                    cessation_dt=str(
                        datetime.datetime.strptime(party['cessationDate'],
                                                   '%Y-%m-%d'))[:10]
                    if party.get('cessationDate', None) else None,
                    last_nme=party['officer']['lastName'],
                    middle_nme=party['officer'].get('middleInitial', ''),
                    first_nme=party['officer']['firstName'],
                    bus_company_num=business['business'].get(
                        'businessNumber', None),
                    business_name=party['officer'].get('orgName', ''),
                )

        except Exception as err:
            current_app.logger.error(
                f'Error in corp_party: Failed create new party for event {event_id}'
            )
            raise err

        return corp_party_id
Example #14
0
    def add_filing(cls, con, filing):  # pylint: disable=too-many-locals,too-many-statements,too-many-branches;
        """Add new filing to COLIN tables.

        :param con: DB connection
        :param filing: Filing dict.
        :returns (int): the filing ID of the new filing.
        """
        try:
            corp_num = filing.get_corp_num()
            user_id = 'COOPER' if corp_num[:2] == 'CP' else None
            cursor = con.cursor()

            # create new event record, return event ID
            event_id = cls._get_event_id(cursor, corp_num, 'FILE')

            # create new filing user
            cls._create_filing_user(cursor, event_id, filing, user_id)
            if filing.filing_type == 'annualReport':
                ar_date = filing.body['annualReportDate']
                agm_date = filing.body['annualGeneralMeetingDate']
                filing_type_cd = 'OTANN'

                # create new filing
                cls._create_filing(cursor, event_id, corp_num, ar_date,
                                   agm_date, filing_type_cd)

                # update corporation record
                Business.update_corporation(cursor, corp_num, agm_date, True)

                # update corp_state TO ACT (active) if it is in good standing. From CRUD:
                # - the current corp_state != 'ACT' and,
                # - they just filed the last outstanding ARs
                agm_year = int(ar_date[:4])
                if filing.business.business['corpState'] != 'ACT':
                    last_year = datetime.datetime.now().year - 1
                    if agm_year >= last_year:
                        Business.update_corp_state(cursor,
                                                   event_id,
                                                   corp_num,
                                                   state='ACT')

                # create new ledger text for annual report
                text = agm_date if agm_date else f'NO AGM HELD IN {agm_year}'
                cls._add_ledger_text(cursor=cursor,
                                     event_id=event_id,
                                     text=f'ANNUAL REPORT - {text}',
                                     user_id=user_id)

            elif filing.filing_type == 'changeOfAddress':
                # set date to last ar date + 1 -- Bob wants this to be set to null
                # last_ar_date = filing.business.business['lastArDate']
                # day = int(last_ar_date[-2:]) + 1
                # try:
                #     date = str(datetime.datetime.strptime(last_ar_date[:-2] + ('0' + str(day))[1:], '%Y-%m-%d'))[:10]
                # except ValueError:
                #     try:
                #         day = '-01'
                #         month = int(last_ar_date[5:7]) + 1
                #         date = str(datetime.datetime.strptime(last_ar_date[:5] + ('0' + str(month))[1:] + day,
                #                                               '%Y-%m-%d')
                #                    )[:10]
                #     except ValueError:
                #         mm_dd = '-01-01'
                #         yyyy = int(last_ar_date[:4]) + 1
                #         date = str(datetime.datetime.strptime(str(yyyy) + mm_dd, '%Y-%m-%d'))[:10]
                date = None

                # create new filing
                filing_type_cd = 'OTADD'
                cls._create_filing(cursor, event_id, corp_num, date, None,
                                   filing_type_cd)

                # create new addresses for delivery + mailing, return address ids
                for office_type in filing.body['offices']:
                    office_arr = filing.body['offices'][office_type]
                    delivery_addr_id = Address.create_new_address(
                        cursor, office_arr['deliveryAddress'])
                    mailing_addr_id = Address.create_new_address(
                        cursor, office_arr['mailingAddress'])
                    office_desc = (office_type.replace('O', ' O')).title()
                    office_code = Office.OFFICE_TYPES_CODES[office_type]

                    # update office table to include new addresses
                    Office.update_office(cursor, event_id, corp_num,
                                         delivery_addr_id, mailing_addr_id,
                                         office_code)

                    # create new ledger text for address change
                    cls._add_ledger_text(cursor, event_id,
                                         f'Change to the {office_desc}.',
                                         user_id)
                # update corporation record
                Business.update_corporation(cursor, corp_num)

            elif filing.filing_type == 'changeOfDirectors':
                # create new filing
                # bob wants this to be null
                # date = filing.business.business['lastArDate']
                date = None
                filing_type_cd = 'OTCDR'
                cls._create_filing(cursor, event_id, corp_num, date, None,
                                   filing_type_cd)

                # create, cease, change directors
                changed_dirs = []
                for director in filing.body['directors']:
                    if 'appointed' in director['actions']:
                        Director.create_new_director(
                            cursor=cursor,
                            event_id=event_id,
                            director=director,
                            business=filing.business.as_dict())

                    if 'ceased' in director['actions'] and not any(
                            elem in ['nameChanged', 'addressChanged']
                            for elem in director['actions']):
                        Director.end_by_name(cursor=cursor,
                                             director=director,
                                             event_id=event_id,
                                             corp_num=corp_num)

                    elif 'nameChanged' in director[
                            'actions'] or 'addressChanged' in director[
                                'actions']:
                        if 'appointed' in director['actions']:
                            current_app.logger.error(
                                f'Director appointed with name/address change: {director}'
                            )
                        changed_dirs.append(director)
                        # end tmp copy of director with no cessation date (will be recreated with changes and cessation
                        # date - otherwise end up with two copies of ended director)
                        tmp = director.copy()
                        tmp['cessationDate'] = ''
                        Director.end_by_name(cursor=cursor,
                                             director=tmp,
                                             event_id=event_id,
                                             corp_num=corp_num)

                # add back changed directors as new row - if ceased director with changes this will add them with
                # cessation date + end event id filled
                for director in changed_dirs:
                    Director.create_new_director(
                        cursor=cursor,
                        event_id=event_id,
                        director=director,
                        business=filing.business.as_dict())

                # create new ledger text for address change
                cls._add_ledger_text(cursor=cursor,
                                     event_id=event_id,
                                     text=f'Director change.',
                                     user_id=user_id)
                # update corporation record
                Business.update_corporation(cursor=cursor, corp_num=corp_num)

            else:
                raise InvalidFilingTypeException(
                    filing_type=filing.filing_type)

            return event_id

        except Exception as err:
            # something went wrong, roll it all back
            current_app.logger.error(err.with_traceback(None))

            raise err