Skip to content

Commit

Permalink
Merge pull request #30 from Jordan-Prescott/call_flow_graph_2
Browse files Browse the repository at this point in the history
Call flow graph 2
  • Loading branch information
Jordan-Prescott authored May 17, 2024
2 parents 583b4e5 + 1fcfb6c commit 85094ff
Show file tree
Hide file tree
Showing 13 changed files with 945 additions and 243 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,5 @@ sandbox.py

# mac
*.DS_Store

os_reports/
call_flow_data-temp/
163 changes: 160 additions & 3 deletions odins_spear/methods/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ def session(self):
# ADMINISTRATORS
# ADVICE OF CHARGE
# ALTERNATE NUMBERS

def user_alternate_numbers(self, user_id: str):
"""Fetches a list of a user/ service such as Auto Attendant, Hunt Group, or Call Centres
alternate numebrs.
Args:
user_id (str): Target user/ service_user_id
Returns:
Dict: List of all alternate numbers assigned to the user/ service.
"""

endpoint = f"/users/alternate-numbers?userId={user_id}"

return self.requester.get(endpoint)

# ANSWER CONFIRMATION
# ALTERNATE USER ID
# ANNOUNCEMENTS
Expand Down Expand Up @@ -63,26 +79,142 @@ def group_call_centers(self, service_provider_id: str, group_id: str):

return self.requester.get(endpoint)


def group_call_center(self, service_user_id: str):

endpoint = f"/groups/call-centers?serviceUserId={service_user_id}"

return self.requester.get(endpoint)


def user_call_center(self, user_id: str):

endpoint = f"/users/call-center?userId={user_id}"

return self.requester.get(endpoint)



def group_call_center_bounced_calls(self, service_user_id: str):

endpoint = f"/groups/call-centers/bounced-calls?serviceUserId={service_user_id}"

return self.requester.get(endpoint)


def group_call_center_forced_forwarding(self, service_user_id: str):

endpoint = f"/groups/call-centers/forced-forwarding?serviceUserId={service_user_id}"

return self.requester.get(endpoint)


def group_call_center_overflow(self, service_user_id):

endpoint = f"/groups/call-centers/overflow?serviceUserId={service_user_id}"

return self.requester.get(endpoint)


def group_call_center_stranded_calls(self, service_user_id):

endpoint = f"/groups/call-centers/stranded-calls?serviceUserId={service_user_id}"

return self.requester.get(endpoint)


def group_call_center_stranded_calls_unavailable(self, service_user_id):

endpoint = f"/groups/call-centers/stranded-calls-unavailable?serviceUserId={service_user_id}"

return self.requester.get(endpoint)

# CALL CONTROL
# CALL FORWARDING ALWAYS
# CALL FORWARDING ALWAYS SECONDARY

def user_call_forwarding_always(self, user_id: str):

endpoint = f"/users/call-forwarding-always?userId={user_id}"

return self.requester.get(endpoint)


def bulk_call_forwarding_always(self, service_provider_id: str, group_id: str):

endpoint = f"/users/call-forwarding-always/bulk?serviceProviderId={service_provider_id}&groupId={group_id}"

return self.requester.get(endpoint)


# CALL FORWARDING BUSY

def user_call_forwarding_busy(self, user_id: str):

endpoint = f"/users/call-forwarding-busy?userId={user_id}"

return self.requester.get(endpoint)


def bulk_call_forwarding_busy(self, service_provider_id: str, group_id: str):

endpoint = f"/users/call-forwarding-busy/bulk?serviceProviderId={service_provider_id}&groupId={group_id}"

return self.requester.get(endpoint)


# CALL FORWARDING NO ANSWER

def user_call_forwarding_no_answer(self, user_id: str):

endpoint = f"/users/call-forwarding-no-answer?userId={user_id}"

return self.requester.get(endpoint)


def bulk_call_forwarding_no_answer(self, service_provider_id: str, group_id: str):

endpoint = f"/users/call-forwarding-no-answer/bulk?serviceProviderId={service_provider_id}&groupId={group_id}"

return self.requester.get(endpoint)


# CALL FORWARDING NOT REACHABLE

def user_call_forwarding_not_reachable(self, user_id: str):

endpoint = f"/users/call-forwarding-not-reachable?userId={user_id}"

return self.requester.get(endpoint)


def bulk_call_forwarding_not_reachable(self, service_provider_id: str, group_id: str):

endpoint = f"/users/call-forwarding-not-reachable/bulk?serviceProviderId={service_provider_id}&groupId={group_id}"

return self.requester.get(endpoint)


# CALL FORWARDING SELECTIVE
# CALL FORWARDING SETTINGS

