def post(): """Create a new draft statement.""" try: # Quick check: must provide an account ID. account_id = get_account_id(request) if account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Disable schema validation: draft may be partial/incomplele. # valid_format, errors = schema_utils.validate(request_json, 'draft', 'ppr') # if not valid_format: # return validation_error_response(errors, VAL_ERROR) # Save new draft statement: BusinessException raised if failure. draft = Draft.create_from_json(request_json, account_id) draft.save() return draft.json, HTTPStatus.CREATED except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def get(registration_num): """Get a financing statement by registration number.""" try: if registration_num is None: return path_param_error_response('registration number') # Quick check: must be staff or provide an account ID. account_id = get_account_id(request) if not is_staff(jwt) and account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) # Try to fetch financing statement by registration number # Not found or non-staff historical throws a business exception. statement = FinancingStatement.find_by_registration_number(registration_num, is_staff(jwt)) return statement.json, HTTPStatus.OK except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def post(): """Create a new financing statement.""" try: # Quick check: must be staff or provide an account ID. account_id = get_account_id(request) if not is_staff(jwt) and account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Validate request data against the schema. valid_format, errors = schema_utils.validate(request_json, 'financingStatement', 'ppr') if not valid_format: return validation_error_response(errors, VAL_ERROR) # TODO: charge a fee. # Try to save the financing statement: failure throws a business exception. statement = FinancingStatement.create_from_json(request_json, account_id) statement.save() return statement.json, HTTPStatus.CREATED except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def get(code): """Get a preset registering or secured party by client code.""" try: if code is None: return resource_utils.path_param_error_response('code') # Quick check: must be staff or provide an account ID. account_id = resource_utils.get_account_id(request) if not is_staff(jwt) and account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) # Try to fetch client party by code current_app.logger.debug( f'Getting party code for account {account_id} with code = {code}.' ) party = ClientCode.find_by_code(code) if not party: return resource_utils.not_found_error_response('party', code) return party, HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def put(document_id): """Update a draft statement by document ID with data in the request body.""" try: if document_id is None: return path_param_error_response('document ID') # Quick check: must provide an account ID. account_id = get_account_id(request) if account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Disable schema validation: draft may be partial/incomplele. # valid_format, errors = schema_utils.validate(request_json, 'draft', 'ppr') # if not valid_format: # return validation_error_response(errors, VAL_ERROR) # Save draft statement update: BusinessException raised if failure. draft = Draft.update(request_json, document_id) draft.save() return draft.json, HTTPStatus.OK except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def get(name_or_code): """Get a list of client parties (registering or secured parties) associated with a head office code or name.""" try: if name_or_code is None: return resource_utils.path_param_error_response('nameOrCode') fuzzy_param = request.args.get(FUZZY_NAME_SEARCH_PARAM) # Quick check: must be staff or provide an account ID. account_id = resource_utils.get_account_id(request) if not is_staff(jwt) and account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) # Try to fetch client parties: no results is an empty list. current_app.logger.debug( f'Getting {account_id} head office party codes searching on {name_or_code}.' ) parties = ClientCode.find_by_head_office(name_or_code, fuzzy_param) # if not parties: # return resource_utils.not_found_error_response('party', code) return jsonify(parties), HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def post(registration_num): """Renew a financing statement by registration number.""" try: if registration_num is None: return path_param_error_response('registration number') # Quick check: must be staff or provide an account ID. account_id = get_account_id(request) if not is_staff(jwt) and account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Validate request data against the schema. valid_format, errors = schema_utils.validate(request_json, 'renewalStatement', 'ppr') if not valid_format: return validation_error_response(errors, VAL_ERROR_RENEWAL) # payload base registration number must match path registration number if registration_num != request_json['baseRegistrationNumber']: return path_data_mismatch_error_response(registration_num, 'base registration number', request_json['baseRegistrationNumber']) # Fetch base registration information: business exception thrown if not # found or historical. statement = FinancingStatement.find_by_registration_number(registration_num, False) # Verify base debtor (bypassed for staff) if not statement.validate_base_debtor(request_json['baseDebtor'], is_staff(jwt)): return base_debtor_invalid_response() # TODO: charge a fee. # Try to save the renewal statement: failure throws a business exception. statement = Registration.create_from_json(request_json, model_utils.REG_CLASS_RENEWAL, statement, registration_num, account_id) statement.save() return statement.json, HTTPStatus.OK except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def patch(): """Update user profile UI settings for the user represented by the request JWT.""" try: # Quick check: always require an account ID. account_id = resource_utils.get_account_id(request) if not is_staff(jwt) and account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) request_json = request.get_json(silent=True) current_app.logger.debug( f'Updating user profile for {account_id} with values: {request_json}' ) # Validate against the schema. if not bypass_validation(request_json): valid_format, errors = schema_utils.validate( request_json, 'userProfile', 'common') if not valid_format: return resource_utils.validation_error_response( errors, VAL_ERROR) token = g.jwt_oidc_token_info current_app.logger.debug( f'Updating user profile for {account_id} with token: {token}') # Try to fetch existing user from JWT. user = User.find_by_jwt_token(token) if not user: # If user does not exist, create user and user profile with the default settings. current_app.logger.error( f'Update user profile no user found for {account_id} request token.' ) return resource_utils.not_found_error_response( 'user profile', account_id) user_profile = user.user_profile user_profile.update_profile(request_json) return user_profile.json, HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error current_app.logger.error( f'Get user profile {account_id} failed: ' + repr(default_exception)) return resource_utils.default_exception_response(default_exception)
def post(search_id): """Execute a search detail request using selection choices in the request body.""" try: if search_id is None: return resource_utils.path_param_error_response('search ID') # Quick check: must be staff or provide an account ID. account_id = resource_utils.get_account_id(request) if not is_staff(jwt) and account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Validate schema. valid_format, errors = schema_utils.validate( request_json, 'searchSummary', 'ppr') if not valid_format: return resource_utils.validation_error_response( errors, VAL_ERROR) # Perform any extra data validation such as start and end dates here search_detail = SearchResult.validate_search_select( request_json, search_id) # Save the search query selection and details that match the selection. search_detail.update_selection(request_json) if not search_detail.search_response: return resource_utils.unprocessable_error_response( 'search result details') response_data = search_detail.json if resource_utils.is_pdf(request): token = g.jwt_oidc_token_info # Return report if request header Accept MIME type is application/pdf. return get_pdf(response_data, account_id, ReportTypes.SEARCH_DETAIL_REPORT.value, token['name']) return jsonify(response_data), HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def get(): """Get a list of client parties associated with an account-BCOL number pair.""" try: # Quick check: must be staff or provide an account ID. account_id = resource_utils.get_account_id(request) if account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) # Try to fetch client parties: no results is an empty list. current_app.logger.debug(f'Getting {account_id} party codes.') parties = ClientCode.find_by_account_id(account_id, True) return jsonify(parties), HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def get(): """Get existing user profile UI settings for the user represented by the request JWT.""" try: # Quick check: always require an account ID. account_id = resource_utils.get_account_id(request) if not is_staff(jwt) and account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) token = g.jwt_oidc_token_info current_app.logger.debug( f'Getting user profile for account {account_id} with token: {token}' ) # Try to fetch existing user from JWT. user = User.find_by_jwt_token(token, account_id) current_app.logger.debug( f'User profile query completed for account {account_id}.') if not user: # If user does not exist, create user and user profile with the default settings. current_app.logger.debug( f'No user found for {account_id} request token: creating records.' ) user = User.create_from_jwt_token(token, account_id) user.user_profile = UserProfile.create_from_json(None, user.id) user.user_profile.save() return user.user_profile.json, HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error current_app.logger.error( f'Get user profile {account_id} failed: ' + repr(default_exception)) return resource_utils.default_exception_response(default_exception)
def get(): """Get the list of draft statements belonging to the header account ID.""" try: # Quick check: must provide an account ID. account_id = get_account_id(request) if account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) # Try to fetch draft list for account ID draft_list = Draft.find_all_by_account_id(account_id) return jsonify(draft_list), HTTPStatus.OK except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def get(): """Get account search history.""" try: # Quick check: must have an account ID. account_id = resource_utils.get_account_id(request) if account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) # Try to fetch search history by account id. # No results throws a not found business exception. current_app.logger.info( f'Fetching search history for {account_id}.') history = SearchRequest.find_all_by_account_id(account_id) return jsonify(history), HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def put(search_id): """Execute a search selection update request replacing the current value with the request body contents.""" try: if search_id is None: return resource_utils.path_param_error_response('search ID') # Quick check: must be staff or provide an account ID. account_id = resource_utils.get_account_id(request) if account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Validate schema. valid_format, errors = schema_utils.validate( request_json, 'searchSummary', 'ppr') if not valid_format: return resource_utils.validation_error_response( errors, VAL_ERROR) search_request = SearchRequest.find_by_id(search_id) if not search_request: return resource_utils.not_found_error_response( 'searchId', search_id) # Save the updated search selection. search_request.update_search_selection(request_json) return jsonify( search_request.updated_selection), HTTPStatus.ACCEPTED except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def get(document_id): """Get a draft statement by document ID.""" try: if document_id is None: return path_param_error_response('document ID') # Quick check: must be staff or provide an account ID. account_id = get_account_id(request) if not is_staff(jwt) and account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) # Try to fetch draft statement by document ID draft = Draft.find_by_document_number(document_id, False) return draft.json, HTTPStatus.OK except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def delete(document_id): """Delete a draft statement by document ID.""" try: if document_id is None: return path_param_error_response('document ID') # Quick check: must be staff or provide an account ID. account_id = get_account_id(request) if not is_staff(jwt) and account_id is None: return account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return unauthorized_error_response(account_id) # Try to fetch draft statement by document ID Draft.delete(document_id) return '', HTTPStatus.NO_CONTENT except BusinessException as exception: return business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return default_exception_response(default_exception)
def get(search_id): """Get search detail information for a previous search.""" try: if search_id is None: return resource_utils.path_param_error_response('search ID') # Quick check: must have an account ID. account_id = resource_utils.get_account_id(request) if account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) # Try to fetch search detail by search id. current_app.logger.info(f'Fetching search detail for {search_id}.') search_detail = SearchResult.find_by_search_id(search_id, True) if not search_detail: return resource_utils.not_found_error_response( 'searchId', search_id) response_data = search_detail.json if resource_utils.is_pdf(request): token = g.jwt_oidc_token_info # Return report if request header Accept MIME type is application/pdf. return get_pdf(response_data, account_id, ReportTypes.SEARCH_DETAIL_REPORT.value, token['name']) return jsonify(response_data), HTTPStatus.OK except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def post(): # pylint: disable=too-many-branches """Execute a new search request using criteria in the request body.""" try: # Quick check: must be staff or provide an account ID. account_id = resource_utils.get_account_id(request) if not account_id: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Validate request against the schema. valid_format, errors = schema_utils.validate( request_json, 'searchQuery', 'ppr') if not valid_format: return resource_utils.validation_error_response( errors, VAL_ERROR) # Perform any extra data validation such as start and end dates here SearchRequest.validate_query(request_json) # Staff has special payment rules and setup. if is_staff_account(account_id) or is_bcol_help(account_id): return staff_search(request, request_json, account_id) query = SearchRequest.create_from_json( request_json, account_id, g.jwt_oidc_token_info.get('username', None)) # Charge a search fee. invoice_id = None payment = Payment(jwt=jwt.get_token_auth_header(), account_id=account_id, details=get_payment_details( query, request_json['type'])) pay_ref = payment.create_payment(TransactionTypes.SEARCH.value, 1, None, query.client_reference_id) invoice_id = pay_ref['invoiceId'] query.pay_invoice_id = int(invoice_id) query.pay_path = pay_ref['receipt'] # Execute the search query: treat no results as a success. try: query.search() # Now save the initial detail results in the search_result table with no # search selection criteria (the absence indicates an incomplete search). search_result = SearchResult.create_from_search_query(query) search_result.save() except Exception as db_exception: # noqa: B902; handle all db related errors. current_app.logger.error( SAVE_ERROR_MESSAGE.format(account_id, repr(db_exception))) if invoice_id is not None: current_app.logger.info( PAY_REFUND_MESSAGE.format(account_id, invoice_id)) try: payment.cancel_payment(invoice_id) except Exception as cancel_exception: # noqa: B902; log exception current_app.logger.error( PAY_REFUND_ERROR.format(account_id, invoice_id, repr(cancel_exception))) raise db_exception return query.json, HTTPStatus.CREATED except SBCPaymentException as pay_exception: return resource_utils.pay_exception_response(pay_exception) except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)
def post(): """Execute a new search request using criteria in the request body.""" try: # Quick check: must be staff or provide an account ID. account_id = resource_utils.get_account_id(request) if not is_staff(jwt) and account_id is None: return resource_utils.account_required_response() # Verify request JWT and account ID if not authorized(account_id, jwt): return resource_utils.unauthorized_error_response(account_id) request_json = request.get_json(silent=True) # Validate request against the schema. valid_format, errors = schema_utils.validate( request_json, 'searchQuery', 'ppr') if not valid_format: return resource_utils.validation_error_response( errors, VAL_ERROR) # Perform any extra data validation such as start and end dates here SearchClient.validate_query(request_json) query = SearchClient.create_from_json(request_json, account_id) # Charge a search fee. if account_id: payment = Payment(jwt=jwt.get_token_auth_header(), account_id=account_id) pay_ref = payment.create_payment(TransactionTypes.SEARCH.value, 1, None, query.client_reference_id) invoice_id = pay_ref['invoiceId'] query.pay_invoice_id = int(invoice_id) query.pay_path = pay_ref['receipt'] # Execute the search query: treat no results as a success. try: query.search() # if not query.search_response or query.returned_results_size == 0: # return resource_utils.unprocessable_error_response('search query') # Now save the initial detail results in the search_result table with no # search selection criteria (the absence indicates an incomplete search). search_result = SearchResult.create_from_search_query(query) search_result.save() except Exception as db_exception: # noqa: B902; handle all db related errors. current_app.logger.error( f'Search {account_id} db save failed: ' + repr(db_exception)) current_app.logger.error( f'Search {account_id} rolling back payment for invoice {invoice_id}.' ) try: payment.cancel_payment(invoice_id) except Exception as cancel_exception: # noqa: B902; log exception current_app.logger.error( f'Search {account_id} payment refund failed for invoice {invoice_id}: ' + repr(cancel_exception)) raise db_exception return query.json, HTTPStatus.CREATED except SBCPaymentException as pay_exception: return resource_utils.pay_exception_response(pay_exception) except BusinessException as exception: return resource_utils.business_exception_response(exception) except Exception as default_exception: # noqa: B902; return nicer default error return resource_utils.default_exception_response(default_exception)