Example #1
0
    def find_by_registration_number(cls,
                                    registration_num: str = None,
                                    staff: bool = False,
                                    allow_historical: bool = False):
        """Return a financing statement by registration number."""
        statement = None
        if registration_num:
            # statement = cls.query.filter(FinancingStatement.financing_id == Registration.financing_id,
            #                            Registration.registration_num == registration_num,
            #                            Registration.registration_type_cl.in_(['PPSALIEN', 'MISCLIEN'])).one_or_none()
            statement = db.session.query(FinancingStatement).\
                        filter(FinancingStatement.financing_id == Registration.financing_id,
                               Registration.registration_num == registration_num,
                               Registration.registration_type_cl.in_(['PPSALIEN', 'MISCLIEN', 'CROWNLIEN'])).\
                               one_or_none()

        if not statement:
            raise BusinessException(
                error=
                f'No Financing Statement found for registration number {registration_num}.',
                status_code=HTTPStatus.NOT_FOUND)

        if not allow_historical and not staff and statement.state_type_cd != model_utils.STATE_ACTIVE:
            raise BusinessException(
                error=
                f'The Financing Statement for registration number {registration_num} has been discharged.',
                status_code=HTTPStatus.BAD_REQUEST)

        return statement
Example #2
0
def validate_delete_ids(json_data, financing_statement):
    """Perform non-schema extra validation on a change amendment delete party, collateral ID's."""
    error_msg = party_validator.validate_party_ids(json_data,
                                                   financing_statement)
    error_msg += registration_validator.validate_collateral_ids(
        json_data, financing_statement)
    if error_msg != '':
        raise BusinessException(error=error_msg,
                                status_code=HTTPStatus.BAD_REQUEST)
Example #3
0
 def save(self):
     """Render a search results detail information to the local cache."""
     try:
         db.session.add(self)
         db.session.commit()
     except Exception as db_exception:  # noqa: B902; just logging
         current_app.logger.error('DB search_result save exception: ' +
                                  repr(db_exception))
         raise BusinessException(
             error='Database search_result save failed: ' +
             repr(db_exception),
             status_code=HTTPStatus.INTERNAL_SERVER_ERROR)
Example #4
0
 def save(self):
     """Render a search query to the local cache."""
     try:
         db.session.add(self)
         db.session.commit()
     except Exception as db_exception:
         current_app.logger.error('DB search_client save exception: ' +
                                  repr(db_exception))
         raise BusinessException(
             error='Database search_client save failed: ' +
             repr(db_exception),
             status_code=HTTPStatus.INTERNAL_SERVER_ERROR)
Example #5
0
    def find_by_document_number(cls,
                                document_number: str = None,
                                allow_used: bool = False):
        """Return a draft statement by document ID."""
        draft = None
        if document_number:
            draft = cls.query.filter(
                Draft.document_number == document_number).one_or_none()

        if not draft:
            raise BusinessException(
                error=
                f'No Draft Statement found for Document ID {document_number}.',
                status_code=HTTPStatus.NOT_FOUND)

        if draft.registration and not allow_used:
            raise BusinessException(
                error=
                f'Draft Statement for Document ID {document_number} has been used.',
                status_code=HTTPStatus.BAD_REQUEST)

        return draft