def user_call_forwarding_selective(self, user_id: str):

endpoint = f"/users/call-forwarding-selective?userId={user_id}"

return self.requester.get(endpoint)


def user_call_forwarding_selective_criterias(self, user_id: str):

endpoint = f"/users/call-forwarding-selective/criteria?userId={user_id}"

return self.requester.get(endpoint)


def user_call_forwarding_selective_criteria(self, user_id: str, criteria_name: str):

endpoint = f"/users/call-forwarding-selective/criteria?criteriaName={criteria_name}&userId={user_id}"

return self.requester.get(endpoint)

# CALL NOTIFY
# CALL PARK
# CALL PICKUP
Expand Down Expand Up @@ -533,6 +665,21 @@ def user_report(self, user_id: str):
# ROUTE LIST
# ROUTING PROFILE
# SCHEDULES

def group_schedules(self, service_provider_id: str, group_id: str):

endpoint = f"/groups/schedules?serviceProviderId={service_provider_id}&groupId={group_id}"

return self.requester.get(endpoint)


def group_events(self, service_provider_id: str, group_id: str, name: str, type: str):

endpoint = f"/groups/events?serviceProviderId={service_provider_id}&groupId={group_id}&name={name}&type={type}"

return self.requester.get(endpoint)


# SECURITY CLASSIFICATION
# SELECTIVE CALL ACCEPTANCE
# SELECTIVE CALL REJECTION
Expand All @@ -553,6 +700,16 @@ def service_providers(self, reseller_id=None):
return self.requester.get(endpoint)


def service_provider(self, service_provider_id: str):
"""
Args:
reseller_id (str): Only list the Service Provider IDs within the specified Reseller.
"""

endpoint = f"/service-providers?serviceProviderId={service_provider_id}"

return self.requester.get(endpoint)

# SERVICES

def user_services_assigned(self, user_id: str):
Expand Down
28 changes: 25 additions & 3 deletions odins_spear/reporter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
from . import reports

class Reporter:
''' generates human friendly reports
'''
""" generates human friendly reports.
"""

def __init__(self, api) -> None:
self.api = api
self.api = api


def call_flow(self, service_provider_id: str, group_id: str, number: str, number_type: str,
broadworks_entity_type: str):
"""Generates a graphical flow chart of how a call to a specified number routes
through the broadworks system.
Args:
service_provider_id (str): Service Provider/ Enterprise where group is hosted.
group_id (str): Group ID where target number for call flow is located.
number (str): Target number for call flow.
number_type (str): Type of number, options: "dn": Direct Number, "extension": Extension, "alias": Alias
broadworks_entity_type (str): Broadworks entity type target number is associated with. \
Options: "auto_attendant": Auto Attendant, "call_center": Call Center, "hunt_group": Hunt Group, "user": User
"""

return reports.call_flow.main(self.api, service_provider_id, group_id, number, number_type,
broadworks_entity_type)


5 changes: 5 additions & 0 deletions odins_spear/reports/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
__all__ = [
"call_flow"
]

from .call_flow import main
140 changes: 140 additions & 0 deletions odins_spear/reports/call_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import json

from tqdm import tqdm

from .report_utils.graphviz_module import GraphvizModule
from .report_utils.helpers import find_entity_with_number_type
from .report_utils.parsing import call_flow_module


from odins_spear.store import DataStore
from odins_spear.store import broadwork_entities as bre

def main(api, service_provider_id: str, group_id: str, number: str, number_type: str,
broadworks_entity_type: str):

data_store = DataStore()

print("Start.\n")
print("Fetching Service Provider & Group details.")
# Gather entities
service_provider = bre.ServiceProvider.from_dict(data=api.get.service_provider(service_provider_id))
group = bre.Group.from_dict(service_provider=service_provider, data=api.get.group(service_provider_id, group_id))

data_store.store_objects(service_provider, group)

auto_attendants = api.get.auto_attendants(service_provider_id, group_id)
for aa in tqdm(auto_attendants, desc=f"Fetching all Auto Attendants."):
auto_attendant = bre.AutoAttendant.from_dict(group=group, data=api.get.auto_attendant(aa['serviceUserId']))
data_store.auto_attendants.append(auto_attendant)

print("Fetching all users this may take a couple of minutes, please wait.")
users = api.get.users(service_provider_id, group_id, extended=True)

# Captures users with the forward fucntionality
call_forward_always_users = [
item["user"]["userId"] for item in api.get.bulk_call_forwarding_always(service_provider_id, group_id) if item["service"]["assigned"] \
and item["data"]["isActive"]
]

call_forward_busy_users = [
item["user"]["userId"] for item in api.get.bulk_call_forwarding_busy(service_provider_id, group_id) if item["service"]["assigned"] \
and item["data"]["isActive"]
]

