Skip to content

Commit

Permalink
Merge pull request #21 from DostEducation/develop
Browse files Browse the repository at this point in the history
Release v1.0
  • Loading branch information
GauravGusain98 authored Dec 11, 2021
2 parents 7d3d05f + 89d0611 commit 6f3e821
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 31 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ DB_HOST=
DB_PORT=
SECRET_KEY=
CONNECTION_NAME=
RETRY_LOGS_BATCH_LIMIT=
MAX_RETRY_ATTEMPTS_FOR_LOGS=
8 changes: 3 additions & 5 deletions api/mixins.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from __future__ import absolute_import

from datetime import datetime
from api import db


class TimestampMixin(object):
created_on = db.Column(db.DateTime, server_default=db.func.now())
updated_on = db.Column(
db.DateTime, server_onupdate=db.func.now(), server_default=db.func.now()
)
created_on = db.Column(db.DateTime, default=datetime.now)
updated_on = db.Column(db.DateTime, onupdate=datetime.now, default=datetime.now)
1 change: 1 addition & 0 deletions api/models/ivr_callback_transaction_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ class IvrCallbackTransactionLog(TimestampMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
payload = db.Column(db.Text)
processed = db.Column(db.Boolean, nullable=False)
attempts = db.Column(db.Integer, nullable=False, default="0")
4 changes: 4 additions & 0 deletions api/services/call_log_event_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This file is treated as service layer
from flask import request
from api import models, db
from datetime import datetime


class CallLogEventService:
Expand All @@ -20,6 +21,9 @@ def create_call_log_event(self, data):
pick_time=data["pick_time"],
end_time=data["end_time"],
duration=data["duration"],
created_on=data["log_created_on"]
if data.get("log_created_on", None)
else datetime.now(),
)
db.session.add(call_log_event)
db.session.commit()
38 changes: 20 additions & 18 deletions api/services/handle_event_service.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import requests
from flask import request
from api import models, db
from api import models, db, app
from . import registration_service as registration
from . import call_log_event_service as call_log_event


class HandleEventService:
def handle_event_service(self, request):

def handle_event_service(self, form_data):
call_sid_exist = db.session.query(
db.exists().where(models.CallLogEvent.call_sid == request.form["CallSid"])
db.exists().where(models.CallLogEvent.call_sid == form_data["CallSid"])
).scalar()

if call_sid_exist:
return

url_decoded_system_phone = requests.utils.unquote(request.form["To"])
url_decoded_system_phone = requests.utils.unquote(form_data["To"])

system_phone_exists = db.session.query(
db.exists().where(models.SystemPhone.phone == url_decoded_system_phone)
Expand All @@ -26,13 +25,13 @@ def handle_event_service(self, request):

try:
data = {}
data["call_sid"] = request.form["CallSid"]
data["account_sid"] = request.form["AccountSid"]
data["from_number"] = request.form["From"]
data["call_sid"] = form_data["CallSid"]
data["account_sid"] = form_data["AccountSid"]
data["from_number"] = form_data["From"]
data["to_number"] = url_decoded_system_phone
data["call_status"] = request.form["CallStatus"]
data["direction"] = request.form["Direction"]
data["parent_call_sid"] = request.form["ParentCallSid"]
data["call_status"] = form_data["CallStatus"]
data["direction"] = form_data["Direction"]
data["parent_call_sid"] = form_data["ParentCallSid"]

data["telco_code"] = None
data["telco_status"] = None
Expand All @@ -41,18 +40,21 @@ def handle_event_service(self, request):
data["end_time"] = None
data["duration"] = None

if form_data.get("log_created_on", None):
data["log_created_on"] = form_data["log_created_on"]

if data["call_status"] != "Missed":
data["telco_code"] = request.form["TelcoCode"]
data["telco_status"] = request.form["TelcoStatus"]
data["dial_time"] = request.form["DialTime"]
data["end_time"] = request.form["EndTime"]
data["duration"] = request.form["Duration"]
data["telco_code"] = form_data["TelcoCode"]
data["telco_status"] = form_data["TelcoStatus"]
data["dial_time"] = form_data["DialTime"]
data["end_time"] = form_data["EndTime"]
data["duration"] = form_data["Duration"]

"""PickTime is available only when the call is answered.
The telco code for answered calls is 16.
"""
if request.form["TelcoCode"] == "16":
data["pick_time"] = request.form["PickTime"]
if form_data["TelcoCode"] == app.config["TELCO_CODE_ANSWERED"]:
data["pick_time"] = form_data["PickTime"]

call_log_event.CallLogEventService.create_call_log_event(self, data)
if data["call_status"] == "Missed":
Expand Down
6 changes: 4 additions & 2 deletions api/services/registration_service.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# This file is treated as service layer
from flask import request
from api import models, db
from datetime import datetime


class RegistrationService:
# Create a registartion
def create_registration(self, data):

system_phone_data = models.SystemPhone.query.filter_by(
phone=data["to_number"]
).first()
Expand All @@ -31,6 +30,9 @@ def create_registration(self, data):
partner_id=partner.partner_id,
state=system_phone_data.state,
has_dropped_missedcall=True,
created_on=data["log_created_on"]
if data.get("log_created_on", None)
else datetime.now(),
)
db.session.add(registration)
db.session.commit()
18 changes: 17 additions & 1 deletion api/services/transaction_log_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This file is treated as service layer
from api import models, db
from api import models, db, app
import json