Example #6
0
    def find_by_registration_number(cls, registration_num: str,
                                    account_id: str,
                                    staff: bool = False,
                                    base_reg_num: str = None):
        """Return the registration matching the registration number."""
        registration = None
        if registration_num:
            registration = cls.query.filter(Registration.registration_num == registration_num).one_or_none()

        if not registration:
            raise BusinessException(
                error=model_utils.ERR_REGISTRATION_NOT_FOUND.format(registration_num=registration_num),
                status_code=HTTPStatus.NOT_FOUND
            )

        if not staff and account_id and registration.account_id != account_id:
            # Check extra registrations
            extra_reg = UserExtraRegistration.find_by_registration_number(base_reg_num, account_id)
            if not extra_reg:
                raise BusinessException(
                    error=model_utils.ERR_REGISTRATION_ACCOUNT.format(account_id=account_id,
                                                                      registration_num=registration_num),
                    status_code=HTTPStatus.UNAUTHORIZED
                )

        if not staff and model_utils.is_historical(registration.financing_statement, False):
            raise BusinessException(
                error=model_utils.ERR_FINANCING_HISTORICAL.format(registration_num=registration_num),
                status_code=HTTPStatus.BAD_REQUEST
            )

        if not staff and base_reg_num and base_reg_num != registration.base_registration_num:
            raise BusinessException(
                error=model_utils.ERR_REGISTRATION_MISMATCH.format(registration_num=registration_num,
                                                                   base_reg_num=base_reg_num),
                status_code=HTTPStatus.BAD_REQUEST
            )

        return registration
Example #7
0
    def validate(json_data):
        """Perform any extra data validation here, either because it is too complicated for the schema.

        Or because it requires existing data (client party codes).
        """
        error_msg = ''

        # Verify the party codes.
        error_msg = error_msg + FinancingStatement.validate_parties(json_data)

        if error_msg != '':
            raise BusinessException(error=error_msg,
                                    status_code=HTTPStatus.BAD_REQUEST)
Example #8
0
    def find_by_registration_number(cls, registration_num: str,
                                    account_id: str,
                                    staff: bool = False,
                                    create: bool = False):
        """Return a financing statement by registration number."""
        statement = None
        if registration_num:
            statement = db.session.query(FinancingStatement).\
                        filter(FinancingStatement.id == Registration.financing_id,
                               Registration.registration_num == registration_num,
                               Registration.registration_type_cl.in_(['PPSALIEN', 'MISCLIEN', 'CROWNLIEN'])).\
                               one_or_none()

        if not statement:
            raise BusinessException(
                error=model_utils.ERR_FINANCING_NOT_FOUND.format(registration_num=registration_num),
                status_code=HTTPStatus.NOT_FOUND
            )

        if not staff and account_id and statement.registration[0].account_id != account_id:
            # Check extra registrations
            extra_reg = UserExtraRegistration.find_by_registration_number(statement.registration[0].registration_num,
                                                                          account_id)
            if not extra_reg:
                raise BusinessException(
                    error=model_utils.ERR_REGISTRATION_ACCOUNT.format(account_id=account_id,
                                                                      registration_num=registration_num),
                    status_code=HTTPStatus.UNAUTHORIZED
                )
        # Skip historical check if staff and not creating
        if staff and not create:
            return statement
        if model_utils.is_historical(statement, create):  # and (not staff or create):
            raise BusinessException(
                error=model_utils.ERR_FINANCING_HISTORICAL.format(registration_num=registration_num),
                status_code=HTTPStatus.BAD_REQUEST
            )
        return statement
Example #9
0
 def save(self):
     """Render a user profile to the local cache."""
     try:
         db.session.add(self)
         db.session.commit()
         current_app.logger.debug('Created/updated user profile: {}'.format(
             self.json))
     except Exception as db_exception:  # noqa: B902; just logging and wrapping
         current_app.logger.error('DB user_profile save exception: ' +
                                  repr(db_exception))
         raise BusinessException(
             error='Database user_profile save failed: ' +
             repr(db_exception),
             status_code=HTTPStatus.INTERNAL_SERVER_ERROR)
Example #10
0
def get_callback_pdf(report_data, account_id, report_type, token,
                     account_name):
    """Event callback generate a PDF of the provided report type using the provided data."""
    try:
        return Report(report_data, account_id, report_type,
                      account_name).get_pdf(token=token)
    except FileNotFoundError:
        # We don't have a template for it, so it must only be available on paper.
        return jsonify({'message':
                        _('No PDF report found.')}), HTTPStatus.NOT_FOUND
    except Exception as err:  # noqa: B902; return nicer default error
        current_app.logger.error(
            f'Generate report failed for account {account_id}, type {report_type}: '
            + repr(err))
        raise BusinessException(error=DEFAULT_ERROR_MSG,
                                status_code=HTTPStatus.INTERNAL_SERVER_ERROR)
