brynq-sdk-zoho 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- brynq_sdk_zoho-1.0.0/PKG-INFO +10 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk/zoho/__init__.py +2 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk/zoho/extract_zoho_desk.py +174 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk/zoho/upload_zoho_desk.py +51 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk_zoho.egg-info/PKG-INFO +10 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk_zoho.egg-info/SOURCES.txt +10 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk_zoho.egg-info/dependency_links.txt +1 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk_zoho.egg-info/not-zip-safe +1 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk_zoho.egg-info/requires.txt +1 -0
- brynq_sdk_zoho-1.0.0/brynq_sdk_zoho.egg-info/top_level.txt +1 -0
- brynq_sdk_zoho-1.0.0/setup.cfg +4 -0
- brynq_sdk_zoho-1.0.0/setup.py +16 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from typing import Union, List
|
|
5
|
+
import requests
|
|
6
|
+
import json
|
|
7
|
+
from brynq_sdk.BrynQ import BrynQ
|
|
8
|
+
|
|
9
|
+
basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
10
|
+
sys.path.append(basedir)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ExtractZohoDesk(BrynQ):
|
|
14
|
+
|
|
15
|
+
def __init__(self, label: Union[str, List], debug: bool = False):
|
|
16
|
+
"""
|
|
17
|
+
For the full documentation, see: https://avisi-apps.gitbook.io/tracket/api/
|
|
18
|
+
"""
|
|
19
|
+
super().__init__()
|
|
20
|
+
self.headers = self._get_headers(label=label)
|
|
21
|
+
self.base_url = "https://desk.zoho.com/api/v1/"
|
|
22
|
+
self.payload = {}
|
|
23
|
+
|
|
24
|
+
def _get_headers(self, label):
|
|
25
|
+
"""
|
|
26
|
+
Get the credentials for the Tracket API from BrynQ, with those credentials, get the access_token for Tracket.
|
|
27
|
+
Return the headers with the access_token.
|
|
28
|
+
"""
|
|
29
|
+
# Get credentials from BrynQ
|
|
30
|
+
credentials = self.get_system_credential(system='zoho-desk', label=label)
|
|
31
|
+
|
|
32
|
+
# With those credentials, get the access_token from Tracket
|
|
33
|
+
org_id = credentials["config"]["organisation_id"]
|
|
34
|
+
zoho_system_id = credentials["id"]
|
|
35
|
+
token = BrynQ().refresh_system_credential(system="zoho-desk", system_id=zoho_system_id)["access_token"]
|
|
36
|
+
headers = {
|
|
37
|
+
'Authorization': f'Zoho-oauthtoken {token}',
|
|
38
|
+
'orgId': f'{org_id}',
|
|
39
|
+
}
|
|
40
|
+
return headers
|
|
41
|
+
|
|
42
|
+
def get_zoho_accounts(self, query_params=""):
|
|
43
|
+
"""
|
|
44
|
+
This function gets all the accounts from zoho and saves them as df_zoho_accounts
|
|
45
|
+
:return: df_zoho_accounts
|
|
46
|
+
"""
|
|
47
|
+
base_url = f"{self.base_url}accounts"
|
|
48
|
+
return self._multiple_calls(base_url, query_params)
|
|
49
|
+
|
|
50
|
+
def get_zoho_agents(self, query_params=""):
|
|
51
|
+
"""
|
|
52
|
+
This function gets the user data from zoho and saves the data to df_zoho_users
|
|
53
|
+
:return:
|
|
54
|
+
"""
|
|
55
|
+
base_url = f"{self.base_url}agents"
|
|
56
|
+
return self._multiple_calls(base_url, query_params)
|
|
57
|
+
|
|
58
|
+
def get_zoho_agent(self, agent_id, query_params=""):
|
|
59
|
+
"""
|
|
60
|
+
This function gets the user data from zoho and saves the data to df_zoho_users
|
|
61
|
+
:return:
|
|
62
|
+
"""
|
|
63
|
+
url = f"{self.base_url}agents/{agent_id}?{query_params}"
|
|
64
|
+
return self._single_call(url)
|
|
65
|
+
|
|
66
|
+
def get_zoho_contacts(self, query_params=""):
|
|
67
|
+
"""
|
|
68
|
+
This function gets the zoho contact information from zoho desk and saves the data to df_zoho_contacts
|
|
69
|
+
:return:
|
|
70
|
+
"""
|
|
71
|
+
base_url = f"{self.base_url}contacts"
|
|
72
|
+
return self._multiple_calls(base_url, query_params)
|
|
73
|
+
|
|
74
|
+
def get_recent_zoho_tickets(self, query_params=""):
|
|
75
|
+
"""
|
|
76
|
+
This function gets the newest 100 tickets form Zoho-Desk
|
|
77
|
+
:return:
|
|
78
|
+
"""
|
|
79
|
+
url = f"{self.base_url}tickets?limit=100&from=0&{query_params}"
|
|
80
|
+
return self._single_call(url)
|
|
81
|
+
|
|
82
|
+
def get_all_zoho_tickets(self, query_params: str = "") -> pd.DataFrame:
|
|
83
|
+
"""
|
|
84
|
+
This function gets the zoho contact information from zoho desk and saves the data to df_zoho_contacts
|
|
85
|
+
:return:
|
|
86
|
+
"""
|
|
87
|
+
base_url = f"{self.base_url}tickets"
|
|
88
|
+
return self._multiple_calls(base_url, query_params)
|
|
89
|
+
|
|
90
|
+
def get_archived_zoho_tickets(self, query_params: str = "") -> pd.DataFrame:
|
|
91
|
+
"""
|
|
92
|
+
This function gets the zoho contact information from zoho desk and saves the data to df_zoho_contacts
|
|
93
|
+
:return:
|
|
94
|
+
"""
|
|
95
|
+
base_url = f"{self.base_url}tickets/archivedTickets"
|
|
96
|
+
return self._multiple_calls(base_url, query_params)
|
|
97
|
+
|
|
98
|
+
def get_active_ticket_timers(self, tickets: pd.DataFrame, query_params: str = "") -> pd.DataFrame:
|
|
99
|
+
"""=
|
|
100
|
+
This function gets all the active ticket timers from the tickets given in the tickets dataframe.
|
|
101
|
+
:param tickets: dataframe with the ticket_id's
|
|
102
|
+
:param query_params: query parameters for the API call
|
|
103
|
+
:return: pd.DataFrame with the ticket timers
|
|
104
|
+
"""
|
|
105
|
+
df = pd.DataFrame()
|
|
106
|
+
count = 0
|
|
107
|
+
for index, ticket in tickets.iterrows():
|
|
108
|
+
count = count + 1
|
|
109
|
+
print(f"Checking for ticket number {ticket.ticket_id}. ticket {count} / " + str(
|
|
110
|
+
len(tickets.index)))
|
|
111
|
+
url = f"{self.base_url}tickets/{ticket.ticket_id}/activeTimer?{query_params}"
|
|
112
|
+
df_temp = self._single_call(url)
|
|
113
|
+
df_temp['ticket_id'] = ticket.ticket_id
|
|
114
|
+
df_temp['link'] = ticket.link
|
|
115
|
+
df_temp['ticket_number'] = ticket.ticket_number
|
|
116
|
+
df = pd.concat([df, df_temp])
|
|
117
|
+
df = df.reset_index(drop=True)
|
|
118
|
+
return df
|
|
119
|
+
|
|
120
|
+
def get_zoho_ticket_timers(self, tickets, query_params=""):
|
|
121
|
+
"""
|
|
122
|
+
This function gets all the ticket timers from the recent tickets if there already exists a database. Otherwise,
|
|
123
|
+
it will get all the ticket timers. the ticket timers are saved to df_zoho_ticket_timers
|
|
124
|
+
:return:
|
|
125
|
+
"""
|
|
126
|
+
df = pd.DataFrame()
|
|
127
|
+
count = 0
|
|
128
|
+
for ticket_id in tickets["ticket_id"]:
|
|
129
|
+
count = count + 1
|
|
130
|
+
print(f"Checking for ticket number {ticket_id}. ticket {count} / " + str(
|
|
131
|
+
len(tickets.index)))
|
|
132
|
+
url = f"{self.base_url}tickets/{ticket_id}/timeEntry?{query_params}"
|
|
133
|
+
df_temp = self._single_call(url)
|
|
134
|
+
df = pd.concat([df, df_temp])
|
|
135
|
+
df = df.reset_index(drop=True)
|
|
136
|
+
return df
|
|
137
|
+
|
|
138
|
+
def _multiple_calls(self, base_url, query_params) -> pd.DataFrame:
|
|
139
|
+
"""
|
|
140
|
+
This function helps the API calls to do multiple calls in one function
|
|
141
|
+
:return:
|
|
142
|
+
"""
|
|
143
|
+
df = pd.DataFrame()
|
|
144
|
+
end_of_loop = False
|
|
145
|
+
offset = 0
|
|
146
|
+
while not end_of_loop:
|
|
147
|
+
url = f"{base_url}?from={offset}&limit=90&{query_params}"
|
|
148
|
+
df_temp = self._single_call(url)
|
|
149
|
+
df = pd.concat([df_temp, df])
|
|
150
|
+
if len(df_temp) != 90:
|
|
151
|
+
end_of_loop = True
|
|
152
|
+
else:
|
|
153
|
+
offset += 90
|
|
154
|
+
return df
|
|
155
|
+
|
|
156
|
+
def _single_call(self, url: str) -> pd.DataFrame:
|
|
157
|
+
"""
|
|
158
|
+
This function helps the API calls to do a single call in one function
|
|
159
|
+
:return:
|
|
160
|
+
"""
|
|
161
|
+
response = requests.request("GET", url, headers=self.headers, data=self.payload)
|
|
162
|
+
if response.status_code == 401:
|
|
163
|
+
response = requests.request("GET", url, headers=self.headers, data=self.payload)
|
|
164
|
+
if response.status_code == 200:
|
|
165
|
+
df = response.json()
|
|
166
|
+
if 'data' in df:
|
|
167
|
+
df = pd.json_normalize(df['data'])
|
|
168
|
+
else:
|
|
169
|
+
df = pd.json_normalize(df)
|
|
170
|
+
return df
|
|
171
|
+
elif response.status_code == 204:
|
|
172
|
+
return pd.DataFrame()
|
|
173
|
+
else:
|
|
174
|
+
raise Exception(response.text)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from typing import Union, List
|
|
5
|
+
import requests
|
|
6
|
+
import json
|
|
7
|
+
from brynq_sdk.brynq import BrynQ
|
|
8
|
+
|
|
9
|
+
basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
10
|
+
sys.path.append(basedir)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class UploadZohoDesk(BrynQ):
|
|
14
|
+
|
|
15
|
+
def __init__(self, label: Union[str, List], debug: bool = False):
|
|
16
|
+
"""
|
|
17
|
+
For the full documentation, see: https://avisi-apps.gitbook.io/tracket/api/
|
|
18
|
+
"""
|
|
19
|
+
super().__init__()
|
|
20
|
+
self.headers = self.__get_headers(label=label)
|
|
21
|
+
self.base_url = "https://desk.zoho.com/api/v1/"
|
|
22
|
+
|
|
23
|
+
def __get_headers(self, label):
|
|
24
|
+
"""
|
|
25
|
+
Get the credentials for the Traket API from BrynQ, with those credentials, get the access_token for Tracket.
|
|
26
|
+
Return the headers with the access_token.
|
|
27
|
+
"""
|
|
28
|
+
# Get credentials from BrynQ
|
|
29
|
+
credentials = self.get_system_credential(system='zoho-desk', label=label)
|
|
30
|
+
|
|
31
|
+
# With those credentials, get the access_token from Tracket
|
|
32
|
+
org_id = credentials["config"]["organisation_id"]
|
|
33
|
+
zoho_system_id = credentials["id"]
|
|
34
|
+
token = BrynQ().refresh_system_credential(system="zoho-desk", system_id=zoho_system_id)["access_token"]
|
|
35
|
+
headers = {
|
|
36
|
+
'Authorization': f'Zoho-oauthtoken {token}',
|
|
37
|
+
'orgId': f'{org_id}',
|
|
38
|
+
'Content-Type': 'application/json'
|
|
39
|
+
}
|
|
40
|
+
return headers
|
|
41
|
+
|
|
42
|
+
def update_ticket_time_entry(self, ticket_id, time_entry_id, payload):
|
|
43
|
+
"""
|
|
44
|
+
This function updates the time entry of a ticket in zoho desk
|
|
45
|
+
:param ticket_id: str
|
|
46
|
+
:param time_entry_id: str
|
|
47
|
+
:param payload: dict
|
|
48
|
+
"""
|
|
49
|
+
url = f"{self.base_url}tickets/{ticket_id}/timeEntry/{time_entry_id}"
|
|
50
|
+
response = requests.request("PATCH", url, headers=self.headers, data=json.dumps(payload))
|
|
51
|
+
return response
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
setup.py
|
|
2
|
+
brynq_sdk/zoho/__init__.py
|
|
3
|
+
brynq_sdk/zoho/extract_zoho_desk.py
|
|
4
|
+
brynq_sdk/zoho/upload_zoho_desk.py
|
|
5
|
+
brynq_sdk_zoho.egg-info/PKG-INFO
|
|
6
|
+
brynq_sdk_zoho.egg-info/SOURCES.txt
|
|
7
|
+
brynq_sdk_zoho.egg-info/dependency_links.txt
|
|
8
|
+
brynq_sdk_zoho.egg-info/not-zip-safe
|
|
9
|
+
brynq_sdk_zoho.egg-info/requires.txt
|
|
10
|
+
brynq_sdk_zoho.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
brynq-sdk-brynq>=1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
brynq_sdk
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='brynq_sdk_zoho',
|
|
5
|
+
version='1.0.0',
|
|
6
|
+
description='ZOHO wrapper from BrynQ',
|
|
7
|
+
long_description='ZOHO wrapper from BrynQ',
|
|
8
|
+
author='BrynQ',
|
|
9
|
+
author_email='support@brynq.com',
|
|
10
|
+
packages=["brynq_sdk.zoho"],
|
|
11
|
+
license='BrynQ License',
|
|
12
|
+
install_requires=[
|
|
13
|
+
'brynq-sdk-brynq>=1'
|
|
14
|
+
],
|
|
15
|
+
zip_safe=False,
|
|
16
|
+
)
|