Skip to content

Commit

Permalink
Merge pull request #34 from DostEducation/develop
Browse files Browse the repository at this point in the history
Release 08 May 2024
  • Loading branch information
Sachinbisht27 authored May 8, 2024
2 parents 96dbaf8 + cd1f937 commit 38a4181
Show file tree
Hide file tree
Showing 26 changed files with 674 additions and 86 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FLASK_APP=
FLASK_ENV=

SQLALCHEMY_DATABASE_URI=

Expand Down
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ Example of Pull Request Title: #1023 Add user authentication functionality
- [ ] The changes requires a change to the documentation.
- [ ] I have updated the documentation based on the my changes.
- [ ] I have added tests to cover my changes (if not applicable, please state why)
- [ ] All new and existing tests are passing.\
- [ ] All new and existing tests are passing.
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
env:
SQLALCHEMY_DATABASE_URI: ${{ secrets.SQLALCHEMY_DATABASE_URI }}
FLASK_APP: ${{ secrets.FLASK_APP }}
FLASK_ENV: ${{ secrets.FLASK_APP_STAGING }}
FLASK_ENV: ${{ secrets.FLASK_ENV_STAGING }}
run: |
flask db upgrade
Expand All @@ -61,7 +61,7 @@ jobs:
--entry-point=handle_payload \
--memory=256MB \
--timeout=30s \
--set-env-vars=FLASK_APP=${{ secrets.FLASK_APP_STAGING }},LOGGING_LEVEL=${{ secrets.LOGGING_LEVEL }},SQLALCHEMY_DATABASE_URI=${{ secrets.SQLALCHEMY_DATABASE_URI_STAGING }}
--set-env-vars=FLASK_ENV=${{ secrets.FLASK_ENV_STAGING }},LOGGING_LEVEL=${{ secrets.LOGGING_LEVEL }},SQLALCHEMY_DATABASE_URI=${{ secrets.SQLALCHEMY_DATABASE_URI_STAGING }}
deploy-production:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -99,7 +99,7 @@ jobs:
env:
SQLALCHEMY_DATABASE_URI: ${{ secrets.SQLALCHEMY_DATABASE_URI_PROD }}
FLASK_APP: ${{ secrets.FLASK_APP }}
FLASK_ENV: ${{ secrets.FLASK_APP_PROD }}
FLASK_ENV: ${{ secrets.FLASK_ENV_PROD }}
run: |
flask db upgrade
Expand All @@ -117,4 +117,4 @@ jobs:
--entry-point=handle_payload \
--memory=256MB \
--timeout=30s \
--set-env-vars=FLASK_APP=${{ secrets.FLASK_APP_PROD }},LOGGING_LEVEL=${{ secrets.LOGGING_LEVEL }},SQLALCHEMY_DATABASE_URI=${{ secrets.SQLALCHEMY_DATABASE_URI_PRODUCTION }}
--set-env-vars=FLASK_ENV=${{ secrets.FLASK_ENV_PROD }},LOGGING_LEVEL=${{ secrets.LOGGING_LEVEL }},SQLALCHEMY_DATABASE_URI=${{ secrets.SQLALCHEMY_DATABASE_URI_PRODUCTION }}
9 changes: 3 additions & 6 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ on:
branches:
- develop
- main

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.12.1'
- uses: pre-commit/[email protected]
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/[email protected]
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ __pycache__/
.venv
env/
venv/
.python-version
17 changes: 9 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,27 @@ repos:
- id: check-added-large-files
- id: debug-statements
- id: requirements-txt-fixer
- repo: https://github.com/pre-commit/mirrors-isort
rev: 'v5.10.1'
hooks:
- id: isort
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.9.0'
rev: 'v1.10.0'
hooks:
- id: mypy
exclude: alembic
- repo: https://github.com/psf/black
rev: 24.4.0
rev: 24.4.2
hooks:
- id: black
args: [--line-length=79]
args: [--line-length=88]
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
hooks:
- id: flake8
exclude: __init__.py
args: [--max-line-length=88]
- repo: https://github.com/PyCQA/docformatter
rev: v1.5.0
rev: v1.7.5
hooks:
- id: docformatter
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
- id: python-use-type-annotations
1 change: 1 addition & 0 deletions api/helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .common_helper import *
9 changes: 9 additions & 0 deletions api/helpers/common_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from datetime import datetime, timedelta