Example #11
0
    def get_or_create_user_by_jwt(cls, jwt_oidc_token, account_id: str = None):
        """Return a valid user for audit tracking purposes."""
        # GET existing or CREATE new user based on the JWT info
        try:
            user = User.find_by_jwt_token(jwt_oidc_token)
            current_app.logger.debug(f'finding user: {jwt_oidc_token}')
            if not user:
                current_app.logger.debug(f'didnt find user, attempting to create new user:{jwt_oidc_token}')
                user = User.create_from_jwt_token(jwt_oidc_token, account_id)

            return user
        except Exception as err:  # noqa: B902; just logging and wrapping as BusinessException
            current_app.logger.error(err.with_traceback(None))
            raise BusinessException('unable_to_get_or_create_user',
                                    '{"code": "unable_to_get_or_create_user",'
                                    '"description": "Unable to get or create user from the JWT, ABORT"}'
                                    )
Example #12
0
    def validate(json_data, financing_statement, registration_type_cl: str):
        """Perform any extra data validation here, either because it is too complicated for the schema.

        Or because it requires existing data.
        """
        error_msg = ''

        # Verify the party codes and delete party ID's.
        error_msg = error_msg + Registration.validate_parties(json_data, financing_statement)

        if registration_type_cl in (model_utils.REG_CLASS_AMEND,
                                    model_utils.REG_CLASS_AMEND_COURT,
                                    model_utils.REG_CLASS_CHANGE):
            # Check delete vehicle ID's
            if 'deleteVehicleCollateral' in json_data:
                for collateral in json_data['deleteVehicleCollateral']:
                    if 'vehicleId' not in collateral:
                        error_msg = error_msg + 'Required vehicleId missing in deleteVehicleCollateral. '
                    else:
                        collateral_id = collateral['vehicleId']
                        existing = Registration.find_vehicle_collateral_by_id(collateral_id,
                                                                              financing_statement.vehicle_collateral)
                        if not existing:
                            error_msg = error_msg + 'Invalid vehicleId ' + str(collateral_id) + \
                                                    ' in deleteVehicleCollateral. '

            # Check delete general collateral ID's
            if 'deleteGeneralCollateral' in json_data:
                for collateral in json_data['deleteGeneralCollateral']:
                    if 'collateralId' not in collateral:
                        error_msg = error_msg + 'Required collateralId missing in deleteGeneralCollateral. '
                    else:
                        collateral_id = collateral['collateralId']
                        existing = Registration.find_general_collateral_by_id(collateral_id,
                                                                              financing_statement.general_collateral)
                        if not existing:
                            error_msg = error_msg + 'Invalid collateralId ' + str(collateral_id) + \
                                                    ' in deleteGeneralCollateral. '

        if error_msg != '':
            raise BusinessException(
                error=error_msg,
                status_code=HTTPStatus.BAD_REQUEST
            )
