def find_affidavit_by_org_id(org_id: int): """Return affidavit for the org by finding the admin for the org.""" current_app.logger.debug('<find_affidavit_by_org_id ') affidavit = AffidavitModel.find_by_org_id(org_id) affidavit_dict = Affidavit(affidavit).as_dict() affidavit_dict['documentUrl'] = MinioService.create_signed_get_url( affidavit.document_id) current_app.logger.debug('>find_affidavit_by_org_id ') return affidavit_dict
def find_affidavit_by_user_guid(user_guid: str, status: str = None): """Return affidavit for the user.""" current_app.logger.debug('<find_affidavit_by_user_guid ') affidavit = AffidavitModel.find_effective_by_user_guid( user_guid, status) affidavit_dict = Affidavit(affidavit).as_dict() affidavit_dict['documentUrl'] = MinioService.create_signed_get_url( affidavit.document_id) current_app.logger.debug('>find_affidavit_by_user_guid ') return affidavit_dict
def approve_or_reject(org_id: int, is_approved: bool, user: UserModel): """Mark the affdiavit as approved or rejected.""" current_app.logger.debug('<find_affidavit_by_org_id ') affidavit: AffidavitModel = AffidavitModel.find_by_org_id(org_id) affidavit.decision_made_by = user.username affidavit.decision_made_on = datetime.now() affidavit.status_code = AffidavitStatus.APPROVED.value if is_approved else AffidavitStatus.REJECTED.value current_app.logger.debug('>find_affidavit_by_org_id ') return Affidavit(affidavit)
def create_affidavit(token_info: Dict, affidavit_info: Dict): """Create a new affidavit record.""" current_app.logger.debug('<create_affidavit ') user = UserService.find_by_jwt_token(token=token_info) # If the user already have a pending affidavit, raise error existing_affidavit = AffidavitModel.find_pending_by_user_id( user_id=user.identifier) if existing_affidavit is not None: raise BusinessException(Error.ACTIVE_AFFIDAVIT_EXISTS, None) contact = affidavit_info.pop('contact') affidavit_model = AffidavitModel( issuer=affidavit_info.get('issuer'), document_id=affidavit_info.get('documentId'), status_code=AffidavitStatus.PENDING.value, user_id=user.identifier) affidavit_model.add_to_session() # Save contact for the affidavit if contact: contact = ContactModel(**camelback2snake(contact)) contact.add_to_session() contact_link = ContactLinkModel() contact_link.affidavit = affidavit_model contact_link.contact = contact contact_link.add_to_session() affidavit_model.save() return Affidavit(affidavit_model)
def approve_or_reject_bceid_admin(admin_user_id: int, is_approved: bool, user: UserModel): """Mark the BCeId Admin Affidavit as approved or rejected.""" current_app.logger.debug('<approve_or_reject_bceid_admin ') affidavit: AffidavitModel = AffidavitModel.find_pending_by_user_id( admin_user_id) if affidavit is None: raise BusinessException(Error.DATA_NOT_FOUND, None) affidavit.decision_made_by = user.username affidavit.decision_made_on = datetime.now() affidavit.status_code = AffidavitStatus.APPROVED.value if is_approved else AffidavitStatus.REJECTED.value current_app.logger.debug('>approve_or_reject_bceid_admin ') return Affidavit(affidavit)
def approve_or_reject(org_id: int, is_approved: bool, user: UserModel): """Mark the affidavit as approved or rejected.""" current_app.logger.debug('<approve_or_reject ') # In order to get the pending affidavit to be reviewed, we need to filter out the following cases # 1. Inactive affidavits - usually while the old affidavit is made inactive # while the task is put on hold and the user uploads a new one. # 2. When the user account request is rejected, then user creates a new account filtered_affidavit_statuses = [ AffidavitStatus.INACTIVE.value, AffidavitStatus.REJECTED.value ] affidavit: AffidavitModel = AffidavitModel.find_by_org_id( org_id, filtered_affidavit_statuses) affidavit.decision_made_by = user.username affidavit.decision_made_on = datetime.now() affidavit.status_code = AffidavitStatus.APPROVED.value if is_approved else AffidavitStatus.REJECTED.value current_app.logger.debug('>approve_or_reject') return Affidavit(affidavit)
def create_affidavit(affidavit_info: Dict): """Create a new affidavit record.""" current_app.logger.debug('<create_affidavit ') user = UserService.find_by_jwt_token() # If the user already have a pending affidavit, raise error existing_affidavit: AffidavitModel = AffidavitModel.find_pending_by_user_id( user_id=user.identifier) trigger_task_update = False if existing_affidavit is not None: # inactivate the current affidavit existing_affidavit.status_code = AffidavitStatus.INACTIVE.value existing_affidavit.flush() trigger_task_update = True contact = affidavit_info.pop('contact') affidavit_model = AffidavitModel( issuer=affidavit_info.get('issuer'), document_id=affidavit_info.get('documentId'), status_code=AffidavitStatus.PENDING.value, user_id=user.identifier) affidavit_model.add_to_session() # Save contact for the affidavit if contact: contact = ContactModel(**camelback2snake(contact)) contact.add_to_session() contact_link = ContactLinkModel() contact_link.affidavit = affidavit_model contact_link.contact = contact contact_link.add_to_session() affidavit_model.save() if trigger_task_update: Affidavit._modify_task(user) return Affidavit(affidavit_model)
class Org: # pylint: disable=too-many-public-methods """Manages all aspects of Org data. This service manages creating, updating, and retrieving Org data via the Org model. """ def __init__(self, model): """Return an Org Service.""" self._model = model @ServiceTracing.disable_tracing def as_dict(self): """Return the internal Org model as a dictionary. None fields are not included. """ org_schema = OrgSchema() obj = org_schema.dump(self._model, many=False) return obj @staticmethod def create_org(org_info: dict, user_id): """Create a new organization.""" current_app.logger.debug('<create_org ') # bcol is treated like an access type as well;so its outside the scheme mailing_address = org_info.pop('mailingAddress', None) payment_info = org_info.pop('paymentInfo', {}) product_subscriptions = org_info.pop('productSubscriptions', None) bcol_profile_flags = None response = Org._validate_and_raise_error(org_info) # If the account is created using BCOL credential, verify its valid bc online account bcol_details_response = response.get('bcol_response', None) if bcol_details_response is not None and ( bcol_details := bcol_details_response.json()) is not None: Org._map_response_to_org(bcol_details, org_info) bcol_profile_flags = bcol_details.get('profileFlags') access_type = response.get('access_type') # set premium for GOVM accounts..TODO remove if not needed this logic if access_type == AccessType.GOVM.value: org_info.update({'typeCode': OrgType.PREMIUM.value}) org = OrgModel.create_from_dict(camelback2snake(org_info)) org.access_type = access_type # Set the status based on access type # Check if the user is APPROVED else set the org status to PENDING if access_type == AccessType.GOVM.value: org.status_code = OrgStatus.PENDING_INVITE_ACCEPT.value # If mailing address is provided, save it if mailing_address: Org.add_contact_to_org(mailing_address, org) # create the membership record for this user if its not created by staff and access_type is anonymous Org.create_membership(access_type, org, user_id) if product_subscriptions is not None: subscription_data = {'subscriptions': product_subscriptions} ProductService.create_product_subscription( org.id, subscription_data=subscription_data, skip_auth=True) ProductService.create_subscription_from_bcol_profile( org.id, bcol_profile_flags) Org._create_payment_for_org(mailing_address, org, payment_info, True) # TODO do we have to check anything like this below? # if payment_account_status == PaymentAccountStatus.FAILED: # raise BusinessException(Error.ACCOUNT_CREATION_FAILED_IN_PAY, None) # Send an email to staff to remind review the pending account is_staff_review_needed = access_type in ( AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value, AccessType.GOVN.value ) and not AffidavitModel.find_approved_by_user_id(user_id=user_id) user = UserModel.find_by_jwt_token() if is_staff_review_needed: Org._create_staff_review_task(org, user) org.commit() current_app.logger.info(f'<created_org org_id:{org.id}') return Org(org)
def delete_org(org_id): """Soft-Deletes an Org. Only admin can perform this. 1 - All businesses gets unaffiliated. 2 - All team members removed. 3 - If there is any credit on the account then cannot be deleted. Premium: 1 - If there is any active PAD transactions going on, then cannot be deleted. """ current_app.logger.debug(f'<Delete Org {org_id}') # Affiliation uses OrgService, adding as local import # pylint:disable=import-outside-toplevel, cyclic-import from auth_api.services.affiliation import Affiliation as AffiliationService check_auth(one_of_roles=(ADMIN, STAFF), org_id=org_id) org: OrgModel = OrgModel.find_by_org_id(org_id) if not org: raise BusinessException(Error.DATA_NOT_FOUND, None) if org.status_code not in (OrgStatus.ACTIVE.value, OrgStatus.PENDING_INVITE_ACCEPT.value): raise BusinessException(Error.NOT_ACTIVE_ACCOUNT, None) # Deactivate pay account Org._delete_pay_account(org_id) # Find all active affiliations and remove them. entities = AffiliationService.find_affiliations_by_org_id(org_id) for entity in entities: AffiliationService.delete_affiliation( org_id=org_id, business_identifier=entity['business_identifier'], reset_passcode=True) # Deactivate all members. members = MembershipModel.find_members_by_org_id(org_id) for member in members: member.status = Status.INACTIVE.value member.flush() user: UserModel = UserModel.find_by_id(member.user_id) # Remove user from keycloak group if they are not part of any orgs if len(MembershipModel.find_orgs_for_user(member.user_id)) == 0: KeycloakService.remove_from_account_holders_group( user.keycloak_guid) # If the admin is BCeID user, mark the affidavit INACTIVE. if user.login_source == LoginSource.BCEID.value and member.membership_type_code == ADMIN: affidavit: AffidavitModel = AffidavitModel.find_approved_by_user_id( user.id) if affidavit: affidavit.status_code = AffidavitStatus.INACTIVE.value affidavit.flush() # Set the account as INACTIVE org.status_code = OrgStatus.INACTIVE.value org.save() current_app.logger.debug('org Inactivated>')
def create_org( org_info: dict, user_id, # pylint: disable=too-many-locals, too-many-statements, too-many-branches token_info: Dict = None, bearer_token: str = None, origin_url: str = None): """Create a new organization.""" current_app.logger.debug('<create_org ') # bcol is treated like an access type as well;so its outside the scheme bcol_credential = org_info.pop('bcOnlineCredential', None) mailing_address = org_info.pop('mailingAddress', None) payment_info = org_info.pop('paymentInfo', {}) selected_payment_method = payment_info.get('paymentMethod', None) org_type = org_info.get('typeCode', OrgType.BASIC.value) branch_name = org_info.get('branchName', None) bcol_profile_flags = None # If the account is created using BCOL credential, verify its valid bc online account if bcol_credential: bcol_response = Org.get_bcol_details(bcol_credential, bearer_token).json() Org._map_response_to_org(bcol_response, org_info) bcol_profile_flags = bcol_response.get('profileFlags') is_staff_admin = token_info and Role.STAFF_CREATE_ACCOUNTS.value in token_info.get( 'realm_access').get('roles') is_bceid_user = token_info and token_info.get( 'loginSource', None) == LoginSource.BCEID.value Org.validate_account_limit(is_staff_admin, user_id) access_type = Org.validate_access_type(is_bceid_user, is_staff_admin, org_info) # Always check duplicated name for all type of account. Org.raise_error_if_duplicate_name(org_info['name'], branch_name) # set premium for GOVM accounts..TODO remove if not needed this logic if access_type == AccessType.GOVM.value: org_type = OrgType.PREMIUM.value org_info.update({'typeCode': OrgType.PREMIUM.value}) org = OrgModel.create_from_dict(camelback2snake(org_info)) org.access_type = access_type # If the account is anonymous or govm set the billable value as False else True org.billable = access_type not in [ AccessType.ANONYMOUS.value, AccessType.GOVM.value ] # Set the status based on access type # Check if the user is APPROVED else set the org status to PENDING # Send an email to staff to remind review the pending account if access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value) \ and not AffidavitModel.find_approved_by_user_id(user_id=user_id): Org._handle_bceid_status_and_notification(org, origin_url, token_info) if access_type == AccessType.GOVM.value: org.status_code = OrgStatus.PENDING_INVITE_ACCEPT.value # If mailing address is provided, save it if mailing_address: Org.add_contact_to_org(mailing_address, org) # create the membership record for this user if its not created by staff and access_type is anonymous Org.create_membership(access_type, is_staff_admin, org, user_id) # dir search and GOVM doesnt need default products if access_type not in (AccessType.ANONYMOUS.value, AccessType.GOVM.value): ProductService.create_default_product_subscriptions( org, bcol_profile_flags, is_new_transaction=False) payment_method = Org._validate_and_get_payment_method( selected_payment_method, OrgType[org_type], access_type=access_type) user_name = '' if payment_method == PaymentMethod.PAD.value: # to get the pad accepted date user: UserModel = UserModel.find_by_jwt_token(token=token_info) user_name = user.username Org._create_payment_settings(org, payment_info, payment_method, mailing_address, user_name, True) # TODO do we have to check anything like this below? # if payment_account_status == PaymentAccountStatus.FAILED: # raise BusinessException(Error.ACCOUNT_CREATION_FAILED_IN_PAY, None) org.commit() current_app.logger.info(f'<created_org org_id:{org.id}') return Org(org)
def create_org( org_info: dict, user_id, # pylint: disable=too-many-locals, too-many-statements, too-many-branches token_info: Dict = None, bearer_token: str = None, origin_url: str = None): """Create a new organization.""" current_app.logger.debug('<create_org ') # bcol is treated like an access type as well;so its outside the scheme bcol_credential = org_info.pop('bcOnlineCredential', None) mailing_address = org_info.pop('mailingAddress', None) payment_info = org_info.pop('paymentInfo', {}) selected_payment_method = payment_info.get('paymentMethod', None) org_type = org_info.get('typeCode', OrgType.BASIC.value) # If the account is created using BCOL credential, verify its valid bc online account if bcol_credential: bcol_response = Org.get_bcol_details(bcol_credential, org_info, bearer_token).json() Org._map_response_to_org(bcol_response, org_info) is_staff_admin = token_info and Role.STAFF_CREATE_ACCOUNTS.value in token_info.get( 'realm_access').get('roles') is_bceid_user = token_info and token_info.get( 'loginSource', None) == LoginSource.BCEID.value Org.validate_account_limit(is_staff_admin, user_id) access_type = Org.validate_access_type(is_bceid_user, is_staff_admin, org_info) duplicate_check = (org_type == OrgType.BASIC.value) or (not bcol_credential) if duplicate_check: # Allow duplicate names if premium and link to bcol Org.raise_error_if_duplicate_name(org_info['name']) org = OrgModel.create_from_dict(camelback2snake(org_info)) org.access_type = access_type # If the account is anonymous set the billable value as False else True org.billable = access_type != AccessType.ANONYMOUS.value # Set the status based on access type # Check if the user is APPROVED else set the org status to PENDING # Send an email to staff to remind review the pending account if access_type in (AccessType.EXTRA_PROVINCIAL.value, AccessType.REGULAR_BCEID.value) \ and not AffidavitModel.find_approved_by_user_id(user_id=user_id): org.status_code = OrgStatus.PENDING_AFFIDAVIT_REVIEW.value user = UserModel.find_by_jwt_token(token=token_info) Org.send_staff_review_account_reminder(user, org.id, origin_url) # If mailing address is provided, save it if mailing_address: Org.add_contact_to_org(mailing_address, org) # create the membership record for this user if its not created by staff and access_type is anonymous Org.create_membership(access_type, is_staff_admin, org, user_id) Org.add_product(org.id, token_info) payment_method = Org._validate_and_get_payment_method( selected_payment_method, OrgType[org_type]) Org._create_payment_settings(org, payment_info, payment_method, mailing_address, True) # TODO do we have to check anything like this below? # if payment_account_status == PaymentAccountStatus.FAILED: # raise BusinessException(Error.ACCOUNT_CREATION_FAILED_IN_PAY, None) org.commit() current_app.logger.info(f'<created_org org_id:{org.id}') return Org(org)