def get_ist_timestamp() -> datetime:
return datetime.utcnow() + timedelta(minutes=330)


def check_activity_key(activity_key: str, keyword: str, status: str):
return activity_key.startswith(keyword) and activity_key.endswith(status)
39 changes: 35 additions & 4 deletions api/models/user_activities.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
from datetime import date
from flask_sqlalchemy.query import Query as BaseQuery
from sqlalchemy import desc, func

from api import db
from api.mixins import TimestampMixin


class UserActivitiesQuery(BaseQuery):
def get_todays_started_activity_for_user(self, user_id, user_phone):
return (
self.filter(
UserActivities.user_id == user_id,
UserActivities.user_phone == user_phone,
UserActivities.is_started.is_(True),
func.DATE(UserActivities.started_on) == date.today(),
)
.order_by(desc("started_on"))
.first()
)

def get_todays_succeeded_activity_for_user(self, user_id, user_phone):
return (
self.filter(
UserActivities.user_id == user_id,
UserActivities.user_phone == user_phone,
UserActivities.is_succeeded.is_(True),
func.DATE(UserActivities.succeeded_on) == date.today(),
)
.order_by(desc("succeeded_on"))
.first()
)


class UserActivities(TimestampMixin, db.Model):
query_class = UserActivitiesQuery

__tablename__ = "user_activities"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
user_phone = db.Column(db.Integer, nullable=False, index=True)
user_phone = db.Column(db.BigInteger, nullable=False, index=True)
user_flow_id = db.Column(db.Integer, db.ForeignKey("user_flows.id"))
activity = db.Column(db.String(500))
is_started = db.Column(db.Boolean, default=False, nullable=False)
is_started = db.Column(db.Boolean)
started_on = db.Column(db.DateTime)
is_succeeded = db.Column(db.Boolean, default=False, nullable=False)
is_succeeded = db.Column(db.Boolean)
succeeded_on = db.Column(db.DateTime)
is_completed = db.Column(db.Boolean, default=False, nullable=False)
is_completed = db.Column(db.Boolean)
completed_on = db.Column(db.DateTime)
2 changes: 1 addition & 1 deletion api/models/user_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ class UserAttributes(TimestampMixin, db.Model):
__tablename__ = "user_attributes"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
user_phone = db.Column(db.Integer, nullable=False, index=True)
user_phone = db.Column(db.BigInteger, nullable=False, index=True)
field_name = db.Column(db.String(255))
field_value = db.Column(db.String(255))
29 changes: 26 additions & 3 deletions api/models/user_flows.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
from datetime import date
from flask_sqlalchemy.query import Query as BaseQuery
from sqlalchemy import desc, func

from api import db
from api.mixins import TimestampMixin


class UserFlowsQuery(BaseQuery):
def get_todays_latest_user_flow(self, flow_uuid, user_phone):
return (
self.filter(
UserFlows.flow_uuid == flow_uuid,
UserFlows.user_phone == user_phone,
func.DATE(UserFlows.flow_start_time) == date.today(),
)
.order_by(desc("flow_start_time"))
.first()
)


class UserFlows(TimestampMixin, db.Model):
query_class = UserFlowsQuery

class FlowRunStatus:
STARTED = "started"
COMPLETED = "completed"
ENDED = "ended"

__tablename__ = "user_flows"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
user_phone = db.Column(db.Integer, nullable=False, index=True)
flow_uuid = db.Column(db.String(255))
user_phone = db.Column(db.BigInteger, nullable=False, index=True)
flow_uuid = db.Column(db.String(255), index=True)
flow_name = db.Column(db.String(255))
flow_type = db.Column(db.String(255))
flow_run_status = db.Column(db.String(255))
flow_start_time = db.Column(db.DateTime)
flow_end_time = db.Column(db.DateTime)
is_active = db.Column(db.Boolean, default=False, nullable=False)
is_active = db.Column(db.Boolean)
4 changes: 2 additions & 2 deletions api/models/user_indicator_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
class UserIndicatorResponses(TimestampMixin, db.Model):