call_forward_no_answer_users = [
item["user"]["userId"] for item in api.get.bulk_call_forwarding_no_answer(service_provider_id, group_id) if item["service"]["assigned"] \
and item["data"]["isActive"]
]

call_forward_not_reachable = [
item["user"]["userId"] for item in api.get.bulk_call_forwarding_not_reachable(service_provider_id, group_id) if item["service"]["assigned"] \
and item["data"]["isActive"]
]

for u in tqdm(users, desc=f"Parsing all Users."):
user = bre.User.from_dict(group=group, data=u)

if user.id in call_forward_always_users:
user.call_forwarding_always = str(api.get.user_call_forwarding_always(user.id)["forwardToPhoneNumber"])
if user.id in call_forward_busy_users:
user.call_forwarding_busy = str(api.get.user_call_forwarding_busy(user.id)["forwardToPhoneNumber"])
if user.id in call_forward_no_answer_users:
user.call_forwarding_no_answer = str(api.get.user_call_forwarding_no_answer(user.id)["forwardToPhoneNumber"])
if user.id in call_forward_not_reachable:
user.call_forwarding_not_reachable = str(api.get.user_call_forwarding_not_reachable(user.id)["forwardToPhoneNumber"])

data_store.users.append(user)


call_centers = api.get.group_call_centers(service_provider_id, group_id)
for cc in tqdm(call_centers, desc=f"Fetching all Call Centers."):
call_center = bre.CallCenter.from_dict(group= group, data= api.get.group_call_center(cc['serviceUserId']))

try:
overflow_settings = api.get.group_call_center_overflow(call_center.service_user_id)
call_center.overflow_calls_action = overflow_settings["action"]
call_center.overflow_calls_transfer_to_phone_number = overflow_settings["transferPhoneNumber"] \
if call_center.overflow_calls_action == "Transfer" else None
except Exception:
call_center.overflow_calls_action = None
call_center.overflow_calls_transfer_to_phone_number = None

try:
stranded_calls_settings = api.get.group_call_center_stranded_calls(call_center.service_user_id)
call_center.stranded_call_unavailable_action = stranded_calls_settings["action"]
call_center.stranded_call_unavailable_transfer_to_phone_number = stranded_calls_settings["transferPhoneNumber"] \
if call_center.stranded_call_unavailable_action == "Transfer" else None
except Exception:
call_center.stranded_call_unavailable_action = None
call_center.stranded_call_unavailable_transfer_to_phone_number = None

try:
stranded_calls_unavailable_settings = api.get.group_call_center_stranded_calls_unavailable(call_center.service_user_id)
call_center.stranded_call_unavailable_action = stranded_calls_unavailable_settings["action"]
call_center.stranded_call_unavailable_transfer_to_phone_number = stranded_calls_unavailable_settings["transferPhoneNumber"] \
if call_center.stranded_call_unavailable_action == "Transfer" else None
except Exception:
call_center.stranded_call_unavailable_action = None
call_center.stranded_call_unavailable_transfer_to_phone_number = None

try:
forced_forwarding_settings = api.get.group_call_center_forced_forwarding(call_center.service_user_id)
call_center.forced_forwarding_enabled = forced_forwarding_settings["enabled"]
call_center.forced_forwarding_forward_to_phone_number = forced_forwarding_settings["forwardToPhoneNumber"] \
if call_center.forced_forwarding_enabled else None
except Exception:
call_center.forced_forwarding_enabled = False
call_center.forced_forwarding_forward_to_phone_number = None

data_store.call_centers.append(call_center)

hunt_groups = api.get.group_hunt_groups(service_provider_id, group_id)
for hg in tqdm(hunt_groups, desc=f"Fetching all Hunt Groups."):
hunt_group = bre.HuntGroup.from_dict(group=group, data= api.get.group_hunt_group(hg['serviceUserId']))
data_store.hunt_groups.append(hunt_group)

# locate number using broadworks_entity_type to zone in on correct location
call_flow_start_node = find_entity_with_number_type(
number,
number_type.lower(),
getattr(data_store, broadworks_entity_type + "s")
)
call_flow_start_node._start_node = True

# Nodes used in the graph
print("Gathering nodes in flow.")
bre_nodes = call_flow_module(call_flow_start_node, data_store)

print("Generating report.")
# build, generate, save graph
graph = GraphvizModule(
"./os_reports/"
)
graph.generate_call_flow_graph(
bre_nodes,
number
)
print("Saving report.")
graph._save_graph(f"Calls To {number}")
print("\nEnd.")
Loading

0 comments on commit 85094ff

Please sign in to comment.