Remove submodule cic ussd
This commit is contained in:
16
apps/cic-ussd/cic_ussd/state_machine/logic/__init__.py
Normal file
16
apps/cic-ussd/cic_ussd/state_machine/logic/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# standard imports
|
||||
import os
|
||||
import re
|
||||
from glob import glob
|
||||
from importlib import import_module
|
||||
from os.path import basename, dirname, isfile, join
|
||||
|
||||
# get all modules in the directory
|
||||
modules = glob(join(dirname(__file__), "*.py"))
|
||||
|
||||
for file in modules:
|
||||
# exclude 'init.py'
|
||||
if isfile(file) and not re.match(r'^__', os.path.basename(file)):
|
||||
# strip .py extension
|
||||
file_name = basename(file[:-3])
|
||||
import_module("." + file_name, package=__name__)
|
||||
20
apps/cic-ussd/cic_ussd/state_machine/logic/balance.py
Normal file
20
apps/cic-ussd/cic_ussd/state_machine/logic/balance.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# standard imports
|
||||
import logging
|
||||
from typing import Tuple
|
||||
|
||||
# third-party imports
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import User
|
||||
|
||||
logg = logging.getLogger(__file__)
|
||||
|
||||
|
||||
def process_mini_statement_request(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function compiles a brief statement of a user's last three inbound and outbound transactions and send the
|
||||
same as a message on their selected avenue for notification.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('This section requires integration with cic-eth. (The last 6 transactions would be sent as an sms.)')
|
||||
90
apps/cic-ussd/cic_ussd/state_machine/logic/menu.py
Normal file
90
apps/cic-ussd/cic_ussd/state_machine/logic/menu.py
Normal file
@@ -0,0 +1,90 @@
|
||||
"""This module defines functions responsible for interaction with the ussd menu. It takes user input and navigates the
|
||||
ussd menu facilitating the return of appropriate menu responses based on said user input.
|
||||
"""
|
||||
|
||||
# standard imports
|
||||
from typing import Tuple
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import User
|
||||
|
||||
|
||||
def menu_one_selected(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks that user input matches a string with value '1'
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
:return: A user input's match with '1'
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user_input == '1'
|
||||
|
||||
|
||||
def menu_two_selected(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks that user input matches a string with value '2'
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user input's match with '2'
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user_input == '2'
|
||||
|
||||
|
||||
def menu_three_selected(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks that user input matches a string with value '3'
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user input's match with '3'
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user_input == '3'
|
||||
|
||||
|
||||
def menu_four_selected(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""
|
||||
This function checks that user input matches a string with value '4'
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user input's match with '4'
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user_input == '4'
|
||||
|
||||
|
||||
def menu_five_selected(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""
|
||||
This function checks that user input matches a string with value '5'
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user input's match with '5'
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user_input == '5'
|
||||
|
||||
|
||||
def menu_zero_zero_selected(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""
|
||||
This function checks that user input matches a string with value '00'
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user input's match with '00'
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user_input == '00'
|
||||
|
||||
|
||||
def menu_ninety_nine_selected(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""
|
||||
This function checks that user input matches a string with value '99'
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user input's match with '99'
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user_input == '99'
|
||||
143
apps/cic-ussd/cic_ussd/state_machine/logic/pin.py
Normal file
143
apps/cic-ussd/cic_ussd/state_machine/logic/pin.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""This module defines functions responsible for creation, validation, reset and any other manipulations on the
|
||||
user's pin.
|
||||
"""
|
||||
|
||||
# standard imports
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
# third party imports
|
||||
import bcrypt
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import AccountStatus, User
|
||||
from cic_ussd.encoder import PasswordEncoder, create_password_hash
|
||||
from cic_ussd.operations import persist_session_to_db_task, create_or_update_session
|
||||
from cic_ussd.redis import InMemoryStore
|
||||
|
||||
|
||||
logg = logging.getLogger(__file__)
|
||||
|
||||
|
||||
def is_valid_pin(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks a pin's validity by ensuring it has a length of for characters and the characters are
|
||||
numeric.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A pin's validity
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
pin_is_valid = False
|
||||
matcher = r'^\d{4}$'
|
||||
if re.match(matcher, user_input):
|
||||
pin_is_valid = True
|
||||
return pin_is_valid
|
||||
|
||||
|
||||
def is_authorized_pin(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks whether the user input confirming a specific pin matches the initial pin entered.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A match between two pin values.
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user.verify_password(password=user_input)
|
||||
|
||||
|
||||
def is_locked_account(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks whether a user's account is locked due to too many failed attempts.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A match between two pin values.
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user.get_account_status() == AccountStatus.LOCKED.name
|
||||
|
||||
|
||||
def save_initial_pin_to_session_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function hashes a pin and stores it in session data.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
|
||||
# define redis cache entry point
|
||||
cache = InMemoryStore.cache
|
||||
|
||||
# get external session id
|
||||
external_session_id = ussd_session.get('external_session_id')
|
||||
|
||||
# get corresponding session record
|
||||
in_redis_ussd_session = cache.get(external_session_id)
|
||||
in_redis_ussd_session = json.loads(in_redis_ussd_session)
|
||||
|
||||
# set initial pin data
|
||||
initial_pin = create_password_hash(user_input)
|
||||
session_data = {
|
||||
'initial_pin': initial_pin
|
||||
}
|
||||
|
||||
# create new in memory ussd session with current ussd session data
|
||||
create_or_update_session(
|
||||
external_session_id=external_session_id,
|
||||
phone=in_redis_ussd_session.get('msisdn'),
|
||||
service_code=in_redis_ussd_session.get('service_code'),
|
||||
user_input=user_input,
|
||||
current_menu=in_redis_ussd_session.get('state'),
|
||||
session_data=session_data
|
||||
)
|
||||
persist_session_to_db_task(external_session_id=external_session_id, queue='cic-ussd')
|
||||
|
||||
|
||||
def pins_match(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks whether the user input confirming a specific pin matches the initial pin entered.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A match between two pin values.
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
initial_pin = ussd_session.get('session_data').get('initial_pin')
|
||||
fernet = PasswordEncoder(PasswordEncoder.key)
|
||||
initial_pin = fernet.decrypt(initial_pin.encode())
|
||||
return bcrypt.checkpw(user_input.encode(), initial_pin)
|
||||
|
||||
|
||||
def complete_pin_change(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function persists the user's pin to the database
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
password_hash = ussd_session.get('session_data').get('initial_pin')
|
||||
user.password_hash = password_hash
|
||||
User.session.add(user)
|
||||
User.session.commit()
|
||||
|
||||
|
||||
def is_blocked_pin(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks whether the user input confirming a specific pin matches the initial pin entered.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A match between two pin values.
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
return user.get_account_status() == AccountStatus.LOCKED.name
|
||||
|
||||
|
||||
def is_valid_new_pin(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks whether the user's new pin is a valid pin and that it isn't the same as the old one.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A match between two pin values.
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
is_old_pin = user.verify_password(password=user_input)
|
||||
return is_valid_pin(state_machine_data=state_machine_data) and not is_old_pin
|
||||
23
apps/cic-ussd/cic_ussd/state_machine/logic/sms.py
Normal file
23
apps/cic-ussd/cic_ussd/state_machine/logic/sms.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# standard imports
|
||||
import logging
|
||||
from typing import Tuple
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import User
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def send_terms_to_user_if_required(state_machine_data: Tuple[str, dict, User]):
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('Requires integration to cic-notify.')
|
||||
|
||||
|
||||
def process_mini_statement_request(state_machine_data: Tuple[str, dict, User]):
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('Requires integration to cic-notify.')
|
||||
|
||||
|
||||
def upsell_unregistered_recipient(state_machine_data: Tuple[str, dict, User]):
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('Requires integration to cic-notify.')
|
||||
119
apps/cic-ussd/cic_ussd/state_machine/logic/transaction.py
Normal file
119
apps/cic-ussd/cic_ussd/state_machine/logic/transaction.py
Normal file
@@ -0,0 +1,119 @@
|
||||
# standard imports
|
||||
import logging
|
||||
from typing import Tuple
|
||||
|
||||
# third party imports
|
||||
|
||||
# local imports
|
||||
from cic_ussd.accounts import BalanceManager
|
||||
from cic_ussd.db.models.user import AccountStatus, User
|
||||
from cic_ussd.operations import get_user_by_phone_number, save_to_in_memory_ussd_session_data
|
||||
from cic_ussd.state_machine.state_machine import UssdStateMachine
|
||||
from cic_ussd.transactions import OutgoingTransactionProcessor
|
||||
|
||||
|
||||
logg = logging.getLogger(__file__)
|
||||
|
||||
|
||||
def is_valid_recipient(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks that a user exists, is not the initiator of the transaction, has an active account status
|
||||
and is authorized to perform standard transactions.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user's validity
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
recipient = get_user_by_phone_number(phone_number=user_input)
|
||||
is_not_initiator = user_input != user.phone_number
|
||||
has_active_account_status = user.get_account_status() == AccountStatus.ACTIVE.name
|
||||
logg.debug('This section requires implementation of checks for user roles and authorization status of an account.')
|
||||
return is_not_initiator and has_active_account_status
|
||||
|
||||
|
||||
def is_valid_token_agent(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks that a user exists, is not the initiator of the transaction, has an active account status
|
||||
and is authorized to perform exchange transactions.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A user's validity
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
# is_token_agent = AccountRole.TOKEN_AGENT.value in user.get_user_roles()
|
||||
logg.debug('This section requires implementation of user roles and authorization to facilitate exchanges.')
|
||||
return is_valid_recipient(state_machine_data=state_machine_data)
|
||||
|
||||
|
||||
def is_valid_transaction_amount(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks that the transaction amount provided is valid as per the criteria for the transaction
|
||||
being attempted.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: A transaction amount's validity
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
try:
|
||||
return int(user_input) > 0
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def has_sufficient_balance(state_machine_data: Tuple[str, dict, User]) -> bool:
|
||||
"""This function checks that the transaction amount provided is valid as per the criteria for the transaction
|
||||
being attempted.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
:return: An account balance's validity
|
||||
:rtype: bool
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
balance_manager = BalanceManager(address=user.blockchain_address,
|
||||
chain_str=UssdStateMachine.chain_str,
|
||||
token_symbol='SRF')
|
||||
balance = balance_manager.get_operational_balance()
|
||||
return int(user_input) <= balance
|
||||
|
||||
|
||||
def save_recipient_phone_to_session_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function saves the phone number corresponding the intended recipients blockchain account.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
session_data = {
|
||||
'recipient_phone_number': user_input
|
||||
}
|
||||
save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session)
|
||||
|
||||
|
||||
def save_transaction_amount_to_session_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function saves the phone number corresponding the intended recipients blockchain account.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
session_data = {
|
||||
'transaction_amount': user_input
|
||||
}
|
||||
save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session)
|
||||
|
||||
|
||||
def process_transaction_request(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function saves the phone number corresponding the intended recipients blockchain account.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
|
||||
# get user from phone number
|
||||
recipient_phone_number = ussd_session.get('session_data').get('recipient_phone_number')
|
||||
recipient = get_user_by_phone_number(phone_number=recipient_phone_number)
|
||||
to_address = recipient.blockchain_address
|
||||
from_address = user.blockchain_address
|
||||
amount = int(ussd_session.get('session_data').get('transaction_amount'))
|
||||
outgoing_tx_processor = OutgoingTransactionProcessor(chain_str=UssdStateMachine.chain_str,
|
||||
from_address=from_address,
|
||||
to_address=to_address)
|
||||
outgoing_tx_processor.process_outgoing_transfer_transaction(amount=amount)
|
||||
89
apps/cic-ussd/cic_ussd/state_machine/logic/user.py
Normal file
89
apps/cic-ussd/cic_ussd/state_machine/logic/user.py
Normal file
@@ -0,0 +1,89 @@
|
||||
# standard imports
|
||||
import logging
|
||||
from typing import Tuple
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import User
|
||||
from cic_ussd.operations import save_to_in_memory_ussd_session_data
|
||||
|
||||
logg = logging.getLogger(__file__)
|
||||
|
||||
|
||||
def change_preferred_language_to_en(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function changes the user's preferred language to english.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
user.preferred_language = 'en'
|
||||
User.session.add(user)
|
||||
User.session.commit()
|
||||
|
||||
|
||||
def change_preferred_language_to_sw(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function changes the user's preferred language to swahili.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
user.preferred_language = 'sw'
|
||||
User.session.add(user)
|
||||
User.session.commit()
|
||||
|
||||
|
||||
def update_account_status_to_active(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function sets user's account to active.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
user.activate_account()
|
||||
User.session.add(user)
|
||||
User.session.commit()
|
||||
|
||||
|
||||
def save_profile_attribute_to_session_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function saves first name data to the ussd session in the redis cache.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
|
||||
# get current menu
|
||||
current_state = ussd_session.get('state')
|
||||
|
||||
# define session data key from current state
|
||||
key = ''
|
||||
if 'first_name' in current_state:
|
||||
key = 'first_name'
|
||||
elif 'last_name' in current_state:
|
||||
key = 'last_name'
|
||||
elif 'gender' in current_state:
|
||||
key = 'gender'
|
||||
elif 'location' in current_state:
|
||||
key = 'location'
|
||||
elif 'business_profile' in current_state:
|
||||
key = 'business_profile'
|
||||
|
||||
# check if there is existing session data
|
||||
if ussd_session.get('session_data'):
|
||||
session_data = ussd_session.get('session_data')
|
||||
session_data[key] = user_input
|
||||
else:
|
||||
session_data = {
|
||||
key: user_input
|
||||
}
|
||||
save_to_in_memory_ussd_session_data(queue='cic-ussd', session_data=session_data, ussd_session=ussd_session)
|
||||
|
||||
|
||||
def persist_profile_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function persists elements of the user profile stored in session data
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: tuple
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
|
||||
# get session data
|
||||
profile_data = ussd_session.get('session_data')
|
||||
logg.debug('This section requires implementation of user metadata.')
|
||||
|
||||
68
apps/cic-ussd/cic_ussd/state_machine/logic/validator.py
Normal file
68
apps/cic-ussd/cic_ussd/state_machine/logic/validator.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# standard imports
|
||||
import logging
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import User
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
def has_complete_profile_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function checks whether the attributes of the user's metadata constituting a profile are filled out.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('This section requires implementation of user metadata.')
|
||||
|
||||
|
||||
def has_empty_username_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function checks whether the aspects of the user's name metadata is filled out.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('This section requires implementation of user metadata.')
|
||||
|
||||
|
||||
def has_empty_gender_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function checks whether the aspects of the user's gender metadata is filled out.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('This section requires implementation of user metadata.')
|
||||
|
||||
|
||||
def has_empty_location_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function checks whether the aspects of the user's location metadata is filled out.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('This section requires implementation of user metadata.')
|
||||
|
||||
|
||||
def has_empty_business_profile_data(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function checks whether the aspects of the user's business profile metadata is filled out.
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
logg.debug('This section requires implementation of user metadata.')
|
||||
|
||||
|
||||
def is_valid_name(state_machine_data: Tuple[str, dict, User]):
|
||||
"""This function checks that a user provided name is valid
|
||||
:param state_machine_data: A tuple containing user input, a ussd session and user object.
|
||||
:type state_machine_data: str
|
||||
"""
|
||||
user_input, ussd_session, user = state_machine_data
|
||||
name_matcher = "^[a-zA-Z]+$"
|
||||
valid_name = re.match(name_matcher, user_input)
|
||||
if valid_name:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
Reference in New Issue
Block a user