__tablename__ = "user_indicator_responses"
id = db.Column(db.Integer, primary_key=True)
id = db.Column(db.BigInteger, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
user_phone = db.Column(db.Integer, nullable=False, index=True)
user_phone = db.Column(db.BigInteger, nullable=False, index=True)
user_flow_id = db.Column(db.Integer, db.ForeignKey("user_flows.id"))
indicator_question = db.Column(db.String(255))
indicator_question_response = db.Column(db.String(255))
11 changes: 9 additions & 2 deletions api/models/users.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
from flask_sqlalchemy.query import Query as BaseQuery

from api import db
from api.mixins import TimestampMixin


class Users(TimestampMixin, db.Model):
class UserQuery(BaseQuery):
def get_by_phone(self, user_phone):
return self.filter(Users.phone == user_phone).first()


class Users(TimestampMixin, db.Model):
query_class = UserQuery
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
glific_user_id = db.Column(db.Integer)
phone = db.Column(db.Integer, nullable=False, index=True)
phone = db.Column(db.BigInteger, nullable=False, index=True)
name = db.Column(db.String(255))
location = db.Column(db.String(255))
4 changes: 4 additions & 0 deletions api/services/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
from .flow_run_log_service import *
from .user_activities_service import *
from .user_creation_service import *
from .user_indicator_response_service import *
from .webhook_transaction_log_service import *
78 changes: 78 additions & 0 deletions api/services/flow_run_log_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from typing import Any, Optional

from api import models
from api.helpers import common_helper
from api.utils import db_utils
from api.utils.loggingutils import logger


class FlowRunLogService:
def __init__(self, user: models.Users):
self.user = user
self.class_model = models.UserFlows

def create_user_flow_log(self, json_data: dict[str, Any]) -> models.UserFlows:
user_flow_log = None

try:
flow_uuid = json_data.get("flow_uuid")
flow_name = json_data.get("flow_name")
flow_type = json_data.get("flow_type")
flow_status = json_data.get("flow_status")

latest_flow_log: models.UserFlows = (
self.class_model.query.get_todays_latest_user_flow(
flow_uuid, self.user.phone
)
)

if flow_status == self.class_model.FlowRunStatus.STARTED:
user_flow_log = self.create_log(flow_uuid, flow_name, flow_type)
elif flow_status == self.class_model.FlowRunStatus.COMPLETED:
user_flow_log = self.update_log(latest_flow_log)
else:
logger.error(
f"Got unexpected flow status {flow_status}. Flow name {flow_name}."
)

except Exception as e:
logger.error(
f"Error while creating new user flow log. json data: {json_data}."
f"Error message: {e}"
)
raise

if user_flow_log is None:
raise ValueError("Failed to create or update user flow log.")

return user_flow_log

def create_log(
self,
flow_uuid: Optional[str],
flow_name: Optional[str],
flow_type: Optional[str],
) -> models.UserFlows:
user_flow_log: models.UserFlows = self.class_model(
user_id=self.user.id,
user_phone=self.user.phone,
flow_uuid=flow_uuid,
flow_name=flow_name,
flow_type=flow_type,
flow_run_status=self.class_model.FlowRunStatus.STARTED,
flow_start_time=common_helper.get_ist_timestamp(),
is_active=True,
)

db_utils.save(user_flow_log)
logger.info(f"Created a user flow log for phone number {self.user.phone}.")
return user_flow_log

def update_log(self, latest_flow_log: models.UserFlows) -> models.UserFlows:
latest_flow_log.flow_run_status = self.class_model.FlowRunStatus.COMPLETED
latest_flow_log.flow_end_time = common_helper.get_ist_timestamp()
latest_flow_log.is_active = False

db_utils.save(latest_flow_log)
logger.info(f"Updated user flow log for phone number {self.user.phone}.")
return latest_flow_log
Loading

0 comments on commit 38a4181

Please sign in to comment.