Example #13
0
    def validate_query(json_data):
        """Perform any extra data validation here, either because it is too complicated for the schema.

        Or because it requires existing data.
        """
        error_msg = ''

        # validate search type - criteria combinations
        search_type = json_data['type']
        if search_type not in ('INDIVIDUAL_DEBTOR', 'BUSINESS_DEBTOR'):
            if 'value' not in json_data['criteria']:
                error_msg += f'Search criteria value is required for search type {search_type}. '
        else:
            if 'debtorName' not in json_data['criteria']:
                error_msg += f'Search criteria debtorName is required for search type {search_type}. '
            elif search_type == 'INDIVIDUAL_DEBTOR' and 'last' not in json_data[
                    'criteria']['debtorName']:
                error_msg += f'Search criteria debtorName last is required for search type {search_type}. '
            elif search_type == 'BUSINESS_DEBTOR' and 'business' not in json_data[
                    'criteria']['debtorName']:
                error_msg += f'Search criteria debtorName businessName is required for search type {search_type}. '

        # Verify the start and end dates.
        if 'startDateTime' in json_data or 'startDateTime' in json_data:
            now = model_utils.now_ts()
            ts_start = None
            ts_end = None
            if 'startDateTime' in json_data:
                ts_start = model_utils.ts_from_iso_format(
                    json_data['startDateTime'])
                if ts_start > now:
                    error_msg = error_msg + 'Search startDateTime invalid: it cannot be in the future. '
            if 'endDateTime' in json_data:
                ts_end = model_utils.ts_from_iso_format(
                    json_data['endDateTime'])
                if ts_end > now:
                    error_msg = error_msg + 'Search endDateTime invalid: it cannot be in the future. '

            if ts_start and ts_end and ts_start > ts_end:
                error_msg = error_msg + 'Search date range invalid: startDateTime cannot be after endDateTime. '

        if error_msg != '':
            raise BusinessException(error=error_msg,
                                    status_code=HTTPStatus.BAD_REQUEST)
Example #14
0
    def validate_search_select(select_json, search_id: int):  # pylint: disable=unused-argument
        """Perform any extra data validation here.

        Either because it is too complicated for the schema, or because it requires existing data.
        Also fetch the existing search_detail record and verify a previous search detail request on
        the same search ID has not been submitted.
        """
        error_msg = ''

        search_result = SearchResult.find_by_search_id(search_id)
        if not search_result:
            error_msg = f'Search select results failed: invalid search ID {search_id}.'
        elif search_result.search_select:
            # Search detail request already submitted.
            error_msg = f'Search select results failed: results already provided for search ID {search_id}.'

        if error_msg != '':
            raise BusinessException(error=error_msg,
                                    status_code=HTTPStatus.BAD_REQUEST)

        return search_result
Example #15
0
def check_access_registration(token: str, staff: bool, account_id: str,
                              statement):
    """Extra check on account access to a registration."""
    if staff or (account_id and statement.account_id == account_id):
        return

    account_name = get_account_name(token, account_id)
    access = False
    if account_name:
        for party in statement.financing_statement.parties:
            if party.party_type in (PARTY_REGISTERING, PARTY_SECURED) and \
                    party.business_name and party.business_name == account_name:
                access = True
            elif party.client_code and party.client_code.name == account_name:
                access = True
    if not access:
        reg_num = statement.registration_num
        current_app.logger.error('Account name ' + account_name +
                                 ' cannot access registration ' + reg_num)
        raise BusinessException(error=ACCOUNT_ACCESS.format(
            account_id=account_id, registration_num=reg_num),
                                status_code=HTTPStatus.UNAUTHORIZED)
Example #16
0
    def find_by_search_id(cls, search_id: int, limit_by_date: bool = False):
        """Return the search detail record matching the search_id."""
        search_detail = None
        error_msg = ''
        if search_id and not limit_by_date:
            search_detail = db.session.query(SearchResult).filter(
                SearchResult.search_id == search_id).one_or_none()
        elif search_id and limit_by_date:
            min_allowed_date = model_utils.today_ts_offset(
                GET_DETAIL_DAYS_LIMIT, False)
            search_detail = db.session.query(SearchResult).filter(
                SearchResult.search_id == search_id).one_or_none()
            if search_detail and search_detail.search and \
                    search_detail.search.search_ts.timestamp() < min_allowed_date.timestamp():
                min_ts = model_utils.format_ts(min_allowed_date)
                error_msg = f'Search get details search ID {search_id} timestamp too old: must be after {min_ts}.'

        if error_msg != '':
            raise BusinessException(error=error_msg,
                                    status_code=HTTPStatus.BAD_REQUEST)

        return search_detail