Expand All @@ -16,3 +16,19 @@ def mark_ivr_transaction_log_as_processed(self, ivr_transaction_log):
ivr_transaction_log.processed = True
db.session.add(ivr_transaction_log)
db.session.commit()

def get_failed_ivr_transaction_log(self):
failed_ivr_transaction_logs = (
models.IvrCallbackTransactionLog.query.filter(
models.IvrCallbackTransactionLog.processed == False
)
.filter(
models.IvrCallbackTransactionLog.attempts
< app.config["MAX_RETRY_ATTEMPTS_FOR_LOGS"]
)
.order_by(models.IvrCallbackTransactionLog.id)
.limit(app.config["RETRY_LOGS_BATCH_LIMIT"])
.all()
)

return failed_ivr_transaction_logs
4 changes: 4 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@
SQLALCHEMY_TRACK_MODIFICATIONS = True
WTF_CSRF_ENABLED = True
SECRET_KEY = os.environ.get("SECRET_KEY")

RETRY_LOGS_BATCH_LIMIT = os.environ.get("RETRY_LOGS_BATCH_LIMIT", 1000)
TELCO_CODE_ANSWERED = 16
MAX_RETRY_ATTEMPTS_FOR_LOGS = os.environ.get("MAX_RETRY_ATTEMPTS_FOR_LOGS", 3)
42 changes: 37 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
# from pprint import pprint
from api import models, db, services
from flask import jsonify, request
import json


def callback(request):
try:
if request.method == "POST":
formData = request.form
json_data = request.get_json()
form_data = request.form
transaction_log_service = services.TransactionLogService()

if json_data and json_data.get("type", None) == "retry_failed_log":
retry_failed_webhook(transaction_log_service)
return "Success"

ivr_transaction_log = (
transaction_log_service.create_new_ivr_transaction_log(formData)
transaction_log_service.create_new_ivr_transaction_log(form_data)
)
service = services.HandleEventService()
service.handle_event_service(request)
processed = process_form_data(form_data)

if not processed:
return jsonify(message="Something went wrong!"), 400

transaction_log_service.mark_ivr_transaction_log_as_processed(
ivr_transaction_log
)
Expand All @@ -21,6 +31,28 @@ def callback(request):
jsonify(message="Currently, the system do not accept a GET request"),
405,
)
except IndexError:
except:
return jsonify(message="Something went wrong!"), 400

return "Success"


def retry_failed_webhook(transaction_log_service):
failed_ivr_logs = transaction_log_service.get_failed_ivr_transaction_log()

for log in failed_ivr_logs:
payload = json.loads(log.payload)
payload["log_created_on"] = log.created_on
log.processed = process_form_data(payload)
log.attempts += 1
db.session.add(log)
db.session.commit()


def process_form_data(form_data):
try:
service = services.HandleEventService()
service.handle_event_service(form_data)
return True
except:
return False

0 comments on commit 6f3e821

Please sign in to comment.