def _add_filings(con, json_data: dict, filing_list: list, identifier: str, corp_types: list) -> list: """Process all parts of the filing.""" filings_added = [] for filing_type in filing_list: filing = Filing() filing.header = json_data['header'] filing.filing_date = filing.header['date'] filing.filing_type = filing_type filing.body = filing_list[filing_type] print('body: ', filing.body) # get utc lear effective date and convert to pacific time for insert into oracle filing.effective_date = convert_to_pacific_time( filing.header['learEffectiveDate']) if filing_type != 'incorporationApplication': filing.business = Business.find_by_identifier( identifier, corp_types, con) else: filing.business = Business.create_corporation(con, json_data) # add the new filing event_id = Filing.add_filing(con, filing) filings_added.append({ 'event_id': event_id, 'filing_type': filing_type }) return filings_added
def get(identifier=None): """Return the complete business info.""" if not identifier: try: con = DB.connection con.begin() corp_type = request.args.get('legal_type', None).upper() corp_num = Business.get_next_corp_num(corp_type, con) con.commit() except Exception as err: # pylint: disable=broad-except; want to catch all errors current_app.logger.error(err.with_traceback(None)) if con: con.rollback() if corp_num: return jsonify({'corpNum': corp_num}), 200 return jsonify({'message': 'Identifier required'}), 404 try: business = Business.find_by_identifier(identifier) if not business: return jsonify({'message': f'{identifier} not found'}), 404 return jsonify(business.as_dict()) except GenericException as err: # pylint: disable=duplicate-code return jsonify( {'message': err.error}), err.status_code except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify( {'message': 'Error when trying to retrieve business record from COLIN'}), 500
def post(identifier, **kwargs): # pylint: disable=unused-argument; filing_type is only used for the get """Create a new filing.""" try: json_data = request.get_json() if not json_data: return jsonify({'message': 'No input data provided'}), 400 # validate schema is_valid, errors = validate(json_data, 'filing', validate_schema=True) if not is_valid: for err in errors: print(err.message) return jsonify( {'message': 'Error: Invalid Filing schema'}), 400 json_data = json_data.get('filing', None) filing_list = {'changeOfAddress': json_data.get('changeOfAddress', None), 'changeOfDirectors': json_data.get('changeOfDirectors', None), 'annualReport': json_data.get('annualReport', None)} # ensure that the business in the AR matches the business in the URL if identifier != json_data['business']['identifier']: return jsonify( {'message': 'Error: Identifier in URL does not match identifier in filing data'}), 400 filings_added = [] for filing_type in filing_list: if filing_list[filing_type]: filing = Filing() filing.business = Business.find_by_identifier(identifier) filing.header = json_data['header'] filing.filing_type = filing_type filing.body = filing_list[filing_type] # add the new filing event_id = Filing.add_filing(filing) filings_added.append({'event_id': event_id, 'filing_type': filing_type}) # return the completed filing data completed_filing = Filing() completed_filing.header = json_data['header'] # get business info again - could have changed since filings were applied completed_filing.business = Business.find_by_identifier(identifier) completed_filing.body = {} for filing_info in filings_added: filing = Filing.find_filing(business=completed_filing.business, event_id=filing_info['event_id'], filing_type=filing_info['filing_type']) if not filing: raise FilingNotFoundException(identifier=identifier, filing_type=filing_info['filing_type'], event_id=filing_info['event_id']) completed_filing.body.update({filing_info['filing_type']: filing.body}) return jsonify(completed_filing.as_dict()), 201 except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify( {'message': 'Error when trying to retrieve business record from COLIN'}), 500
def get(info_type, legal_type=None, identifier=None): # pylint: disable = too-many-return-statements; """Return specific business info for businesses.""" try: con = DB.connection con.begin() cursor = con.cursor() if info_type == 'tax_ids': json_data = request.get_json() if not json_data or not json_data['identifiers']: return jsonify({'message': 'No input data provided' }), HTTPStatus.BAD_REQUEST # remove the BC prefix identifiers = [x[-7:] for x in json_data['identifiers']] bn_15s = Business._get_bn_15s( # pylint: disable = protected-access; internal call cursor=cursor, identifiers=identifiers) return jsonify(bn_15s), HTTPStatus.OK if info_type == 'resolutions': if not legal_type or legal_type not in [ x.value for x in Business.LearBusinessTypes ]: return jsonify({ 'message': 'Must provide a valid legal type.' }), HTTPStatus.BAD_REQUEST if not identifier: return jsonify({ 'message': f'Must provide a business identifier for {info_type}.' }), HTTPStatus.BAD_REQUEST # convert identifier if BC legal_type if legal_type in Business.CORP_TYPE_CONVERSION[ Business.LearBusinessTypes.BCOMP.value]: identifier = identifier[-7:] return jsonify({ 'resolutionDates': Business.get_resolutions(cursor=cursor, corp_num=identifier) }), HTTPStatus.OK return jsonify({'message': f'{info_type} not implemented.' }), HTTPStatus.NOT_IMPLEMENTED except Exception as err: # pylint: disable=broad-except; want to catch all errors current_app.logger.error(err.with_traceback(None)) return jsonify({'message': 'Something went wrong.' }), HTTPStatus.INTERNAL_SERVER_ERROR
def _add_filings(con, json_data, filing_list, identifier): filings_added = [] for filing_type in filing_list: filing = Filing() if filing_type != 'incorporationApplication': filing.business = Business.find_by_identifier(identifier, con) else: filing.business = Business.insert_new_business(con, filing_list[filing_type]) filing.header = json_data['header'] filing.filing_type = filing_type filing.body = filing_list[filing_type] filing.business.business['legalName'] = json_data['business']['legalName'] # add the new filing event_id = Filing.add_filing(con, filing) filings_added.append({'event_id': event_id, 'filing_type': filing_type}) return filings_added
def find_filing(cls, business: Business = None, filing_type: str = None, year: int = None): """Return a Filing.""" if not business or not filing_type: return None try: identifier = business.get_corp_num() # set filing type code from filing_type (string) if filing_type == 'annualReport': filing_type_code = 'OTANN' filing_obj = cls.find_ar(business, identifier, year) elif filing_type == 'changeOfAddress': filing_obj = cls.find_change_of_addr(business, identifier, year) else: # default value filing_type_code = 'FILE' raise InvalidFilingTypeException return filing_obj except FilingNotFoundException as err: # pass through exception to caller raise err except Exception as err: # general catch-all exception current_app.logger.error(err.with_traceback(None)) # pass through exception to caller raise err
def get(identifier, filing_type): """Return the complete filing info or historic (pre-bob-date=2019-03-08) filings.""" try: # get optional parameters (event_id / year) event_id = request.args.get('eventId', None) year = request.args.get('year', None) if year: year = int(year) # get business business = Business.find_by_identifier(identifier) # get filings history from before bob-date if filing_type == 'historic': historic_filings_info = Filing.get_historic_filings( business=business) return jsonify(historic_filings_info) # else get filing filing = Filing.get_filing(business=business, event_id=event_id, filing_type=filing_type, year=year) return jsonify(filing.as_dict()) except GenericException as err: # pylint: disable=duplicate-code return jsonify({'message': err.error}), err.status_code except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify({ 'message': 'Error when trying to retrieve business record from COLIN' }), 500
def get(info_type): """Return specific business info for businesses.""" if info_type == 'tax_ids': json_data = request.get_json() if not json_data or not json_data['identifiers']: return jsonify({'message': 'No input data provided' }), HTTPStatus.BAD_REQUEST # remove the BC prefix identifiers = [x[-7:] for x in json_data['identifiers']] try: con = DB.connection con.begin() cursor = con.cursor() bn_15s = Business._get_bn_15s( # pylint: disable = protected-access; internal call cursor=cursor, identifiers=identifiers) return jsonify(bn_15s), HTTPStatus.OK except Exception as err: # pylint: disable=broad-except; want to catch all errors current_app.logger.error(err.with_traceback(None)) return jsonify({'message': 'Something went wrong.' }), HTTPStatus.INTERNAL_SERVER_ERROR return jsonify({'message': f'{info_type} not implemented.' }), HTTPStatus.NOT_IMPLEMENTED
def get(legal_type: str, identifier: str): """Return the complete business info.""" if legal_type not in [x.value for x in Business.LearBusinessTypes]: return jsonify({'message': 'Must provide a valid legal type.' }), HTTPStatus.BAD_REQUEST try: # convert identifier if BC legal_type if legal_type in Business.CORP_TYPE_CONVERSION[ Business.LearBusinessTypes.BCOMP.value]: identifier = identifier[-7:] # get business corp_types = Business.CORP_TYPE_CONVERSION[legal_type] business = Business.find_by_identifier(identifier, corp_types) if not business: return jsonify({'message': f'{identifier} not found' }), HTTPStatus.NOT_FOUND return jsonify(business.as_dict()), HTTPStatus.OK except GenericException as err: # pylint: disable=duplicate-code return jsonify({'message': err.error}), err.status_code except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify({ 'message': 'Error when trying to retrieve business record from COLIN' }), HTTPStatus.INTERNAL_SERVER_ERROR
def get_historic_filings(cls, business: Business = None): """Get list all filings from before the bob-date=2019-03-08.""" if not business: return None try: historic_filings = [] cursor = DB.connection.cursor() cursor.execute(""" select event.event_id, event_timestmp, filing_typ_cd, effective_dt, period_end_dt, agm_date from event join filing on event.event_id = filing.event_id where corp_num=:identifier order by event_timestmp """, identifier=business.get_corp_num() ) filings_info_list = [] for filing_info in cursor: filings_info_list.append(dict(zip([x[0].lower() for x in cursor.description], filing_info))) for filing_info in filings_info_list: if not cls.FILING_TYPES[filing_info['filing_typ_cd']]: raise InvalidFilingTypeException(filing_type=filing_info['filing_typ_cd']) filing_info['filing_type'] = cls.FILING_TYPES[filing_info['filing_typ_cd']] date = convert_to_json_date(filing_info['event_timestmp']) if date < '2019-03-08': filing = Filing() filing.business = business filing.header = { 'date': date, 'name': filing_info['filing_type'], 'effectiveDate': convert_to_json_date(filing_info['effective_dt']), 'historic': True, 'availableOnPaperOnly': True, 'colinIds': [filing_info['event_id']] } filing.body = { filing_info['filing_type']: { 'annualReportDate': convert_to_json_date(filing_info['period_end_dt']), 'annualGeneralMeetingDate': convert_to_json_date(filing_info['agm_date']) } } historic_filings.append(filing.as_dict()) return historic_filings except InvalidFilingTypeException as err: current_app.logger.error('Unknown filing type found when getting historic filings for ' f'{business.get_corp_num()}.') # pass through exception to caller raise err except Exception as err: # general catch-all exception current_app.logger.error(err.with_traceback(None)) # pass through exception to caller raise err
def get(legal_type, identifier, filing_type): """Return the complete filing info or historic (pre-bob-date=2019-03-08) filings.""" try: if legal_type not in [x.value for x in Business.LearBusinessTypes]: return jsonify({'message': 'Must provide a valid legal type.' }), HTTPStatus.BAD_REQUEST # get optional parameters (event_id / year) event_id = request.args.get('eventId', None) year = request.args.get('year', None) if year: year = int(year) # convert identifier if BC legal_type if legal_type in Business.CORP_TYPE_CONVERSION[ Business.LearBusinessTypes.BCOMP.value]: identifier = identifier[-7:] # get business corp_types = Business.CORP_TYPE_CONVERSION[legal_type] business = Business.find_by_identifier(identifier, corp_types) # get filings history from before bob-date if filing_type == 'historic': historic_filings_info = Filing.get_historic_filings( business=business) return jsonify(historic_filings_info) # else get filing filing = Filing() filing.business = business filing.filing_type = filing_type filing.event_id = event_id filing = Filing.get_filing(filing=filing, year=year) return jsonify(filing.as_dict()) except GenericException as err: # pylint: disable=duplicate-code return jsonify({'message': err.error}), err.status_code except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify({ 'message': 'Error when trying to retrieve business record from COLIN' }), HTTPStatus.INTERNAL_SERVER_ERROR
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)
def get_filing(cls, business: Business = None, event_id: str = None, filing_type: str = None, year: int = None): """Get a Filing.""" if not business or not filing_type: return None try: identifier = business.get_corp_num() if filing_type == 'annualReport': filing_obj = cls._get_ar(identifier=identifier, event_id=event_id, year=year) elif filing_type == 'changeOfAddress': filing_obj = cls._get_coa(identifier=identifier, event_id=event_id, year=year) elif filing_type == 'changeOfDirectors': filing_obj = cls._get_cod(identifier=identifier, event_id=event_id, year=year) else: raise InvalidFilingTypeException(filing_type=filing_type) filing_obj.business = business return filing_obj except FilingNotFoundException as err: # pass through exception to caller raise err except Exception as err: # general catch-all exception current_app.logger.error(err.with_traceback(None)) # pass through exception to caller raise err
def get(identifier): """Return the complete business info.""" if not identifier: return jsonify({'message': 'Identifier required'}), 404 try: business = Business.find_by_identifier(identifier) if not business: return jsonify({'message': f'{identifier} not found'}), 404 return jsonify(business.as_dict()) except GenericException as err: # pylint: disable=duplicate-code return jsonify({'message': err.error}), err.status_code except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify({ 'message': 'Error when trying to retrieve business record from COLIN' }), 500
def post(legal_type: str): """Create and return a new corp number for the given legal type.""" if legal_type not in [x.value for x in Business.LearBusinessTypes]: return jsonify({'message': 'Must provide a valid legal type.' }), HTTPStatus.BAD_REQUEST try: con = DB.connection con.begin() corp_num = Business.get_next_corp_num(con=con, corp_type=legal_type) con.commit() except Exception as err: # pylint: disable=broad-except; want to catch all errors current_app.logger.error(err.with_traceback(None)) if con: con.rollback() if corp_num: return jsonify({'corpNum': corp_num}), HTTPStatus.OK return jsonify({'message': 'Failed to get new corp number' }), HTTPStatus.INTERNAL_SERVER_ERROR
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
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() legal_type = corp_num[:2] user_id = Filing.USERS[legal_type] if legal_type in ('CP', 'BC') 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 cls._add_office_from_filing(cursor, event_id, corp_num, user_id, filing) # 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']: Party.create_new_corp_party(cursor=cursor, event_id=event_id, party=director, business=filing.business.as_dict()) if 'ceased' in director['actions'] and not any(elem in ['nameChanged', 'addressChanged'] for elem in director['actions']): Party.end_director_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'] = '' Party.end_director_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: Party.create_new_corp_party(cursor=cursor, event_id=event_id, party=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) elif filing.filing_type == 'incorporationApplication': # Add business, update business info # Add offices date = None filing_type_cd = 'OTINC' cls._create_filing(cursor, event_id, corp_num, date, None, filing_type_cd) # Do incorporation here Business.create_corp_name(cursor, corp_num, 'test name', event_id) Business.create_corp_state(cursor, corp_num, event_id) cls._add_office_from_filing(cursor, event_id, corp_num, user_id, filing) cls._add_parties_from_filing(cursor, event_id, filing) cls._add_shares_from_filing(cursor, event_id, corp_num, filing) 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
def get_filing(cls, con=None, # pylint: disable=too-many-arguments, too-many-branches; business: Business = None, event_id: str = None, filing_type: str = None, year: int = None): """Get a Filing.""" if not business or not filing_type: return None try: if not con: con = DB.connection con.begin() cursor = con.cursor() identifier = business.get_corp_num() # get the filing types corresponding filing code code = [key for key in cls.FILING_TYPES if cls.FILING_TYPES[key] == filing_type] if len(code) < 1: raise InvalidFilingTypeException(filing_type=filing_type) # get the filing event info filing_event_info = cls._get_filing_event_info(identifier=identifier, event_id=event_id, filing_type_cd=code[0], year=year, cursor=cursor) if not filing_event_info: raise FilingNotFoundException(identifier=identifier, filing_type=filing_type, event_id=event_id) if filing_type == 'annualReport': filing_obj = cls._get_ar(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) elif filing_type == 'changeOfAddress': filing_obj = cls._get_coa(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) elif filing_type == 'changeOfDirectors': filing_obj = cls._get_cod(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) elif filing_type == 'changeOfName': filing_obj = cls._get_con(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) elif filing_type == 'specialResolution': filing_obj = cls._get_sr(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) elif filing_type == 'voluntaryDissolution': filing_obj = cls._get_vd(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) elif filing_type == 'incorporationApplication': filing_obj = cls._get_inc(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) else: # uncomment to bring in other filings as available on paper only # filing_obj = cls._get_other(identifier=identifier, filing_event_info=filing_event_info, cursor=cursor) raise InvalidFilingTypeException(filing_type=filing_type) filing_obj.header = { 'availableOnPaperOnly': filing_obj.paper_only, 'certifiedBy': filing_event_info['certifiedBy'], 'colinIds': [filing_obj.body['eventId']], 'date': convert_to_json_date(filing_event_info['event_timestmp']), 'effectiveDate': convert_to_json_datetime(filing_obj.effective_date), 'email': filing_event_info['email'], 'name': filing_type } filing_obj.business = business return filing_obj except FilingNotFoundException as err: # pass through exception to caller raise err except Exception as err: # general catch-all exception current_app.logger.error(err.with_traceback(None)) # pass through exception to caller raise err
def post(identifier, **kwargs): """Create a new filing.""" # pylint: disable=unused-argument,too-many-branches; filing_type is only used for the get try: json_data = request.get_json() if not json_data: return jsonify({'message': 'No input data provided'}), 400 # validate schema is_valid, errors = validate(json_data, 'filing', validate_schema=True) if not is_valid: for err in errors: print(err.message) return jsonify( {'message': 'Error: Invalid Filing schema'}), 400 json_data = json_data.get('filing', None) filing_list = {'changeOfAddress': json_data.get('changeOfAddress', None), 'changeOfDirectors': json_data.get('changeOfDirectors', None), 'annualReport': json_data.get('annualReport', None), 'incorporationApplication': json_data.get('incorporationApplication', None)} # Filter out null-values in the filing_list dictionary filing_list = {k: v for k, v in filing_list.items() if filing_list[k]} # ensure that the business in the AR matches the business in the URL if identifier != json_data['business']['identifier']: return jsonify( {'message': 'Error: Identifier in URL does not match identifier in filing data'}), 400 try: # get db connection and start a session, in case we need to roll back con = DB.connection con.begin() filings_added = FilingInfo._add_filings(con, json_data, filing_list, identifier) # return the completed filing data completed_filing = Filing() completed_filing.header = json_data['header'] completed_filing.header['colinIds'] = [] search_corp_num = json_data['business']['identifier'] if search_corp_num[:2] != 'CP': search_corp_num = search_corp_num[-7:] # get business info again - could have changed since filings were applied completed_filing.business = Business.find_by_identifier(search_corp_num, con) completed_filing.body = {} for filing_info in filings_added: filing = Filing.get_filing(con=con, business=completed_filing.business, event_id=filing_info['event_id'], filing_type=filing_info['filing_type']) if not filing: raise FilingNotFoundException(identifier=identifier, filing_type=filing_info['filing_type'], event_id=filing_info['event_id']) completed_filing.body.update({filing_info['filing_type']: filing.body}) completed_filing.header['colinIds'].append(filing_info['event_id']) # success! commit the db changes con.commit() return jsonify(completed_filing.as_dict()), 201 except Exception as db_err: current_app.logger.error(db_err.with_traceback(None)) if con: con.rollback() raise db_err except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify( {'message': 'Error when trying to retrieve business record from COLIN'}), 500
def get_filing(cls, business: Business = None, event_id: str = None, filing_type: str = None, year: int = None): """Get a Filing.""" if not business or not filing_type: return None try: identifier = business.get_corp_num() # get the filing types corresponding filing code code = [ key for key in cls.FILING_TYPES if cls.FILING_TYPES[key] == filing_type ] if len(code) < 1: raise InvalidFilingTypeException(filing_type=filing_type) # get the filing event info filing_event_info = cls._get_filing_event_info( identifier=identifier, event_id=event_id, filing_type_cd=code[0], year=year) if not filing_event_info: raise FilingNotFoundException(identifier=identifier, filing_type=filing_type, event_id=event_id) if filing_type == 'annualReport': filing_obj = cls._get_ar(identifier=identifier, filing_event_info=filing_event_info) elif filing_type == 'changeOfAddress': filing_obj = cls._get_coa(identifier=identifier, filing_event_info=filing_event_info) elif filing_type == 'changeOfDirectors': filing_obj = cls._get_cod(identifier=identifier, filing_event_info=filing_event_info) elif filing_type == 'changeOfName': filing_obj = cls._get_con(identifier=identifier, filing_event_info=filing_event_info) elif filing_type == 'specialResolution': filing_obj = cls._get_sr(identifier=identifier, filing_event_info=filing_event_info) elif filing_type == 'voluntaryDissolution': filing_obj = cls._get_vd(identifier=identifier, filing_event_info=filing_event_info) else: raise InvalidFilingTypeException(filing_type=filing_type) filing_obj.header = { 'date': convert_to_json_date(filing_event_info['event_timestmp']), 'name': filing_type, 'certifiedBy': filing_event_info['certifiedBy'], 'email': filing_event_info['email'], 'availableOnPaperOnly': filing_obj.filing_type in ['voluntaryDissolution', 'specialResolution'] } filing_obj.business = business return filing_obj except FilingNotFoundException as err: # pass through exception to caller raise err except Exception as err: # general catch-all exception current_app.logger.error(err.with_traceback(None)) # pass through exception to caller raise err
def post(legal_type, identifier, **kwargs): """Create a new filing.""" # pylint: disable=unused-argument,too-many-branches; filing_type is only used for the get try: if legal_type not in [x.value for x in Business.LearBusinessTypes]: return jsonify({'message': 'Must provide a valid legal type.' }), HTTPStatus.BAD_REQUEST json_data = request.get_json() if not json_data: return jsonify({'message': 'No input data provided' }), HTTPStatus.BAD_REQUEST # validate schema is_valid, errors = validate(json_data, 'filing', validate_schema=True) if not is_valid: for err in errors: print(err.message) return jsonify({'message': 'Error: Invalid Filing schema' }), HTTPStatus.BAD_REQUEST json_data = json_data.get('filing', None) # ensure that the business in the AR matches the business in the URL if identifier != json_data['business']['identifier']: return jsonify({ 'message': 'Error: Identifier in URL does not match identifier in filing data' }), HTTPStatus.BAD_REQUEST # convert identifier if BC legal_type if legal_type in Business.CORP_TYPE_CONVERSION[ Business.LearBusinessTypes.BCOMP.value]: identifier = identifier[-7:] corp_types = Business.CORP_TYPE_CONVERSION[legal_type] if json_data.get('correction', None): filing_list = {'correction': json_data['correction']} else: filing_list = { 'changeOfAddress': json_data.get('changeOfAddress', None), 'changeOfDirectors': json_data.get('changeOfDirectors', None), 'annualReport': json_data.get('annualReport', None), 'incorporationApplication': json_data.get('incorporationApplication', None), 'alteration': json_data.get('alteration', None), 'transition': json_data.get('transition', None) } # Filter out null-values in the filing_list dictionary filing_list = { k: v for k, v in filing_list.items() if filing_list[k] } print('filing list: ', filing_list) try: # get db connection and start a session, in case we need to roll back con = DB.connection con.begin() filings_added = FilingInfo._add_filings( con, json_data, filing_list, identifier, corp_types) # return the completed filing data completed_filing = Filing() # get business info again - could have changed since filings were applied completed_filing.business = Business.find_by_identifier( identifier, corp_types, con) completed_filing.body = {} for filing_info in filings_added: sub_filing = Filing() sub_filing.business = completed_filing.business sub_filing.filing_type = filing_info['filing_type'] sub_filing.event_id = filing_info['event_id'] sub_filing = Filing.get_filing(filing=sub_filing, con=con) if completed_filing.header: completed_filing.header['colinIds'].append( sub_filing.event_id) # annual report is the only filing with sub filings underneath it if sub_filing.filing_type == 'annualReport': completed_filing.header['name'] = 'annualReport' else: completed_filing.header = sub_filing.header completed_filing.body.update( {sub_filing.filing_type: sub_filing.body}) # success! commit the db changes con.commit() return jsonify(completed_filing.as_dict()), HTTPStatus.CREATED except Exception as db_err: current_app.logger.error( 'failed to file - rolling back partial db changes.') if con: con.rollback() raise db_err except Exception as err: # pylint: disable=broad-except; want to catch all errors # general catch-all exception current_app.logger.error(err.with_traceback(None)) return jsonify({ 'message': f'Error when trying to file for business {identifier}' }), HTTPStatus.INTERNAL_SERVER_ERROR