Skip to content

Commit

Permalink
Onboarding Changes (#1590)
Browse files Browse the repository at this point in the history
* Added code related to onboarding status and onboarding timestamp and added few test cases related to the same.

* Added code related to onboarding status and onboarding timestamp and added few test cases related to the same.

* Added code related to onboarding status and onboarding timestamp and added few test cases related to the same.

* Added code related to onboarding status and onboarding timestamp and added few test cases related to the same.

* Added code related to onboarding status and onboarding timestamp and added few test cases related to the same.

* Added code related to onboarding status and onboarding timestamp and added few test cases related to the same.
  • Loading branch information
maheshsattala authored Nov 6, 2024
1 parent 25efad2 commit e58b75a
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 8 deletions.
8 changes: 5 additions & 3 deletions kairon/api/app/routers/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ async def get_users_details(current_user: User = Depends(Authentication.get_curr
return {"data": {"user": user_details}}


@router.post("/details", response_model=Response)
async def update_users_details(current_user: User = Depends(Authentication.get_current_user)):
@router.post("/details/{status}", response_model=Response)
async def update_user_details(
status: str = Path(description="user onboarding status", examples=["Completed", "Skipped"]),
current_user: User = Depends(Authentication.get_current_user)):
"""
Updates the details of the current logged-in user.
"""
AccountProcessor.update_is_onboarded(current_user.email)
AccountProcessor.update_user_details(current_user.email, status)
return {"message": "Details updated!"}


Expand Down
7 changes: 6 additions & 1 deletion kairon/shared/account/data_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from kairon.shared.constants import UserActivityType
from kairon.shared.data.audit.data_objects import Auditlog
from kairon.shared.data.signals import push_notification, auditlogger
from kairon.shared.data.constant import ACCESS_ROLES, ACTIVITY_STATUS
from kairon.shared.data.constant import ACCESS_ROLES, ACTIVITY_STATUS, ONBOARDING_STATUS
from kairon.shared.utils import Utility


Expand Down Expand Up @@ -49,6 +49,9 @@ class User(Auditlog):
account = LongField(required=True)
user = StringField(required=True)
is_onboarded = BooleanField(default=False)
onboarding_status = StringField(default=ONBOARDING_STATUS.NOT_COMPLETED.value,
choices=[a_type.value for a_type in ONBOARDING_STATUS])
onboarding_timestamp = DateTimeField(default=None)
timestamp = DateTimeField(default=datetime.utcnow)
status = BooleanField(default=True)
meta = {"indexes": [{"fields": ["$email", "$first_name", "$last_name"]}]}
Expand All @@ -65,6 +68,8 @@ def validate(self, clean=True):
)
elif isinstance(email(self.email), ValidationFailure):
raise ValidationError("Please enter valid email address")
elif self.onboarding_status not in [status.value for status in ONBOARDING_STATUS]:
raise ValidationError(f"{self.onboarding_status} is not a valid status")


class BotMetaData(EmbeddedDocument):
Expand Down
9 changes: 6 additions & 3 deletions kairon/shared/account/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from kairon.shared.admin.processor import Sysadmin
from kairon.shared.constants import UserActivityType, PluginTypes
from kairon.shared.data.audit.data_objects import AuditLogData
from kairon.shared.data.constant import ACCESS_ROLES, ACTIVITY_STATUS, INTEGRATION_STATUS
from kairon.shared.data.constant import ACCESS_ROLES, ACTIVITY_STATUS, INTEGRATION_STATUS, ONBOARDING_STATUS
from kairon.shared.data.data_objects import BotSettings, ChatClientConfig, SlotMapping
from kairon.shared.plugins.factory import PluginFactory
from kairon.shared.utils import Utility
Expand Down Expand Up @@ -785,10 +785,13 @@ def get_complete_user_details(email: str):
return user

@staticmethod
def update_is_onboarded(email: Text):
def update_user_details(email: Text, status: Text):
try:
user = User.objects(email__iexact=email, status=True).get()
user.is_onboarded = True
if status in [ONBOARDING_STATUS.COMPLETED.value, ONBOARDING_STATUS.SKIPPED.value]:
user.is_onboarded = True
user.onboarding_status = status
user.onboarding_timestamp = datetime.utcnow()
user.save()
except DoesNotExist as e:
logging.error(e)
Expand Down
7 changes: 7 additions & 0 deletions kairon/shared/data/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ class EVENT_STATUS(str, Enum):
ABORTED = "Aborted"


class ONBOARDING_STATUS(str, Enum):
NOT_COMPLETED = "Not Completed"
SKIPPED = "Skipped"
IN_PROGRESS = "In Progress"
COMPLETED = "Completed"


class TASK_TYPE(str, Enum):
ACTION = "Action"
EVENT = "Event"
Expand Down
138 changes: 137 additions & 1 deletion tests/integration_test/services_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2688,6 +2688,142 @@ def test_get_executor_logs(get_executor_logs):
assert actual["data"]["logs"][0]['bot'] == pytest.bot


def test_update_user_details_with_invalid_onboarding_status():
response = client.post(
"/api/user/details/Invalid",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)

actual = response.json()
assert not actual["success"]
assert actual["error_code"] == 422
assert not actual["data"]
assert actual["message"] == "Invalid is not a valid status"

response = client.post(
"/api/user/details/INITIATED",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)

actual = response.json()
assert not actual["success"]
assert actual["error_code"] == 422
assert not actual["data"]
assert actual["message"] == "INITIATED is not a valid status"

response = client.post(
"/api/user/details/IN PROGRESS",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)

actual = response.json()
assert not actual["success"]
assert actual["error_code"] == 422
assert not actual["data"]
assert actual["message"] == "IN PROGRESS is not a valid status"

response = client.post(
"/api/user/details/Done",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)

actual = response.json()
assert not actual["success"]
assert actual["error_code"] == 422
assert not actual["data"]
assert actual["message"] == "Done is not a valid status"


def test_update_user_details_with_onboarding_status():
response = client.get(
"/api/user/details",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
).json()
assert response["data"]["user"]["_id"]
assert response["data"]["user"]["email"] == "[email protected]"
assert (
response["data"]["user"]["bots"]["account_owned"][0]["user"]
== "[email protected]"
)
assert response["data"]["user"]["bots"]["account_owned"][0]["timestamp"]
assert response["data"]["user"]["bots"]["account_owned"][0]["name"]
assert response["data"]["user"]["bots"]["account_owned"][0]["_id"]
assert not response["data"]["user"]["bots"]["shared"]
assert response["data"]["user"]["timestamp"]
assert response["data"]["user"]["status"]
assert response["data"]["user"]["account_name"] == "integration"
assert response["data"]["user"]["first_name"] == "Demo"
assert response["data"]["user"]["last_name"] == "User"
assert response["data"]["user"]["onboarding_status"] == "Not Completed"
assert response["data"]["user"]["is_onboarded"] is False

response = client.post(
"/api/user/details/In Progress",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)

actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0
assert actual["message"] == "Details updated!"

response = client.get(
"/api/user/details",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
).json()
assert response["data"]["user"]["_id"]
assert response["data"]["user"]["email"] == "[email protected]"
assert (
response["data"]["user"]["bots"]["account_owned"][0]["user"]
== "[email protected]"
)
assert response["data"]["user"]["bots"]["account_owned"][0]["timestamp"]
assert response["data"]["user"]["bots"]["account_owned"][0]["name"]
assert response["data"]["user"]["bots"]["account_owned"][0]["_id"]
assert not response["data"]["user"]["bots"]["shared"]
assert response["data"]["user"]["timestamp"]
assert response["data"]["user"]["status"]
assert response["data"]["user"]["account_name"] == "integration"
assert response["data"]["user"]["first_name"] == "Demo"
assert response["data"]["user"]["last_name"] == "User"
assert response["data"]["user"]["onboarding_status"] == "In Progress"
assert response["data"]["user"]["onboarding_timestamp"]
assert response["data"]["user"]["is_onboarded"] is False

response = client.post(
"/api/user/details/Completed",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)

actual = response.json()
assert actual["success"]
assert actual["error_code"] == 0
assert actual["message"] == "Details updated!"

response = client.get(
"/api/user/details",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
).json()
assert response["data"]["user"]["_id"]
assert response["data"]["user"]["email"] == "[email protected]"
assert (
response["data"]["user"]["bots"]["account_owned"][0]["user"]
== "[email protected]"
)
assert response["data"]["user"]["bots"]["account_owned"][0]["timestamp"]
assert response["data"]["user"]["bots"]["account_owned"][0]["name"]
assert response["data"]["user"]["bots"]["account_owned"][0]["_id"]
assert not response["data"]["user"]["bots"]["shared"]
assert response["data"]["user"]["timestamp"]
assert response["data"]["user"]["status"]
assert response["data"]["user"]["account_name"] == "integration"
assert response["data"]["user"]["first_name"] == "Demo"
assert response["data"]["user"]["last_name"] == "User"
assert response["data"]["user"]["onboarding_status"] == "Completed"
assert response["data"]["user"]["onboarding_timestamp"]
assert response["data"]["user"]["is_onboarded"] is True


def test_get_collection_data_with_no_collection_data():
response = client.get(
url=f"/api/bot/{pytest.bot}/data/collection",
Expand Down Expand Up @@ -12628,7 +12764,7 @@ def test_get_user_details():

def test_update_user_details():
response = client.post(
"/api/user/details",
"/api/user/details/Completed",
headers={"Authorization": pytest.token_type + " " + pytest.access_token},
)

Expand Down
69 changes: 69 additions & 0 deletions tests/unit_test/api/api_processor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2835,3 +2835,72 @@ def test_get_attributes(self):
attributes = AuditDataProcessor.get_attributes(document)
assert attributes[0]['key'] == 'email'
assert attributes[0]['value'] == '[email protected]'

def test_update_user_details_with_invalid_onboarding_status(self):
with pytest.raises(ValidationError, match="Invalid is not a valid status"):
AccountProcessor.update_user_details("[email protected]", "Invalid")

with pytest.raises(ValidationError, match="INITIATED is not a valid status"):
AccountProcessor.update_user_details("[email protected]", "INITIATED")

with pytest.raises(ValidationError, match="IN PROGRESS is not a valid status"):
AccountProcessor.update_user_details("[email protected]", "IN PROGRESS")

with pytest.raises(ValidationError, match="Done is not a valid status"):
AccountProcessor.update_user_details("[email protected]", "Done")

def test_update_user_details_with_onboarding_status(self):
assert len(AccountProcessor.get_accessible_bot_details(pytest.account, "[email protected]")['account_owned']) == 1
user_details = AccountProcessor.get_complete_user_details("[email protected]")
assert user_details["_id"]
assert user_details["email"] == "[email protected]"
assert user_details["bots"]["account_owned"][0]["user"] == "[email protected]"
assert user_details["bots"]["account_owned"][0]["timestamp"]
assert user_details["bots"]["account_owned"][0]["name"] == "test_bot"
assert user_details["bots"]["account_owned"][0]["_id"]
assert not user_details["bots"]["shared"]
assert user_details["timestamp"]
assert user_details["status"]
assert user_details["account_name"] == "paypal"
assert user_details["first_name"] == "Fahad Ali"
assert user_details["last_name"] == "Shaikh"
assert user_details["onboarding_status"] == "Not Completed"
assert user_details["is_onboarded"] is False

AccountProcessor.update_user_details("[email protected]", "In Progress")

user_details = AccountProcessor.get_complete_user_details("[email protected]")
assert user_details["_id"]
assert user_details["email"] == "[email protected]"
assert user_details["bots"]["account_owned"][0]["user"] == "[email protected]"
assert user_details["bots"]["account_owned"][0]["timestamp"]
assert user_details["bots"]["account_owned"][0]["name"] == "test_bot"
assert user_details["bots"]["account_owned"][0]["_id"]
assert not user_details["bots"]["shared"]
assert user_details["timestamp"]
assert user_details["status"]
assert user_details["account_name"] == "paypal"
assert user_details["first_name"] == "Fahad Ali"
assert user_details["last_name"] == "Shaikh"
assert user_details["onboarding_status"] == "In Progress"
assert user_details["onboarding_timestamp"]
assert user_details["is_onboarded"] is False

AccountProcessor.update_user_details("[email protected]", "Completed")

user_details = AccountProcessor.get_complete_user_details("[email protected]")
assert user_details["_id"]
assert user_details["email"] == "[email protected]"
assert user_details["bots"]["account_owned"][0]["user"] == "[email protected]"
assert user_details["bots"]["account_owned"][0]["timestamp"]
assert user_details["bots"]["account_owned"][0]["name"] == "test_bot"
assert user_details["bots"]["account_owned"][0]["_id"]
assert not user_details["bots"]["shared"]
assert user_details["timestamp"]
assert user_details["status"]
assert user_details["account_name"] == "paypal"
assert user_details["first_name"] == "Fahad Ali"
assert user_details["last_name"] == "Shaikh"
assert user_details["onboarding_status"] == "Completed"
assert user_details["onboarding_timestamp"]
assert user_details["is_onboarded"] is True

0 comments on commit e58b75a

Please sign in to comment.