Skip to content

Instantly share code, notes, and snippets.

@freelancing-solutions
Created April 22, 2021 14:07
Show Gist options
  • Save freelancing-solutions/d3626616eb5fbc27ab3492d6d2dfae52 to your computer and use it in GitHub Desktop.
Save freelancing-solutions/d3626616eb5fbc27ab3492d6d2dfae52 to your computer and use it in GitHub Desktop.
affiliates module with flask and python 3.8
import typing
from google.cloud import ndb
from flask import current_app, jsonify
from google.cloud.ndb.exceptions import BadRequestError, BadQueryError
from google.api_core.exceptions import Aborted, RetryError
from data_service.main import cache_stock_buys_sells
from data_service.store.affiliates import AffiliatesValidators as ValidAffiliate
from data_service.store.affiliates import RecruitsValidators as ValidRecruit
from data_service.store.affiliates import EarningsValidators as ValidEarnings
from data_service.store.affiliates import Affiliates, AffiliateSettings, Recruits, EarningsClass
from data_service.store.exceptions import DataServiceError
from data_service.utils.utils import create_id, return_ttl, end_of_month
from data_service.views.context_utils import use_context
class Validator(ValidAffiliate, ValidRecruit, ValidEarnings):
@staticmethod
def can_register_affiliate(self, uid: str) -> bool:
already_registered: bool = self.user_already_registered(uid=uid)
if not isinstance(already_registered, bool):
raise ValueError("invalid user id")
return not already_registered
class AffiliatesView(Validator):
"""
Register new affiliates using this class
"""
def __init__(self):
super(AffiliatesView, self).__init__()
self._max_retries = current_app.config.get('DATASTORE_RETRIES')
self._max_timeout = current_app.config.get('DATASTORE_TIMEOUT')
@use_context
def register_affiliate(self, affiliate_data: dict) -> tuple:
"""
Register new affiliate
"""
uid: typing.Union[None, str] = affiliate_data.get('uid')
if uid is None or uid == "":
return jsonify({'status': False, 'message': 'user id cannot be Null'}), 500
if self.can_register_affiliate(uid=uid) is True:
try:
affiliate_instance: Affiliates = Affiliates(affiliate_id=create_id(), uid=uid)
key = affiliate_instance.put(use_cache=True, retries=self._max_retries, timeout=self._max_timeout)
if key is None:
message: str = "There was an error creating Affiliate"
raise DataServiceError(message)
return jsonify({'status': True,
'message': 'successfully registered an affiliate',
'payload': affiliate_instance.to_dict()}), 200
except BadRequestError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except BadQueryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except ConnectionRefusedError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except RetryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except Aborted as e:
return jsonify({'status': False, 'message': str(e)}), 500
else:
return jsonify({'status': False, 'message': 'User already registered as an Affiliate'}), 500
@use_context
def increment_total_recruits(self, affiliate_data: dict) -> tuple:
"""
update an existing affiliate
"""
affiliate_id = affiliate_data.get('affiliate_id')
if affiliate_id is None or affiliate_id == "":
return jsonify({'status': False, 'message': 'affiliate_id is required'}), 500
try:
affiliate_list: typing.List[Affiliates] = Affiliates.query(Affiliates.affiliate_id == affiliate_id).fetch()
if isinstance(affiliate_list, list) and len(affiliate_list) > 0:
affiliate_instance = affiliate_list[0]
affiliate_instance.total_recruits += 1
key = affiliate_instance.put(use_cache=True, retries=self._max_retries, timeout=self._max_timeout)
if key is None:
message: str = "Something went wrong while updating affiliate"
raise DataServiceError(message)
return jsonify({'status': True,
'message': 'successfully incremented total recruits',
'payload': affiliate_instance.to_dict()}), 200
else:
return jsonify({'status': False, 'message': 'Failed to locate affiliate'}), 500
except BadRequestError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except BadQueryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except ConnectionRefusedError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except RetryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except Aborted as e:
return jsonify({'status': False, 'message': str(e)}), 500
@use_context
def delete_affiliate(self, affiliate_data: dict) -> tuple:
"""
delete affiliate
azwifarwi justice
"""
affiliate_id: typing.Union[None, str] = affiliate_data.get('affiliate_id')
if affiliate_id is None or affiliate_id == "":
return jsonify({'status': False, 'message': 'affiliate_id is required'}), 500
try:
affiliates_list: typing.List[Affiliates] = Affiliates.query(Affiliates.affiliate_id == affiliate_id).fetch()
if isinstance(affiliates_list, list) and len(affiliates_list) > 0:
affiliate_instance = affiliates_list[0]
affiliate_instance.is_active = False
affiliate_instance.is_deleted = True
key = affiliate_instance.put(use_cache=True, retries=self._max_retries, timeout=self._max_timeout)
if key is None:
message: str = 'something went wrong while deleting affiliate'
return jsonify({'status': False, 'message': message}), 500
return jsonify({'status': True,
'message': 'successfully deleted the affiliate',
'payload': affiliate_instance.to_dict()}), 200
else:
return jsonify({'status': False, 'message': 'error locating that affiliate'}), 500
except BadRequestError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except BadQueryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except ConnectionRefusedError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except RetryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except Aborted as e:
return jsonify({'status': False, 'message': str(e)}), 500
@use_context
def mark_active(self, affiliate_data: dict, is_active: bool) -> tuple:
"""
mark a specific affiliate as active or not active
"""
affiliate_id: typing.Union[None, str] = affiliate_data.get('affiliate_id')
if affiliate_id is None or affiliate_id == "":
return jsonify({'status': False, 'message': 'affiliate_id is required'}), 500
if not isinstance(is_active, bool):
raise ValueError("is_active is required and can only be a boolean")
try:
affiliates_list: typing.List[Affiliates] = Affiliates.query(Affiliates.affiliate_id == affiliate_id).fetch()
if isinstance(affiliates_list, list) and len(affiliates_list) > 0:
affiliate_instance: Affiliates = affiliates_list[0]
affiliate_instance.is_active = is_active
key = affiliate_instance.put(use_cache=True, retries=self._max_retries, timeout=self._max_timeout)
if key is None:
message: str = "An Unknown Error occurred while trying to mark affiliate as in-active"
return jsonify({'status': False, 'message': message}), 500
return jsonify({'status': True, 'message': 'successfully marked affiliate as inactive',
'payload': affiliate_instance.to_dict()}), 200
else:
message: str = "Unable to locate affiliate record"
return jsonify({'status': False, 'message': message}), 500
except BadRequestError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except BadQueryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except ConnectionRefusedError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except RetryError as e:
return jsonify({'status': False, 'message': str(e)}), 500
except Aborted as e:
return jsonify({'status': False, 'message': str(e)}), 500
@cache_stock_buys_sells.cached(timeout=return_ttl(name='medium'), unless=end_of_month)
@use_context
def get_affiliate(self, affiliate_data: dict) -> tuple:
"""
with affiliate_id or uid return affiliate
"""
affiliate_id: typing.Union[None, str] = affiliate_data.get('affiliate_id')
uid: typing.Union[None, str] = affiliate_data.get('uid')
if (uid is None) and (affiliate_id is None):
return jsonify({'status': False, 'message': 'uid or affiliate_id is required to fetch affiliate'}), 500
try:
if uid is not None:
affiliates_list: typing.List[Affiliates] = Affiliates.query(Affiliates.uid == uid).fetch()
else:
affiliates_list: typing.List[Affiliates] = Affiliates.query(
Affiliates.affiliate_id == affiliate_id).fetch()
except ConnectionRefusedError as e:
message: str = str(e)
return jsonify({'status': False, 'message': message}), 500
except RetryError as e:
message: str = str(e.message or e)
return jsonify({'status': False, 'message': message}), 500
except Aborted as e:
message: str = str(e.message or e)
return jsonify({'status': False, 'message': message}), 500
if isinstance(affiliates_list, list) and len(affiliates_list) > 0:
affiliate_instance: Affiliates = affiliates_list[0]
return jsonify({'status': True,
'message': 'successfully obtained affiliate data',
'payload': affiliate_instance.to_dict()}), 200
else:
return jsonify({'status': False, 'message': 'unable to locate affiliate'}), 500
@cache_stock_buys_sells.cached(timeout=return_ttl(name='medium'), unless=end_of_month)
@use_context
def get_all_affiliates(self) -> tuple:
"""
return all affiliates
"""
affiliates_list: typing.List[Affiliates] = Affiliates.query().fetch()
payload = [affiliate.to_dict() for affiliate in affiliates_list]
return jsonify({'status': True, 'message': 'Successfully returned all affiliates',
'payload': payload}), 200
@cache_stock_buys_sells.cached(timeout=return_ttl(name='medium'), unless=end_of_month)
@use_context
def get_active_affiliates(self) -> tuple:
"""
return affiliates who are not deleted and are active
"""
affiliates_list: typing.List[Affiliates] = Affiliates.query(
Affiliates.is_active == True, Affiliates.is_deleted == False).fetch()
payload = [affiliate.to_dict() for affiliate in affiliates_list]
return jsonify({'status': True, 'message': 'successfully returned all affiliates',
'payload': payload}), 200
@cache_stock_buys_sells.cached(timeout=return_ttl(name='medium'), unless=end_of_month)
@use_context
def get_in_active_affiliates(self) -> tuple:
"""
return affiliates who are not active
"""
affiliates_list: typing.List[Affiliates] = Affiliates.query(
Affiliates.is_active == False, Affiliates.is_deleted == False).fetch()
payload = [affiliate.to_dict() for affiliate in affiliates_list]
return jsonify({'status': True, 'message': 'successfully returned all affiliates',
'payload': payload}), 200
@cache_stock_buys_sells.cached(timeout=return_ttl(name='medium'), unless=end_of_month)
@use_context
def get_deleted_affiliates(self) -> tuple:
"""
return affiliates who are not active
"""
affiliates_list: typing.List[Affiliates] = Affiliates.query(Affiliates.is_deleted == True).fetch()
payload = [affiliate.to_dict() for affiliate in affiliates_list]
return jsonify({'status': True, 'message': 'Successfully returned all affiliates',
'payload': payload}), 200
class RecruitsView(Validator):
"""
Used by affiliates to register newly recruited members
"""
def __init__(self):
super(RecruitsView, self).__init__()
self._max_retries = current_app.config.get('DATASTORE_RETRIES')
self._max_timeout = current_app.config.get('DATASTORE_TIMEOUT')
@use_context
def add_recruit(self, recruit_data: dict) -> tuple:
"""
recruit_data: dict
"""
referrer_uid: typing.Union[None, str] = recruit_data.get('referrer_uid')
if referrer_uid is None or referrer_uid == "":
return jsonify({'status': False, 'message': 'referrer uid is required'}), 200
# TODO - check if i can add recruit
recruit_instance: Recruits = Recruits(affiliate_id=create_id(), referrer_uid=referrer_uid)
key = recruit_instance.put(use_cache=True, retries=self._max_retries, timeout=self._max_timeout)
if key is None:
message: str = "An Error occurred while adding new recruit"
return jsonify({'status': False, 'message': message}), 500
return jsonify({'status': True, 'message': 'Successfully created new recruit',
'payload': recruit_instance.to_dict()}), 200
@use_context
def delete_recruit(self, recruit_data: dict) -> tuple:
affiliate_id: str = recruit_data.get('affiliate_id')
if affiliate_id is None or affiliate_id == "":
return jsonify({'status': False, 'message': 'affiliate_id is required'}), 500
recruits_list: typing.List[Recruits] = Recruits.query(Recruits.affiliate_id == affiliate_id).fetch()
if isinstance(recruits_list, list) and len(recruits_list) > 0:
recruits_instance = recruits_list[0]
recruits_instance.is_deleted = True
recruits_instance.is_active = False
key = recruits_instance.put(use_cache=True, retries=self._max_retries, timeout=self._max_timeout)
if key is None:
message: str = "An Error occurred while deleting recruit"
return jsonify({'status': False, 'message': message}), 500
return jsonify({'status': True, 'message': 'Successfully deleted recruit'}), 200
else:
message: str = "Recruit does not exist"
return jsonify({'status': False, 'message': message}), 500
@use_context
def mark_active(self, recruit_data: dict, is_active: bool) -> tuple:
affiliate_id: str = recruit_data.get('affiliate_id')
if affiliate_id is None or affiliate_id == "":
return jsonify({'status': False, 'message': 'affiliate_id is required'}), 500
if not isinstance(is_active, bool):
return jsonify({'status': False, 'message': 'is_active is required and can only be a boolean'}), 500
recruits_list: typing.List[Recruits] = Recruits.query(Recruits.affiliate_id == affiliate_id).fetch()
if isinstance(recruits_list, list) and len(recruits_list) > 0:
recruits_instance: Recruits = recruits_list[0]
recruits_instance.is_active = is_active
key = recruits_instance.put(use_cache=True, retries=self._max_retries, timeout=self._max_timeout)
if key is None:
message: str = "An Error occurred while changing recruit active status"
return jsonify({'status': False, 'message': message}), 500
return jsonify({'status': True, 'message': 'Successfully deleted recruit'}), 200
else:
message: str = "Recruit does not exist"
return jsonify({'status': False, 'message': message}), 500
@use_context
def get_recruit(self, recruit_data: dict) -> tuple:
affiliate_id: str = recruit_data.get('affiliate_id')
if affiliate_id is None or affiliate_id == "":
return jsonify({'status': False, 'message': 'affiliate_id is required'}), 500
recruits_list: typing.List[Recruits] = Recruits.query(Recruits.affiliate_id == affiliate_id).fetch()
if isinstance(recruits_list, list) and len(recruits_list) > 0:
recruit_instance: Recruits = recruits_list[0]
message: str = "Successfully retrieved recruit"
return jsonify({'status': True, 'payload': recruit_instance.to_dict(), 'message': message}), 200
else:
message: str = "Recruit does not exist"
return jsonify({'status': False, 'message': message}), 500
@use_context
def get_recruits_by_active_status(self, is_active: bool) -> tuple:
if not isinstance(is_active, bool):
return jsonify({'status': False, 'message': 'is_active status is required'}), 500
recruits_list: typing.List[Recruits] = Recruits.query(Recruits.is_active == is_active).fetch()
payload = [recruit.to_dict() for recruit in recruits_list]
message: str = "{} recruits successfully fetched recruits by active status".format(str(len(recruits_list)))
return jsonify({'status': True, 'message': message, 'payload': payload}), 200
@use_context
def get_recruits_by_deleted_status(self, is_deleted: bool) -> tuple:
if not isinstance(is_deleted, bool):
return jsonify({'status': False, 'message': 'is_deleted status is required'}), 500
recruits_list: typing.List[Recruits] = Recruits.query(Recruits.is_deleted == is_deleted).fetch()
payload = [recruit.to_dict() for recruit in recruits_list]
message: str = "{} recruits successfully fetched recruits by deleted status".format(str(len(recruits_list)))
return jsonify({'status': True, 'message': message, 'payload': payload}), 200
@use_context
def get_recruits_by_affiliate(self, affiliate_data: dict) -> tuple:
referrer_uid: str = affiliate_data.get('referrer_uid')
if referrer_uid is None or referrer_uid == "":
return jsonify({'status': False, 'message': 'referrer_uid is required'}), 500
recruits_list: typing.List[Recruits] = Recruits.query(Recruits.referrer_uid == referrer_uid).fetch()
payload = [recruit.to_dict() for recruit in recruits_list]
message: str = "{} recruits successfully fetched recruits by active status".format(str(len(recruits_list)))
return jsonify({'status': True, 'message': message, 'payload': payload}), 200
@use_context
def get_recruits_by_active_and_affiliate(self, affiliate_data: dict, is_active: bool) -> tuple:
referrer_uid: str = affiliate_data.get('referrer_uid')
if referrer_uid is None or referrer_uid == "":
return jsonify({'status': False, 'message': 'referrer_uid is required'}), 500
if isinstance(is_active, bool):
return jsonify({'status': False, 'message': 'is_active status can only be a boolean'}), 500
recruits_list: typing.List[Recruits] = Recruits.query(Recruits.referrer_uid == referrer_uid,
Recruits.is_active == is_active).fetch()
payload = [recruit.to_dict() for recruit in recruits_list]
message: str = "{} recruits successfully fetched affiliate recruits by status".format(str(len(recruits_list)))
return jsonify({'status': True, 'message': message, 'payload': payload}), 200
class EarningsView(Validator):
"""
Used by system to register new earnings for affiliates
"""
def __init__(self):
super(EarningsView, self).__init__()
self.client = ndb.Client(namespace="main", project=current_app.config.get('PROJECT'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment