@pipedream/harvest 0.1.0 → 1.0.0

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.
Files changed (43) hide show
  1. package/actions/create-invoice/create-invoice.mjs +116 -0
  2. package/actions/create-project/create-project.mjs +138 -0
  3. package/actions/create-task-assignment/create-task-assignment.mjs +77 -0
  4. package/actions/create-timesheet-entry/create-timesheet-entry.mjs +34 -38
  5. package/actions/create-user/create-user.mjs +109 -0
  6. package/actions/create-user-assignment/create-user-assignment.mjs +85 -0
  7. package/actions/delete-invoice/delete-invoice.mjs +38 -0
  8. package/actions/delete-project/delete-project.mjs +38 -0
  9. package/actions/delete-task-assignment/delete-task-assignment.mjs +45 -0
  10. package/actions/delete-time-entry/delete-time-entry.mjs +38 -0
  11. package/actions/delete-user/delete-user.mjs +39 -0
  12. package/actions/delete-user-assignment/delete-user-assignment.mjs +45 -0
  13. package/actions/get-invoice/get-invoice.mjs +39 -0
  14. package/actions/get-me/get-me.mjs +32 -0
  15. package/actions/get-project/get-project.mjs +39 -0
  16. package/actions/get-projects/get-projects.mjs +15 -12
  17. package/actions/get-task-assignment/get-task-assignment.mjs +46 -0
  18. package/actions/get-time-entry/get-time-entry.mjs +39 -0
  19. package/actions/get-time-report/get-time-report.mjs +80 -0
  20. package/actions/get-user/get-user.mjs +40 -0
  21. package/actions/get-user-assignment/get-user-assignment.mjs +46 -0
  22. package/actions/list-account-id-options/list-account-id-options.mjs +12 -3
  23. package/actions/list-clients/list-clients.mjs +57 -0
  24. package/actions/list-invoices/list-invoices.mjs +86 -0
  25. package/actions/list-task-assignments/list-task-assignments.mjs +66 -0
  26. package/actions/list-tasks/list-tasks.mjs +57 -0
  27. package/actions/list-time-entries/list-time-entries.mjs +150 -0
  28. package/actions/list-user-assignments/list-user-assignments.mjs +74 -0
  29. package/actions/list-users/list-users.mjs +57 -0
  30. package/actions/start-timer/start-timer.mjs +5 -7
  31. package/actions/stop-timer/stop-timer.mjs +5 -7
  32. package/actions/update-invoice/update-invoice.mjs +114 -0
  33. package/actions/update-project/update-project.mjs +140 -0
  34. package/actions/update-task-assignment/update-task-assignment.mjs +77 -0
  35. package/actions/update-time-entry/update-time-entry.mjs +92 -0
  36. package/actions/update-user/update-user.mjs +106 -0
  37. package/actions/update-user-assignment/update-user-assignment.mjs +84 -0
  38. package/common/constants.mjs +51 -1
  39. package/common/utils.mjs +50 -1
  40. package/harvest.app.mjs +683 -110
  41. package/package.json +1 -1
  42. package/sources/new-invoice-entry/new-invoice-entry.mjs +1 -1
  43. package/sources/new-timesheet-entry/new-timesheet-entry.mjs +1 -1
package/harvest.app.mjs CHANGED
@@ -1,7 +1,5 @@
1
1
  import constants from "./common/constants.mjs";
2
- import {
3
- axios, ConfigurationError,
4
- } from "@pipedream/platform";
2
+ import { axios } from "@pipedream/platform";
5
3
  import retry from "async-retry";
6
4
 
7
5
  export default {
@@ -11,116 +9,279 @@ export default {
11
9
  projectId: {
12
10
  type: "string",
13
11
  label: "Project ID",
14
- description: "The ID of the project to associate with the time entry",
15
- useQuery: true,
16
- async options({
17
- page, accountId,
18
- }) {
19
- const response = await this.listProjects({
20
- perPage: constants.PAGE_SIZE,
21
- page: page + 1,
22
- accountId,
23
- });
24
- return response.projects.map((project) => ({
25
- label: project.name,
26
- value: project.id,
27
- }));
28
- },
12
+ description: "Free-form project ID, e.g. `14308069`. Run **Get Projects** first to find valid IDs.",
29
13
  },
30
14
  taskId: {
31
15
  type: "string",
32
16
  label: "Task ID",
33
- description: "The ID of the task to associate with the time entry",
34
- useQuery: true,
35
- async options({
36
- page, accountId,
37
- }) {
38
- const response = await this.listTasks({
39
- perPage: constants.PAGE_SIZE,
40
- page: page + 1,
41
- accountId,
42
- });
43
- return response.tasks.map((task) => ({
44
- label: task.name,
45
- value: task.id,
46
- }));
47
- },
17
+ description: "Free-form task ID, e.g. `1467097`. Run **List Tasks** first to find valid IDs.",
48
18
  },
49
19
  userId: {
50
20
  type: "string",
51
21
  label: "User ID",
52
- description: "The ID of the user to associate with the time entry",
53
- useQuery: true,
54
- optional: true,
55
- async options({
56
- page, accountId,
57
- }) {
58
- const response = await this.listUsers({
59
- perPage: constants.PAGE_SIZE,
60
- page: page + 1,
61
- accountId,
62
- });
63
- return response.users.map((user) => ({
64
- label: `${user.first_name} ${user.last_name}`,
65
- value: user.id,
66
- }));
67
- },
22
+ description: "Free-form user ID, e.g. `1782959`. Run **List Users** first to find valid IDs.",
23
+ optional: true,
68
24
  },
69
25
  clientId: {
70
26
  type: "string",
71
27
  label: "Client ID",
72
- description: "The ID of the client to associate with time entries",
73
- useQuery: true,
74
- optional: true,
75
- async options({
76
- page, accountId,
77
- }) {
78
- const response = await this.listClients({
79
- perPage: constants.PAGE_SIZE,
80
- page: page + 1,
81
- accountId,
82
- });
83
- return response.clients.map((client) => ({
84
- label: client.name,
85
- value: client.id,
86
- }));
87
- },
28
+ description: "Free-form client ID, e.g. `5735776`. Run **List Clients** first to find valid IDs.",
29
+ optional: true,
88
30
  },
89
31
  timeEntryId: {
90
32
  type: "string",
91
- label: "Time entry ID",
92
- description: "The ID of the time entry.",
93
- useQuery: true,
94
- async options({
95
- page, isRunning, accountId,
96
- }) {
97
- const response = await this.listTimeEntries({
98
- perPage: constants.PAGE_SIZE,
99
- page: page + 1,
100
- is_running: isRunning,
101
- accountId,
102
- });
103
- return response.time_entries.map((entry) => ({
104
- label: `Project: ${entry.project.name}, Task: ${entry.task.name}, Spend date: ${entry.spent_date} ${entry.started_time || ""} ${entry.ended_time
105
- ? " to " + entry.ended_time
106
- : ""}`,
107
- value: entry.id,
108
- }));
109
- },
33
+ label: "Time Entry ID",
34
+ description: "Free-form time entry ID, e.g. `636708723`. Run **List Time Entries** first to find valid IDs.",
35
+ },
36
+ invoiceId: {
37
+ type: "string",
38
+ label: "Invoice ID",
39
+ description: "Free-form invoice ID, e.g. `13150403`. Run **List Invoices** first to find valid IDs.",
40
+ },
41
+ taskAssignmentId: {
42
+ type: "string",
43
+ label: "Task Assignment ID",
44
+ description: "Free-form task assignment ID, e.g. `162728`. Run **List Task Assignments** first to find valid IDs.",
45
+ },
46
+ userAssignmentId: {
47
+ type: "string",
48
+ label: "User Assignment ID",
49
+ description: "Free-form user assignment ID, e.g. `195420`. Run **List User Assignments** first to find valid IDs.",
110
50
  },
111
51
  accountId: {
112
52
  type: "string",
113
53
  label: "Account ID",
114
- description: "The ID of your account",
115
- async options() {
116
- const { accounts } = await this.listAccounts({});
117
- return accounts.map(({
118
- id, name,
119
- }) => ({
120
- label: name,
121
- value: id,
122
- }));
123
- },
54
+ description: "Your Harvest account ID, e.g. `1234567`. Run **List Account ID Options** to find it.",
55
+ },
56
+ isActive: {
57
+ type: "boolean",
58
+ label: "Is Active",
59
+ description: "Whether the record is active.",
60
+ optional: true,
61
+ },
62
+ updatedSince: {
63
+ type: "string",
64
+ label: "Updated Since",
65
+ description: "Only return records updated since this UTC datetime, e.g. `2019-06-25T15:30:00Z`.",
66
+ optional: true,
67
+ },
68
+ accessRoles: {
69
+ type: "string[]",
70
+ label: "Access Roles",
71
+ description: "Access roles for the user. One of `member`, `manager`, `administrator`; or one of `project_creator`, `billable_rates_manager`, `managed_projects_invoice_drafter`, `managed_projects_invoice_manager`, `client_and_task_manager`, `time_and_expenses_manager`, `estimates_manager` — these additional roles can only be combined with `manager`.",
72
+ optional: true,
73
+ options: constants.ACCESS_ROLE_OPTIONS,
74
+ },
75
+ // Project
76
+ projectName: {
77
+ type: "string",
78
+ label: "Project Name",
79
+ description: "The name of the project. Run **Get Project** or **Get Projects** to see names on existing projects.",
80
+ optional: true,
81
+ },
82
+ isBillable: {
83
+ type: "boolean",
84
+ label: "Is Billable",
85
+ description: "Whether the project is billable.",
86
+ optional: true,
87
+ },
88
+ billBy: {
89
+ type: "string",
90
+ label: "Bill By",
91
+ description: "Method by which the project is invoiced. One of: `Project`, `Tasks`, `People`, `none`.",
92
+ optional: true,
93
+ options: constants.BILL_BY_OPTIONS,
94
+ },
95
+ budgetBy: {
96
+ type: "string",
97
+ label: "Budget By",
98
+ description: "Method by which the project is budgeted. `project`, `task`, and `person` budget in hours (set Budget); `project_cost` and `task_fees` budget in money (set Cost Budget); `none` sets no budget.",
99
+ optional: true,
100
+ options: constants.BUDGET_BY_OPTIONS,
101
+ },
102
+ code: {
103
+ type: "string",
104
+ label: "Code",
105
+ description: "The code associated with the project, e.g. `PRJ-100`. Run **Get Project** or **Get Projects** to see codes on existing projects.",
106
+ optional: true,
107
+ },
108
+ isFixedFee: {
109
+ type: "boolean",
110
+ label: "Is Fixed Fee",
111
+ description: "Whether the project is a fixed-fee project.",
112
+ optional: true,
113
+ },
114
+ projectHourlyRate: {
115
+ type: "string",
116
+ label: "Hourly Rate",
117
+ description: "Rate for projects billed by Project Hourly Rate, decimal, e.g. `150` or `150.00`. Run **Get Project** to see the current rate.",
118
+ optional: true,
119
+ },
120
+ projectBudget: {
121
+ type: "string",
122
+ label: "Budget",
123
+ description: "The budget in **hours**, decimal, e.g. `120` or `120.5`. Only applies when Budget By is `project`, `task`, or `person`. Run **Get Project** to see the current budget.",
124
+ optional: true,
125
+ },
126
+ costBudget: {
127
+ type: "string",
128
+ label: "Cost Budget",
129
+ description: "The budget in **money**, decimal, e.g. `10000` or `10000.00`. Only applies when Budget By is `project_cost` or `task_fees`. Run **Get Project** to see the current cost budget.",
130
+ optional: true,
131
+ },
132
+ projectNotes: {
133
+ type: "string",
134
+ label: "Notes",
135
+ description: "Notes about the project. Run **Get Project** to see any existing notes.",
136
+ optional: true,
137
+ },
138
+ startsOn: {
139
+ type: "string",
140
+ label: "Starts On",
141
+ description: "Start date, format `YYYY-MM-DD`, e.g. `2026-09-01`. Run **Get Project** to see the current start date.",
142
+ optional: true,
143
+ },
144
+ endsOn: {
145
+ type: "string",
146
+ label: "Ends On",
147
+ description: "End date, format `YYYY-MM-DD`, e.g. `2026-12-31`. Run **Get Project** to see the current end date.",
148
+ optional: true,
149
+ },
150
+ // Invoice
151
+ subject: {
152
+ type: "string",
153
+ label: "Subject",
154
+ description: "The invoice subject. Run **Get Invoice** to see the current subject.",
155
+ optional: true,
156
+ },
157
+ invoiceNumber: {
158
+ type: "string",
159
+ label: "Number",
160
+ description: "The invoice number, e.g. `1000`. Run **Get Invoice** to see the current number.",
161
+ optional: true,
162
+ },
163
+ purchaseOrder: {
164
+ type: "string",
165
+ label: "Purchase Order",
166
+ description: "The purchase order number, e.g. `PO-1234`. Run **Get Invoice** to see the current value.",
167
+ optional: true,
168
+ },
169
+ tax: {
170
+ type: "string",
171
+ label: "Tax",
172
+ description: "First tax rate percentage, decimal, e.g. `5.5` for 5.5%. Run **Get Invoice** to see the current rate.",
173
+ optional: true,
174
+ },
175
+ discount: {
176
+ type: "string",
177
+ label: "Discount",
178
+ description: "Discount percentage, decimal, e.g. `10` for 10%. Run **Get Invoice** to see the current discount.",
179
+ optional: true,
180
+ },
181
+ invoiceNotes: {
182
+ type: "string",
183
+ label: "Notes",
184
+ description: "Notes about the invoice. Run **Get Invoice** to see any existing notes.",
185
+ optional: true,
186
+ },
187
+ issueDate: {
188
+ type: "string",
189
+ label: "Issue Date",
190
+ description: "Issue date, `YYYY-MM-DD`, e.g. `2026-09-01`. Run **Get Invoice** to see the current issue date.",
191
+ optional: true,
192
+ },
193
+ dueDate: {
194
+ type: "string",
195
+ label: "Due Date",
196
+ description: "Due date, `YYYY-MM-DD`, e.g. `2026-09-30`. Run **Get Invoice** to see the current due date.",
197
+ optional: true,
198
+ },
199
+ // User
200
+ firstName: {
201
+ type: "string",
202
+ label: "First Name",
203
+ description: "The user's first name. Run **Get User** to see the current value.",
204
+ optional: true,
205
+ },
206
+ lastName: {
207
+ type: "string",
208
+ label: "Last Name",
209
+ description: "The user's last name. Run **Get User** to see the current value.",
210
+ optional: true,
211
+ },
212
+ email: {
213
+ type: "string",
214
+ label: "Email",
215
+ description: "The user's email address, e.g. `jane@example.com`. Run **Get User** to see the current value.",
216
+ optional: true,
217
+ },
218
+ timezone: {
219
+ type: "string",
220
+ label: "Timezone",
221
+ description: "The user's IANA timezone name, e.g. `America/Chicago`. Run **Get User** to see the current value.",
222
+ optional: true,
223
+ },
224
+ isContractor: {
225
+ type: "boolean",
226
+ label: "Is Contractor",
227
+ description: "Whether the user is a contractor.",
228
+ optional: true,
229
+ },
230
+ weeklyCapacity: {
231
+ type: "integer",
232
+ label: "Weekly Capacity",
233
+ description: "Expected weekly working capacity in seconds, e.g. `144000` for a 40-hour week. Run **Get User** to see the current value.",
234
+ optional: true,
235
+ },
236
+ defaultHourlyRate: {
237
+ type: "string",
238
+ label: "Default Hourly Rate",
239
+ description: "Default hourly rate, decimal, e.g. `150` or `150.00`. Run **Get User** to see the current rate.",
240
+ optional: true,
241
+ },
242
+ // Task assignment
243
+ billable: {
244
+ type: "boolean",
245
+ label: "Billable",
246
+ description: "Whether the task assignment is billable.",
247
+ optional: true,
248
+ },
249
+ taskAssignmentHourlyRate: {
250
+ type: "string",
251
+ label: "Hourly Rate",
252
+ description: "Rate used when the project's bill_by is Tasks, decimal, e.g. `150` or `150.00`. Run **Get Task Assignment** to see the current rate.",
253
+ optional: true,
254
+ },
255
+ taskAssignmentBudget: {
256
+ type: "string",
257
+ label: "Budget",
258
+ description: "Budget used when the project's budget_by is task or task_fees, decimal, e.g. `5000` or `5000.00`. Run **Get Task Assignment** to see the current budget.",
259
+ optional: true,
260
+ },
261
+ // User assignment
262
+ isProjectManager: {
263
+ type: "boolean",
264
+ label: "Is Project Manager",
265
+ description: "Whether the user is a project manager.",
266
+ optional: true,
267
+ },
268
+ useDefaultRates: {
269
+ type: "boolean",
270
+ label: "Use Default Rates",
271
+ description: "Whether to use the user's default rate.",
272
+ optional: true,
273
+ },
274
+ userAssignmentHourlyRate: {
275
+ type: "string",
276
+ label: "Hourly Rate",
277
+ description: "Custom hourly rate, decimal, e.g. `150` or `150.00`. Run **Get User Assignment** to see the current rate.",
278
+ optional: true,
279
+ },
280
+ userAssignmentBudget: {
281
+ type: "string",
282
+ label: "Budget",
283
+ description: "Budget used when budget_by is person, decimal, e.g. `5000` or `5000.00`. Run **Get User Assignment** to see the current budget.",
284
+ optional: true,
124
285
  },
125
286
  },
126
287
  methods: {
@@ -175,7 +336,7 @@ export default {
175
336
  });
176
337
  },
