@slates-integrations/zoho 0.2.0-rc.5
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.
- package/README.md +11 -0
- package/docs/SPEC.md +155 -0
- package/logo.png +0 -0
- package/package.json +19 -0
- package/slate.json +17 -0
- package/src/auth.ts +339 -0
- package/src/config.ts +11 -0
- package/src/index.ts +44 -0
- package/src/lib/client.ts +733 -0
- package/src/lib/errors.ts +90 -0
- package/src/lib/urls.ts +77 -0
- package/src/spec.ts +12 -0
- package/src/tools/books-get-invoices.ts +114 -0
- package/src/tools/books-manage-contact.ts +168 -0
- package/src/tools/books-manage-expense.ts +142 -0
- package/src/tools/books-manage-invoice.ts +190 -0
- package/src/tools/crm-get-modules.ts +93 -0
- package/src/tools/crm-get-records.ts +137 -0
- package/src/tools/crm-get-related-records.ts +104 -0
- package/src/tools/crm-manage-record.ts +117 -0
- package/src/tools/crm-search-records.ts +109 -0
- package/src/tools/desk-get-tickets.ts +146 -0
- package/src/tools/desk-manage-contact.ts +125 -0
- package/src/tools/desk-manage-ticket.ts +126 -0
- package/src/tools/index.ts +16 -0
- package/src/tools/people-manage-employee.ts +163 -0
- package/src/tools/projects-get-portals.ts +50 -0
- package/src/tools/projects-manage-project.ts +164 -0
- package/src/tools/projects-manage-task.ts +108 -0
- package/src/triggers/crm-record-events.ts +143 -0
- package/src/triggers/desk-events.ts +121 -0
- package/src/triggers/index.ts +2 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
import { createAxios } from 'slates';
|
|
2
|
+
import { getApiBaseUrl, getDeskBaseUrl, getPeopleBaseUrl, getProjectsBaseUrl } from './urls';
|
|
3
|
+
import type { Datacenter } from './urls';
|
|
4
|
+
import { zohoApiError } from './errors';
|
|
5
|
+
|
|
6
|
+
let createZohoAxios = (config: Parameters<typeof createAxios>[0], operation: string) => {
|
|
7
|
+
let http = createAxios(config);
|
|
8
|
+
let interceptors = (http as any).interceptors;
|
|
9
|
+
|
|
10
|
+
interceptors?.response?.use(
|
|
11
|
+
(response: unknown) => response,
|
|
12
|
+
(error: unknown) => Promise.reject(zohoApiError(error, operation))
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return http;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
let toFormData = (data: Record<string, any>) => {
|
|
19
|
+
let form = new URLSearchParams();
|
|
20
|
+
for (let [key, value] of Object.entries(data)) {
|
|
21
|
+
if (value !== undefined && value !== null) {
|
|
22
|
+
form.set(key, String(value));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return form;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export class ZohoCrmClient {
|
|
29
|
+
private http;
|
|
30
|
+
|
|
31
|
+
constructor(opts: { token: string; datacenter: Datacenter }) {
|
|
32
|
+
let baseUrl = getApiBaseUrl(opts.datacenter);
|
|
33
|
+
this.http = createZohoAxios(
|
|
34
|
+
{
|
|
35
|
+
baseURL: `${baseUrl}/crm/v7`,
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Zoho-oauthtoken ${opts.token}`
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
'CRM request'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async getRecords(
|
|
45
|
+
module: string,
|
|
46
|
+
params?: {
|
|
47
|
+
fields?: string;
|
|
48
|
+
page?: number;
|
|
49
|
+
perPage?: number;
|
|
50
|
+
sortBy?: string;
|
|
51
|
+
sortOrder?: string;
|
|
52
|
+
cvid?: string;
|
|
53
|
+
ids?: string;
|
|
54
|
+
pageToken?: string;
|
|
55
|
+
converted?: 'true' | 'false' | 'both';
|
|
56
|
+
territoryId?: string;
|
|
57
|
+
includeChild?: boolean;
|
|
58
|
+
}
|
|
59
|
+
) {
|
|
60
|
+
let response = await this.http.get(`/${module}`, {
|
|
61
|
+
params: {
|
|
62
|
+
fields: params?.fields,
|
|
63
|
+
page: params?.page,
|
|
64
|
+
per_page: params?.perPage,
|
|
65
|
+
page_token: params?.pageToken,
|
|
66
|
+
sort_by: params?.sortBy,
|
|
67
|
+
sort_order: params?.sortOrder,
|
|
68
|
+
cvid: params?.cvid,
|
|
69
|
+
ids: params?.ids,
|
|
70
|
+
converted: params?.converted,
|
|
71
|
+
territory_id: params?.territoryId,
|
|
72
|
+
include_child: params?.includeChild
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return response.data;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async getRecord(module: string, recordId: string, fields?: string) {
|
|
79
|
+
let response = await this.http.get(`/${module}/${recordId}`, {
|
|
80
|
+
params: { fields }
|
|
81
|
+
});
|
|
82
|
+
return response.data;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async createRecords(module: string, records: Record<string, any>[], trigger?: string[]) {
|
|
86
|
+
let body: Record<string, any> = { data: records };
|
|
87
|
+
if (trigger && trigger.length > 0) body.trigger = trigger;
|
|
88
|
+
let response = await this.http.post(`/${module}`, body);
|
|
89
|
+
return response.data;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async updateRecord(
|
|
93
|
+
module: string,
|
|
94
|
+
recordId: string,
|
|
95
|
+
data: Record<string, any>,
|
|
96
|
+
trigger?: string[]
|
|
97
|
+
) {
|
|
98
|
+
let body: Record<string, any> = { data: [{ ...data, id: recordId }] };
|
|
99
|
+
if (trigger && trigger.length > 0) body.trigger = trigger;
|
|
100
|
+
let response = await this.http.put(`/${module}`, body);
|
|
101
|
+
return response.data;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async deleteRecord(module: string, recordId: string) {
|
|
105
|
+
let response = await this.http.delete(`/${module}`, { params: { ids: recordId } });
|
|
106
|
+
return response.data;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async searchRecords(
|
|
110
|
+
module: string,
|
|
111
|
+
params: {
|
|
112
|
+
criteria?: string;
|
|
113
|
+
email?: string;
|
|
114
|
+
phone?: string;
|
|
115
|
+
word?: string;
|
|
116
|
+
page?: number;
|
|
117
|
+
perPage?: number;
|
|
118
|
+
fields?: string;
|
|
119
|
+
converted?: 'true' | 'false' | 'both';
|
|
120
|
+
approved?: 'true' | 'false' | 'both';
|
|
121
|
+
userType?: string;
|
|
122
|
+
}
|
|
123
|
+
) {
|
|
124
|
+
let response = await this.http.get(`/${module}/search`, {
|
|
125
|
+
params: {
|
|
126
|
+
criteria: params.criteria,
|
|
127
|
+
email: params.email,
|
|
128
|
+
phone: params.phone,
|
|
129
|
+
word: params.word,
|
|
130
|
+
page: params.page,
|
|
131
|
+
per_page: params.perPage,
|
|
132
|
+
fields: params.fields,
|
|
133
|
+
converted: params.converted,
|
|
134
|
+
approved: params.approved,
|
|
135
|
+
type: params.userType
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return response.data;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async getRelatedRecords(
|
|
142
|
+
module: string,
|
|
143
|
+
recordId: string,
|
|
144
|
+
relatedListApiName: string,
|
|
145
|
+
params: {
|
|
146
|
+
fields: string;
|
|
147
|
+
page?: number;
|
|
148
|
+
perPage?: number;
|
|
149
|
+
pageToken?: string;
|
|
150
|
+
ids?: string;
|
|
151
|
+
sortBy?: string;
|
|
152
|
+
sortOrder?: string;
|
|
153
|
+
converted?: 'true' | 'false' | 'both';
|
|
154
|
+
}
|
|
155
|
+
) {
|
|
156
|
+
let response = await this.http.get(`/${module}/${recordId}/${relatedListApiName}`, {
|
|
157
|
+
params: {
|
|
158
|
+
fields: params.fields,
|
|
159
|
+
page: params.page,
|
|
160
|
+
per_page: params.perPage,
|
|
161
|
+
page_token: params.pageToken,
|
|
162
|
+
ids: params.ids,
|
|
163
|
+
sort_by: params.sortBy,
|
|
164
|
+
sort_order: params.sortOrder,
|
|
165
|
+
converted: params.converted
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return response.data;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async executeCoql(query: string) {
|
|
172
|
+
let response = await this.http.post('/coql', { select_query: query });
|
|
173
|
+
return response.data;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async getModules(params?: { status?: string }) {
|
|
177
|
+
let response = await this.http.get('/settings/modules', {
|
|
178
|
+
params: {
|
|
179
|
+
status: params?.status
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
return response.data;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async getUsers(params?: { type?: string; page?: number; perPage?: number }) {
|
|
186
|
+
let response = await this.http.get('/users', {
|
|
187
|
+
params: {
|
|
188
|
+
type: params?.type,
|
|
189
|
+
page: params?.page,
|
|
190
|
+
per_page: params?.perPage
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
return response.data;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async enableNotifications(
|
|
197
|
+
watchData: Array<{
|
|
198
|
+
channelId: string;
|
|
199
|
+
events: string[];
|
|
200
|
+
notifyUrl: string;
|
|
201
|
+
token?: string;
|
|
202
|
+
channelExpiry?: string;
|
|
203
|
+
returnAffectedFieldValues?: boolean;
|
|
204
|
+
}>
|
|
205
|
+
) {
|
|
206
|
+
let response = await this.http.post('/actions/watch', {
|
|
207
|
+
watch: watchData.map(w => ({
|
|
208
|
+
channel_id: w.channelId,
|
|
209
|
+
events: w.events,
|
|
210
|
+
notify_url: w.notifyUrl,
|
|
211
|
+
token: w.token,
|
|
212
|
+
channel_expiry: w.channelExpiry,
|
|
213
|
+
return_affected_field_values: w.returnAffectedFieldValues
|
|
214
|
+
}))
|
|
215
|
+
});
|
|
216
|
+
return response.data;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async disableNotifications(channelIds: string[]) {
|
|
220
|
+
let response = await this.http.delete('/actions/watch', {
|
|
221
|
+
params: { channel_ids: channelIds.join(',') }
|
|
222
|
+
});
|
|
223
|
+
return response.data;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async getNotificationDetails() {
|
|
227
|
+
let response = await this.http.get('/actions/watch');
|
|
228
|
+
return response.data;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export class ZohoDeskClient {
|
|
233
|
+
private http;
|
|
234
|
+
|
|
235
|
+
constructor(opts: { token: string; datacenter: Datacenter; orgId: string }) {
|
|
236
|
+
let baseUrl = getDeskBaseUrl(opts.datacenter);
|
|
237
|
+
this.http = createZohoAxios(
|
|
238
|
+
{
|
|
239
|
+
baseURL: `${baseUrl}/api/v1`,
|
|
240
|
+
headers: {
|
|
241
|
+
Authorization: `Zoho-oauthtoken ${opts.token}`,
|
|
242
|
+
orgId: opts.orgId
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
'Desk request'
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async listTickets(params?: {
|
|
250
|
+
from?: number;
|
|
251
|
+
limit?: number;
|
|
252
|
+
departmentId?: string;
|
|
253
|
+
status?: string;
|
|
254
|
+
sortBy?: string;
|
|
255
|
+
sortOrder?: string;
|
|
256
|
+
}) {
|
|
257
|
+
let response = await this.http.get('/tickets', {
|
|
258
|
+
params: {
|
|
259
|
+
from: params?.from,
|
|
260
|
+
limit: params?.limit,
|
|
261
|
+
departmentId: params?.departmentId,
|
|
262
|
+
status: params?.status,
|
|
263
|
+
sortBy: params?.sortBy,
|
|
264
|
+
sortOrder: params?.sortOrder
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
return response.data;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async getTicket(ticketId: string) {
|
|
271
|
+
let response = await this.http.get(`/tickets/${ticketId}`);
|
|
272
|
+
return response.data;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async createTicket(data: Record<string, any>) {
|
|
276
|
+
let response = await this.http.post('/tickets', data);
|
|
277
|
+
return response.data;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async updateTicket(ticketId: string, data: Record<string, any>) {
|
|
281
|
+
let response = await this.http.patch(`/tickets/${ticketId}`, data);
|
|
282
|
+
return response.data;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async deleteTicket(ticketId: string) {
|
|
286
|
+
let response = await this.http.post('/tickets/moveToTrash', {
|
|
287
|
+
ticketIds: [ticketId]
|
|
288
|
+
});
|
|
289
|
+
return response.data;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async listContacts(params?: { from?: number; limit?: number; sortBy?: string }) {
|
|
293
|
+
let response = await this.http.get('/contacts', { params });
|
|
294
|
+
return response.data;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async getContact(contactId: string) {
|
|
298
|
+
let response = await this.http.get(`/contacts/${contactId}`);
|
|
299
|
+
return response.data;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async createContact(data: Record<string, any>) {
|
|
303
|
+
let response = await this.http.post('/contacts', data);
|
|
304
|
+
return response.data;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async updateContact(contactId: string, data: Record<string, any>) {
|
|
308
|
+
let response = await this.http.patch(`/contacts/${contactId}`, data);
|
|
309
|
+
return response.data;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async deleteContact(contactId: string) {
|
|
313
|
+
let response = await this.http.post('/contacts/moveToTrash', {
|
|
314
|
+
contactIds: [contactId]
|
|
315
|
+
});
|
|
316
|
+
return response.data;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
static async listOrganizations(token: string, datacenter: Datacenter) {
|
|
320
|
+
let baseUrl = getDeskBaseUrl(datacenter);
|
|
321
|
+
let http = createZohoAxios(
|
|
322
|
+
{
|
|
323
|
+
baseURL: `${baseUrl}/api/v1`,
|
|
324
|
+
headers: { Authorization: `Zoho-oauthtoken ${token}` }
|
|
325
|
+
},
|
|
326
|
+
'Desk organizations request'
|
|
327
|
+
);
|
|
328
|
+
let response = await http.get('/organizations');
|
|
329
|
+
return response.data;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async searchTickets(params: {
|
|
333
|
+
from?: number;
|
|
334
|
+
limit?: number;
|
|
335
|
+
departmentId?: string;
|
|
336
|
+
searchStr?: string;
|
|
337
|
+
statusType?: string;
|
|
338
|
+
}) {
|
|
339
|
+
let response = await this.http.get('/tickets/search', {
|
|
340
|
+
params: {
|
|
341
|
+
departmentId: params.departmentId,
|
|
342
|
+
from: params.from,
|
|
343
|
+
limit: params.limit,
|
|
344
|
+
searchStr: params.searchStr,
|
|
345
|
+
statusType: params.statusType
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
return response.data;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async getDepartments() {
|
|
352
|
+
let response = await this.http.get('/departments');
|
|
353
|
+
return response.data;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async createWebhook(data: {
|
|
357
|
+
name: string;
|
|
358
|
+
url: string;
|
|
359
|
+
isEnabled: boolean;
|
|
360
|
+
subscriptions: Array<{ event: string; departmentIds?: string[] }>;
|
|
361
|
+
}) {
|
|
362
|
+
let response = await this.http.post('/webhooks', data);
|
|
363
|
+
return response.data;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
async deleteWebhook(webhookId: string) {
|
|
367
|
+
let response = await this.http.delete(`/webhooks/${webhookId}`);
|
|
368
|
+
return response.data;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async listWebhooks() {
|
|
372
|
+
let response = await this.http.get('/webhooks');
|
|
373
|
+
return response.data;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export class ZohoBooksClient {
|
|
378
|
+
private http;
|
|
379
|
+
|
|
380
|
+
constructor(opts: { token: string; datacenter: Datacenter; organizationId: string }) {
|
|
381
|
+
let baseUrl = getApiBaseUrl(opts.datacenter);
|
|
382
|
+
this.http = createZohoAxios(
|
|
383
|
+
{
|
|
384
|
+
baseURL: `${baseUrl}/books/v3`,
|
|
385
|
+
headers: {
|
|
386
|
+
Authorization: `Zoho-oauthtoken ${opts.token}`
|
|
387
|
+
},
|
|
388
|
+
params: {
|
|
389
|
+
organization_id: opts.organizationId
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
'Books request'
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
static async listOrganizations(token: string, datacenter: Datacenter) {
|
|
397
|
+
let baseUrl = getApiBaseUrl(datacenter);
|
|
398
|
+
let http = createZohoAxios(
|
|
399
|
+
{
|
|
400
|
+
baseURL: `${baseUrl}/books/v3`,
|
|
401
|
+
headers: { Authorization: `Zoho-oauthtoken ${token}` }
|
|
402
|
+
},
|
|
403
|
+
'Books organizations request'
|
|
404
|
+
);
|
|
405
|
+
let response = await http.get('/organizations');
|
|
406
|
+
return response.data;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async listInvoices(params?: {
|
|
410
|
+
page?: number;
|
|
411
|
+
perPage?: number;
|
|
412
|
+
status?: string;
|
|
413
|
+
customerId?: string;
|
|
414
|
+
sortColumn?: string;
|
|
415
|
+
sortOrder?: string;
|
|
416
|
+
}) {
|
|
417
|
+
let response = await this.http.get('/invoices', {
|
|
418
|
+
params: {
|
|
419
|
+
page: params?.page,
|
|
420
|
+
per_page: params?.perPage,
|
|
421
|
+
status: params?.status,
|
|
422
|
+
customer_id: params?.customerId,
|
|
423
|
+
sort_column: params?.sortColumn,
|
|
424
|
+
sort_order: params?.sortOrder
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
return response.data;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
async getInvoice(invoiceId: string) {
|
|
431
|
+
let response = await this.http.get(`/invoices/${invoiceId}`);
|
|
432
|
+
return response.data;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
async createInvoice(data: Record<string, any>) {
|
|
436
|
+
let response = await this.http.post('/invoices', data);
|
|
437
|
+
return response.data;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async updateInvoice(invoiceId: string, data: Record<string, any>) {
|
|
441
|
+
let response = await this.http.put(`/invoices/${invoiceId}`, data);
|
|
442
|
+
return response.data;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
async deleteInvoice(invoiceId: string) {
|
|
446
|
+
let response = await this.http.delete(`/invoices/${invoiceId}`);
|
|
447
|
+
return response.data;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async markInvoiceStatus(invoiceId: string, status: string) {
|
|
451
|
+
let response = await this.http.post(`/invoices/${invoiceId}/status/${status}`);
|
|
452
|
+
return response.data;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
async listContacts(params?: {
|
|
456
|
+
page?: number;
|
|
457
|
+
perPage?: number;
|
|
458
|
+
contactType?: string;
|
|
459
|
+
sortColumn?: string;
|
|
460
|
+
sortOrder?: string;
|
|
461
|
+
}) {
|
|
462
|
+
let response = await this.http.get('/contacts', {
|
|
463
|
+
params: {
|
|
464
|
+
page: params?.page,
|
|
465
|
+
per_page: params?.perPage,
|
|
466
|
+
contact_type: params?.contactType,
|
|
467
|
+
sort_column: params?.sortColumn,
|
|
468
|
+
sort_order: params?.sortOrder
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
return response.data;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async getContact(contactId: string) {
|
|
475
|
+
let response = await this.http.get(`/contacts/${contactId}`);
|
|
476
|
+
return response.data;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async createContact(data: Record<string, any>) {
|
|
480
|
+
let response = await this.http.post('/contacts', data);
|
|
481
|
+
return response.data;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
async updateContact(contactId: string, data: Record<string, any>) {
|
|
485
|
+
let response = await this.http.put(`/contacts/${contactId}`, data);
|
|
486
|
+
return response.data;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
async deleteContact(contactId: string) {
|
|
490
|
+
let response = await this.http.delete(`/contacts/${contactId}`);
|
|
491
|
+
return response.data;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
async listExpenses(params?: {
|
|
495
|
+
page?: number;
|
|
496
|
+
perPage?: number;
|
|
497
|
+
status?: string;
|
|
498
|
+
sortColumn?: string;
|
|
499
|
+
sortOrder?: string;
|
|
500
|
+
}) {
|
|
501
|
+
let response = await this.http.get('/expenses', {
|
|
502
|
+
params: {
|
|
503
|
+
page: params?.page,
|
|
504
|
+
per_page: params?.perPage,
|
|
505
|
+
status: params?.status,
|
|
506
|
+
sort_column: params?.sortColumn,
|
|
507
|
+
sort_order: params?.sortOrder
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
return response.data;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
async getExpense(expenseId: string) {
|
|
514
|
+
let response = await this.http.get(`/expenses/${expenseId}`);
|
|
515
|
+
return response.data;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
async createExpense(data: Record<string, any>) {
|
|
519
|
+
let response = await this.http.post('/expenses', data);
|
|
520
|
+
return response.data;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
async updateExpense(expenseId: string, data: Record<string, any>) {
|
|
524
|
+
let response = await this.http.put(`/expenses/${expenseId}`, data);
|
|
525
|
+
return response.data;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
async deleteExpense(expenseId: string) {
|
|
529
|
+
let response = await this.http.delete(`/expenses/${expenseId}`);
|
|
530
|
+
return response.data;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export class ZohoPeopleClient {
|
|
535
|
+
private http;
|
|
536
|
+
|
|
537
|
+
constructor(opts: { token: string; datacenter: Datacenter }) {
|
|
538
|
+
let baseUrl = getPeopleBaseUrl(opts.datacenter);
|
|
539
|
+
this.http = createZohoAxios(
|
|
540
|
+
{
|
|
541
|
+
baseURL: `${baseUrl}/people/api`,
|
|
542
|
+
headers: {
|
|
543
|
+
Authorization: `Zoho-oauthtoken ${opts.token}`
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
'People request'
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
async getFormRecords(
|
|
551
|
+
formLinkName: string,
|
|
552
|
+
params?: {
|
|
553
|
+
sIndex?: number;
|
|
554
|
+
limit?: number;
|
|
555
|
+
searchColumn?: string;
|
|
556
|
+
searchValue?: string;
|
|
557
|
+
}
|
|
558
|
+
) {
|
|
559
|
+
let response = await this.http.get(`/forms/${formLinkName}/getRecords`, {
|
|
560
|
+
params: {
|
|
561
|
+
sIndex: params?.sIndex ?? 1,
|
|
562
|
+
limit: params?.limit ?? 200,
|
|
563
|
+
searchColumn: params?.searchColumn,
|
|
564
|
+
searchValue: params?.searchValue
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
return response.data;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
async listForms() {
|
|
571
|
+
let response = await this.http.get('/forms');
|
|
572
|
+
return response.data;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
async getFormRecordById(formLinkName: string, recordId: string) {
|
|
576
|
+
let response = await this.http.get(`/forms/${formLinkName}/getDataByID`, {
|
|
577
|
+
params: { recordId }
|
|
578
|
+
});
|
|
579
|
+
return response.data;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
async insertFormRecord(formLinkName: string, data: Record<string, any>) {
|
|
583
|
+
let response = await this.http.post(`/forms/json/${formLinkName}/insertRecord`, null, {
|
|
584
|
+
params: { inputData: JSON.stringify(data) }
|
|
585
|
+
});
|
|
586
|
+
return response.data;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async updateFormRecord(formLinkName: string, recordId: string, data: Record<string, any>) {
|
|
590
|
+
let response = await this.http.post(`/forms/json/${formLinkName}/updateRecord`, null, {
|
|
591
|
+
params: { inputData: JSON.stringify(data), recordId }
|
|
592
|
+
});
|
|
593
|
+
return response.data;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
async getLeaveTypes() {
|
|
597
|
+
let response = await this.http.get('/leave/getLeaveTypeDetails');
|
|
598
|
+
return response.data;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
async getAttendanceEntries(params: { sdate: string; edate: string; empId?: string }) {
|
|
602
|
+
let response = await this.http.get('/attendance/getAttendanceEntries', { params });
|
|
603
|
+
return response.data;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export class ZohoProjectsClient {
|
|
608
|
+
private http;
|
|
609
|
+
|
|
610
|
+
constructor(opts: { token: string; datacenter: Datacenter; portalId: string }) {
|
|
611
|
+
let baseUrl = getProjectsBaseUrl(opts.datacenter);
|
|
612
|
+
this.http = createZohoAxios(
|
|
613
|
+
{
|
|
614
|
+
baseURL: `${baseUrl}/restapi/portal/${opts.portalId}`,
|
|
615
|
+
headers: {
|
|
616
|
+
Authorization: `Zoho-oauthtoken ${opts.token}`
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
'Projects request'
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
static async listPortals(token: string, datacenter: Datacenter) {
|
|
624
|
+
let baseUrl = getProjectsBaseUrl(datacenter);
|
|
625
|
+
let http = createZohoAxios(
|
|
626
|
+
{
|
|
627
|
+
baseURL: `${baseUrl}/restapi`,
|
|
628
|
+
headers: { Authorization: `Zoho-oauthtoken ${token}` }
|
|
629
|
+
},
|
|
630
|
+
'Projects portals request'
|
|
631
|
+
);
|
|
632
|
+
let response = await http.get('/portals/');
|
|
633
|
+
return response.data;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
async listProjects(params?: {
|
|
637
|
+
index?: number;
|
|
638
|
+
range?: number;
|
|
639
|
+
status?: string;
|
|
640
|
+
sortBy?: string;
|
|
641
|
+
sortOrder?: string;
|
|
642
|
+
}) {
|
|
643
|
+
let response = await this.http.get('/projects/', {
|
|
644
|
+
params: {
|
|
645
|
+
index: params?.index,
|
|
646
|
+
range: params?.range,
|
|
647
|
+
status: params?.status,
|
|
648
|
+
sort_column: params?.sortBy,
|
|
649
|
+
sort_order: params?.sortOrder
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
return response.data;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
async getProject(projectId: string) {
|
|
656
|
+
let response = await this.http.get(`/projects/${projectId}/`);
|
|
657
|
+
return response.data;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
async createProject(data: Record<string, any>) {
|
|
661
|
+
let response = await this.http.post('/projects/', toFormData(data));
|
|
662
|
+
return response.data;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
async updateProject(projectId: string, data: Record<string, any>) {
|
|
666
|
+
let response = await this.http.post(`/projects/${projectId}/`, toFormData(data));
|
|
667
|
+
return response.data;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
async deleteProject(projectId: string) {
|
|
671
|
+
let response = await this.http.delete(`/projects/${projectId}/`);
|
|
672
|
+
return response.data;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
async listTasks(
|
|
676
|
+
projectId: string,
|
|
677
|
+
params?: {
|
|
678
|
+
index?: number;
|
|
679
|
+
range?: number;
|
|
680
|
+
status?: string;
|
|
681
|
+
}
|
|
682
|
+
) {
|
|
683
|
+
let response = await this.http.get(`/projects/${projectId}/tasks/`, {
|
|
684
|
+
params: {
|
|
685
|
+
index: params?.index,
|
|
686
|
+
range: params?.range,
|
|
687
|
+
status: params?.status
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
return response.data;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
async getTask(projectId: string, taskId: string) {
|
|
694
|
+
let response = await this.http.get(`/projects/${projectId}/tasks/${taskId}/`);
|
|
695
|
+
return response.data;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
async createTask(projectId: string, data: Record<string, any>) {
|
|
699
|
+
let response = await this.http.post(`/projects/${projectId}/tasks/`, toFormData(data));
|
|
700
|
+
return response.data;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
async updateTask(projectId: string, taskId: string, data: Record<string, any>) {
|
|
704
|
+
let response = await this.http.post(
|
|
705
|
+
`/projects/${projectId}/tasks/${taskId}/`,
|
|
706
|
+
toFormData(data)
|
|
707
|
+
);
|
|
708
|
+
return response.data;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
async deleteTask(projectId: string, taskId: string) {
|
|
712
|
+
let response = await this.http.delete(`/projects/${projectId}/tasks/${taskId}/`);
|
|
713
|
+
return response.data;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
async listMilestones(
|
|
717
|
+
projectId: string,
|
|
718
|
+
params?: {
|
|
719
|
+
index?: number;
|
|
720
|
+
range?: number;
|
|
721
|
+
status?: string;
|
|
722
|
+
}
|
|
723
|
+
) {
|
|
724
|
+
let response = await this.http.get(`/projects/${projectId}/milestones/`, {
|
|
725
|
+
params: {
|
|
726
|
+
index: params?.index,
|
|
727
|
+
range: params?.range,
|
|
728
|
+
status: params?.status
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
return response.data;
|
|
732
|
+
}
|
|
733
|
+
}
|