177
338
  _isRetriableStatusCode(statusCode) {
178
- constants.retriableStatusCodes.includes(statusCode);
339
+ return constants.RETRIABLE_STATUS_CODES.includes(statusCode);
179
340
  },
180
341
  async _withRetries(apiCall) {
181
342
  const retryOpts = {
@@ -188,27 +349,27 @@ export default {
188
349
 
189
350
  return data;
190
351
  } catch (err) {
191
- const { status = 500 } = err;
352
+ const status = err?.response?.status ?? err?.status ?? 500;
192
353
  if (!this._isRetriableStatusCode(status)) {
193
- bail(`
194
- Unexpected error (status code: ${status}):
195
- ${JSON.stringify(err.response)}
196
- `);
354
+ bail(err);
355
+ return;
197
356
  }
198
- throw new ConfigurationError("Could not get data");
357
+ throw err;
199
358
  }
200
359
  }, retryOpts);
201
360
  },
202
361
  async *listTimeEntriesPaginated({
203
- page, updatedSince, accountId,
362
+ page, $, accountId, updatedSince, ...params
204
363
  }) {
205
364
  do {
206
365
  const response = await this._withRetries(
207
366
  () => this.listTimeEntries({
208
367
  per_page: constants.PAGE_SIZE,
209
368
  page,
210
- updated_since: updatedSince,
369
+ $,
211
370
  accountId,
371
+ updated_since: updatedSince,
372
+ ...params,
212
373
  }),
213
374
  );
214
375
 
@@ -225,15 +386,17 @@ export default {
225
386
  } while (true);
226
387
  },
227
388
  async *listInvoicesPaginated({
228
- page, updatedSince, accountId,
389
+ page, $, accountId, updatedSince, ...params
229
390
  }) {
230
391
  do {
231
392
  const response = await this._withRetries(
232
393
  () => this.listInvoices({
233
394
  per_page: constants.PAGE_SIZE,
234
395
  page,
235
- updated_since: updatedSince,
396
+ $,
236
397
  accountId,
398
+ updated_since: updatedSince,
399
+ ...params,
237
400
  }),
238
401
  );
239
402
 
@@ -274,6 +437,139 @@ export default {
274
437
  page += 1;
275
438
  } while (true);
276
439
  },
440
+ async *listClientsPaginated({
441
+ page, $, accountId, isActive, updatedSince,
442
+ }) {
443
+ do {
444
+ const response = await this._withRetries(
445
+ () => this.listClients({
446
+ perPage: constants.PAGE_SIZE,
447
+ page,
448
+ $,
449
+ accountId,
450
+ isActive,
451
+ updatedSince,
452
+ }),
453
+ );
454
+
455
+ if (response.clients.length === 0) {
456
+ return;
457
+ }
458
+ for (const client of response.clients) {
459
+ yield client;
460
+ }
461
+ if (!response.next_page) {
462
+ return;
463
+ }
464
+ page += 1;
465
+ } while (true);
466
+ },
467
+ async *listTasksPaginated({
468
+ page, $, accountId, isActive, updatedSince,
469
+ }) {
470
+ do {
471
+ const response = await this._withRetries(
472
+ () => this.listTasks({
473
+ perPage: constants.PAGE_SIZE,
474
+ page,
475
+ $,
476
+ accountId,
477
+ isActive,
478
+ updatedSince,
479
+ }),
480
+ );
481
+
482
+ if (response.tasks.length === 0) {
483
+ return;
484
+ }
485
+ for (const task of response.tasks) {
486
+ yield task;
487
+ }
488
+ if (!response.next_page) {
489
+ return;
490
+ }
491
+ page += 1;
492
+ } while (true);
493
+ },
494
+ async *listUsersPaginated({
495
+ page, $, accountId, isActive, updatedSince,
496
+ }) {
497
+ do {
498
+ const response = await this._withRetries(
499
+ () => this.listUsers({
500
+ perPage: constants.PAGE_SIZE,
501
+ page,
502
+ $,
503
+ accountId,
504
+ isActive,
505
+ updatedSince,
506
+ }),
507
+ );
508
+
509
+ if (response.users.length === 0) {
510
+ return;
511
+ }
512
+ for (const user of response.users) {
513
+ yield user;
514
+ }
515
+ if (!response.next_page) {
516
+ return;
517
+ }
518
+ page += 1;
519
+ } while (true);
520
+ },
521
+ async *listTaskAssignmentsPaginated({
522
+ page, $, accountId, ...params
523
+ }) {
524
+ do {
525
+ const response = await this._withRetries(
526
+ () => this.listTaskAssignments({
527
+ per_page: constants.PAGE_SIZE,
528
+ page,
529
+ $,
530
+ accountId,
531
+ ...params,
532
+ }),
533
+ );
534
+
535
+ if (response.task_assignments.length === 0) {
536
+ return;
537
+ }
538
+ for (const assignment of response.task_assignments) {
539
+ yield assignment;
540
+ }
541
+ if (!response.next_page) {
542
+ return;
543
+ }
544
+ page += 1;
545
+ } while (true);
546
+ },
547
+ async *listUserAssignmentsPaginated({
548
+ page, $, accountId, ...params
549
+ }) {
550
+ do {
551
+ const response = await this._withRetries(
552
+ () => this.listUserAssignments({
553
+ per_page: constants.PAGE_SIZE,
554
+ page,
555
+ $,
556
+ accountId,
557
+ ...params,
558
+ }),
559
+ );
560
+
561
+ if (response.user_assignments.length === 0) {
562
+ return;
563
+ }
564
+ for (const assignment of response.user_assignments) {
565
+ yield assignment;
566
+ }
567
+ if (!response.next_page) {
568
+ return;
569
+ }
570
+ page += 1;
571
+ } while (true);
572
+ },
277
573
  async getProject({
278
574
  $, projectId, accountId,
279
575
  }) {
@@ -297,7 +593,7 @@ export default {
297
593
  });
298
594
  },
299
595
  async listTasks({
300
- $, perPage, page, accountId,
596
+ $, perPage, page, accountId, isActive, updatedSince,
301
597
  }) {
302
598
  return this._makeRequest({
303
599
  $,
@@ -305,12 +601,14 @@ export default {
305
601
  params: {
306
602
  per_page: perPage,
307
603
  page,
604
+ is_active: isActive,
605
+ updated_since: updatedSince,
308
606
  },
309
607
  accountId,
310
608
  });
311
609
  },
312
610
  async listUsers({
313
- $, perPage, page, accountId,
611
+ $, perPage, page, accountId, isActive, updatedSince,
314
612
  }) {
315
613
  return this._makeRequest({
316
614
  $,
@@ -318,12 +616,14 @@ export default {
318
616
  params: {
319
617
  per_page: perPage,
320
618
  page,
619
+ is_active: isActive,
620
+ updated_since: updatedSince,
321
621
  },
322
622
  accountId,
323
623
  });
324
624
  },
325
625
  async listClients({
326
- $, perPage, page, accountId,
626
+ $, perPage, page, accountId, isActive, updatedSince,
327
627
  }) {
328
628
  return this._makeRequest({
329
629
  $,
@@ -331,17 +631,19 @@ export default {
331
631
  params: {
332
632
  per_page: perPage,
333
633
  page,
634
+ is_active: isActive,
635
+ updated_since: updatedSince,
334
636
  },
335
637
  accountId,
336
638
  });
337
639
  },
338
640
  async createTimeEntry({
339
- $, params, accountId,
641
+ $, data, accountId,
340
642
  }) {
341
643
  return this._makeRequest({
342
644
  $,
343
645
  path: "/time_entries",
344
- params,
646
+ data,
345
647
  method: "post",
346
648
  accountId,
347
649
  });
@@ -387,5 +689,276 @@ export default {
387
689
  params,
388
690
  });
389
691
  },
692
+ async getTimeEntry({
693
+ $, id, accountId,
694
+ }) {
695
+ return this._makeRequest({
696
+ $,
697
+ path: `/time_entries/${id}`,
698
+ accountId,
699
+ });
700
+ },
701
+ async updateTimeEntry({
702
+ $, id, data, accountId,
703
+ }) {
704
+ return this._makeRequest({
705
+ $,
706
+ path: `/time_entries/${id}`,
707
+ method: "patch",
708
+ data,
709
+ accountId,
710
+ });
711
+ },
712
+ async deleteTimeEntry({
713
+ $, id, accountId,
714
+ }) {
715
+ return this._makeRequest({
716
+ $,
717
+ path: `/time_entries/${id}`,
718
+ method: "delete",
719
+ accountId,
720
+ });
721
+ },
722
+ async createProject({
723
+ $, data, accountId,
724
+ }) {
725
+ return this._makeRequest({
726
+ $,
727
+ path: "/projects",
728
+ method: "post",
729
+ data,
730
+ accountId,
731
+ });
732
+ },
733
+ async updateProject({
734
+ $, projectId, data, accountId,
735
+ }) {
736
+ return this._makeRequest({
737
+ $,
738
+ path: `/projects/${projectId}`,
739
+ method: "patch",
740
+ data,
741
+ accountId,
742
+ });
743
+ },
744
+ async deleteProject({
745
+ $, projectId, accountId,
746
+ }) {
747
+ return this._makeRequest({
748
+ $,
749
+ path: `/projects/${projectId}`,
750
+ method: "delete",
751
+ accountId,
752
+ });
753
+ },
754
+ async listTaskAssignments({
755
+ $, projectId, accountId, ...params
756
+ }) {
757
+ const path = projectId
758
+ ? `/projects/${projectId}/task_assignments`
759
+ : "/task_assignments";
760
+ return this._makeRequest({
761
+ $,
762
+ path,
763
+ params,
764
+ accountId,
765
+ });
766
+ },
767
+ async getTaskAssignment({
768
+ $, projectId, taskAssignmentId, accountId,
769
+ }) {
770
+ return this._makeRequest({
771
+ $,
772
+ path: `/projects/${projectId}/task_assignments/${taskAssignmentId}`,
773
+ accountId,
774
+ });
775
+ },
776
+ async createTaskAssignment({
777
+ $, projectId, data, accountId,
778
+ }) {
779
+ return this._makeRequest({
780
+ $,
781
+ path: `/projects/${projectId}/task_assignments`,
782
+ method: "post",
783
+ data,
784
+ accountId,
785
+ });
786
+ },
787
+ async updateTaskAssignment({
788
+ $, projectId, taskAssignmentId, data, accountId,
789
+ }) {
790
+ return this._makeRequest({
791
+ $,
792
+ path: `/projects/${projectId}/task_assignments/${taskAssignmentId}`,
793
+ method: "patch",
794
+ data,
795
+ accountId,
796
+ });
797
+ },
798
+ async deleteTaskAssignment({
799
+ $, projectId, taskAssignmentId, accountId,
800
+ }) {
801
+ return this._makeRequest({
802
+ $,
803
+ path: `/projects/${projectId}/task_assignments/${taskAssignmentId}`,
804
+ method: "delete",
805
+ accountId,
806
+ });
807
+ },
808
+ async listUserAssignments({
809
+ $, projectId, accountId, ...params
810
+ }) {
811
+ const path = projectId
812
+ ? `/projects/${projectId}/user_assignments`
813
+ : "/user_assignments";
814
+ return this._makeRequest({
815
+ $,
816
+ path,
817
+ params,
818
+ accountId,
819
+ });
820
+ },
821
+ async getUserAssignment({
822
+ $, projectId, userAssignmentId, accountId,
823
+ }) {
824
+ return this._makeRequest({
825
+ $,
826
+ path: `/projects/${projectId}/user_assignments/${userAssignmentId}`,
827
+ accountId,
828
+ });
829
+ },
830
+ async createUserAssignment({
831
+ $, projectId, data, accountId,
832
+ }) {
833
+ return this._makeRequest({
834
+ $,
835
+ path: `/projects/${projectId}/user_assignments`,
836
+ method: "post",
837
+ data,
838
+ accountId,
839
+ });
840
+ },
841
+ async updateUserAssignment({
842
+ $, projectId, userAssignmentId, data, accountId,
843
+ }) {
844
+ return this._makeRequest({
845
+ $,
846
+ path: `/projects/${projectId}/user_assignments/${userAssignmentId}`,
847
+ method: "patch",
848
+ data,
849
+ accountId,
850
+ });
851
+ },
852
+ async deleteUserAssignment({
853
+ $, projectId, userAssignmentId, accountId,
854
+ }) {
855
+ return this._makeRequest({
856
+ $,
857
+ path: `/projects/${projectId}/user_assignments/${userAssignmentId}`,
858
+ method: "delete",
859
+ accountId,
860
+ });
861
+ },
862
+ async getTimeReport({
863
+ $, reportBy, accountId, ...params
864
+ }) {
865
+ return this._makeRequest({
866
+ $,
867
+ path: `/reports/time/${reportBy}`,
868
+ params,
869
+ accountId,
870
+ });
871
+ },
872
+ async getUser({
873
+ $, userId, accountId,
874
+ }) {
875
+ return this._makeRequest({
876
+ $,
877
+ path: `/users/${userId}`,
878
+ accountId,
879
+ });
880
+ },
881
+ async getMe({
882
+ $, accountId,
883
+ }) {
884
+ return this._makeRequest({
885
+ $,
886
+ path: "/users/me",
887
+ accountId,
888
+ });
889
+ },
890
+ async createUser({
891
+ $, data, accountId,
892
+ }) {
893
+ return this._makeRequest({
894
+ $,
895
+ path: "/users",
896
+ method: "post",
897
+ data,
898
+ accountId,
899
+ });
900
+ },
901
+ async updateUser({
902
+ $, userId, data, accountId,
903
+ }) {
904
+ return this._makeRequest({
905
+ $,
906
+ path: `/users/${userId}`,
907
+ method: "patch",
908
+ data,
909
+ accountId,
910
+ });
911
+ },
912
+ async deleteUser({
913
+ $, userId, accountId,
914
+ }) {
915
+ return this._makeRequest({
916
+ $,
917
+ path: `/users/${userId}`,
918
+ method: "delete",
919
+ accountId,
920
+ });
921
+ },
922
+ async getInvoice({
923
+ $, invoiceId, accountId,
924
+ }) {
925
+ return this._makeRequest({
926
+ $,
927
+ path: `/invoices/${invoiceId}`,
928
+ accountId,
929
+ });
930
+ },
931
+ async createInvoice({
932
+ $, data, accountId,
933
+ }) {
934
+ return this._makeRequest({
935
+ $,
936
+ path: "/invoices",
937
+ method: "post",
938
+ data,
939
+ accountId,
940
+ });
941
+ },
942
+ async updateInvoice({
943
+ $, invoiceId, data, accountId,
944
+ }) {
945
+ return this._makeRequest({
946
+ $,
947
+ path: `/invoices/${invoiceId}`,
948
+ method: "patch",
949
+ data,
950
+ accountId,
951
+ });
952
+ },
953
+ async deleteInvoice({
954
+ $, invoiceId, accountId,
955
+ }) {
956
+ return this._makeRequest({
957
+ $,
958
+ path: `/invoices/${invoiceId}`,
959
+ method: "delete",
960
+ accountId,
961
+ });
962
+ },
390
963
  },
391
964
  };