@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.
- package/actions/create-invoice/create-invoice.mjs +116 -0
- package/actions/create-project/create-project.mjs +138 -0
- package/actions/create-task-assignment/create-task-assignment.mjs +77 -0
- package/actions/create-timesheet-entry/create-timesheet-entry.mjs +34 -38
- package/actions/create-user/create-user.mjs +109 -0
- package/actions/create-user-assignment/create-user-assignment.mjs +85 -0
- package/actions/delete-invoice/delete-invoice.mjs +38 -0
- package/actions/delete-project/delete-project.mjs +38 -0
- package/actions/delete-task-assignment/delete-task-assignment.mjs +45 -0
- package/actions/delete-time-entry/delete-time-entry.mjs +38 -0
- package/actions/delete-user/delete-user.mjs +39 -0
- package/actions/delete-user-assignment/delete-user-assignment.mjs +45 -0
- package/actions/get-invoice/get-invoice.mjs +39 -0
- package/actions/get-me/get-me.mjs +32 -0
- package/actions/get-project/get-project.mjs +39 -0
- package/actions/get-projects/get-projects.mjs +15 -12
- package/actions/get-task-assignment/get-task-assignment.mjs +46 -0
- package/actions/get-time-entry/get-time-entry.mjs +39 -0
- package/actions/get-time-report/get-time-report.mjs +80 -0
- package/actions/get-user/get-user.mjs +40 -0
- package/actions/get-user-assignment/get-user-assignment.mjs +46 -0
- package/actions/list-account-id-options/list-account-id-options.mjs +12 -3
- package/actions/list-clients/list-clients.mjs +57 -0
- package/actions/list-invoices/list-invoices.mjs +86 -0
- package/actions/list-task-assignments/list-task-assignments.mjs +66 -0
- package/actions/list-tasks/list-tasks.mjs +57 -0
- package/actions/list-time-entries/list-time-entries.mjs +150 -0
- package/actions/list-user-assignments/list-user-assignments.mjs +74 -0
- package/actions/list-users/list-users.mjs +57 -0
- package/actions/start-timer/start-timer.mjs +5 -7
- package/actions/stop-timer/stop-timer.mjs +5 -7
- package/actions/update-invoice/update-invoice.mjs +114 -0
- package/actions/update-project/update-project.mjs +140 -0
- package/actions/update-task-assignment/update-task-assignment.mjs +77 -0
- package/actions/update-time-entry/update-time-entry.mjs +92 -0
- package/actions/update-user/update-user.mjs +106 -0
- package/actions/update-user-assignment/update-user-assignment.mjs +84 -0
- package/common/constants.mjs +51 -1
- package/common/utils.mjs +50 -1
- package/harvest.app.mjs +683 -110
- package/package.json +1 -1
- package/sources/new-invoice-entry/new-invoice-entry.mjs +1 -1
- package/sources/new-timesheet-entry/new-timesheet-entry.mjs +1 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import harvest from "../../harvest.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "harvest-update-invoice",
|
|
5
|
+
name: "Update Invoice",
|
|
6
|
+
description: "Update an existing invoice. Use **List Invoices** to find a valid ID. Example: call with invoiceId set to a draft invoice's ID and subject set to a new value to revise it before sending. [See the documentation](https://help.getharvest.com/api-v2/invoices-api/invoices/invoices/#update-an-invoice).",
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
type: "action",
|
|
9
|
+
ai: "optimized",
|
|
10
|
+
annotations: {
|
|
11
|
+
readOnlyHint: false,
|
|
12
|
+
destructiveHint: false,
|
|
13
|
+
openWorldHint: true,
|
|
14
|
+
},
|
|
15
|
+
props: {
|
|
16
|
+
harvest,
|
|
17
|
+
accountId: {
|
|
18
|
+
propDefinition: [
|
|
19
|
+
harvest,
|
|
20
|
+
"accountId",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
invoiceId: {
|
|
24
|
+
propDefinition: [
|
|
25
|
+
harvest,
|
|
26
|
+
"invoiceId",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
clientId: {
|
|
30
|
+
propDefinition: [
|
|
31
|
+
harvest,
|
|
32
|
+
"clientId",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
subject: {
|
|
36
|
+
propDefinition: [
|
|
37
|
+
harvest,
|
|
38
|
+
"subject",
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
number: {
|
|
42
|
+
propDefinition: [
|
|
43
|
+
harvest,
|
|
44
|
+
"invoiceNumber",
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
purchaseOrder: {
|
|
48
|
+
propDefinition: [
|
|
49
|
+
harvest,
|
|
50
|
+
"purchaseOrder",
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
tax: {
|
|
54
|
+
propDefinition: [
|
|
55
|
+
harvest,
|
|
56
|
+
"tax",
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
discount: {
|
|
60
|
+
propDefinition: [
|
|
61
|
+
harvest,
|
|
62
|
+
"discount",
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
notes: {
|
|
66
|
+
propDefinition: [
|
|
67
|
+
harvest,
|
|
68
|
+
"invoiceNotes",
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
issueDate: {
|
|
72
|
+
propDefinition: [
|
|
73
|
+
harvest,
|
|
74
|
+
"issueDate",
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
dueDate: {
|
|
78
|
+
propDefinition: [
|
|
79
|
+
harvest,
|
|
80
|
+
"dueDate",
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
lineItems: {
|
|
84
|
+
type: "string",
|
|
85
|
+
label: "Line Items",
|
|
86
|
+
description: "JSON array of line item objects. Omit `id` to add a new line item, e.g. `[{\"kind\":\"Service\",\"description\":\"Consulting\",\"unit_price\":100,\"quantity\":5}]`. Include an existing line item's `id` (from the invoice's `line_items` in a prior response, e.g. from **Get Invoice**) plus any fields to change, e.g. `[{\"id\":53341928,\"description\":\"Consulting Phase 2\",\"unit_price\":150}]`, to update it. Include that `id` with `_destroy` set to `true`, e.g. `[{\"id\":53341928,\"_destroy\":true}]`, to delete it.",
|
|
87
|
+
optional: true,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
async run({ $ }) {
|
|
91
|
+
const lineItems = this.lineItems
|
|
92
|
+
? JSON.parse(this.lineItems)
|
|
93
|
+
: undefined;
|
|
94
|
+
const response = await this.harvest.updateInvoice({
|
|
95
|
+
$,
|
|
96
|
+
invoiceId: this.invoiceId,
|
|
97
|
+
accountId: this.accountId,
|
|
98
|
+
data: {
|
|
99
|
+
client_id: this.clientId,
|
|
100
|
+
subject: this.subject,
|
|
101
|
+
number: this.number,
|
|
102
|
+
purchase_order: this.purchaseOrder,
|
|
103
|
+
tax: this.tax,
|
|
104
|
+
discount: this.discount,
|
|
105
|
+
notes: this.notes,
|
|
106
|
+
issue_date: this.issueDate,
|
|
107
|
+
due_date: this.dueDate,
|
|
108
|
+
line_items: lineItems,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
$.export("$summary", `Successfully updated invoice ${response.id}`);
|
|
112
|
+
return response;
|
|
113
|
+
},
|
|
114
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import harvest from "../../harvest.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "harvest-update-project",
|
|
5
|
+
name: "Update Project",
|
|
6
|
+
description: "Update an existing project. Use **Get Projects** to find a project ID. Example: call with projectId set to a project's ID and projectName set to a new name to rename it. [See the documentation](https://help.getharvest.com/api-v2/projects-api/projects/projects/#update-a-project).",
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
type: "action",
|
|
9
|
+
ai: "optimized",
|
|
10
|
+
annotations: {
|
|
11
|
+
readOnlyHint: false,
|
|
12
|
+
destructiveHint: false,
|
|
13
|
+
openWorldHint: true,
|
|
14
|
+
},
|
|
15
|
+
props: {
|
|
16
|
+
harvest,
|
|
17
|
+
accountId: {
|
|
18
|
+
propDefinition: [
|
|
19
|
+
harvest,
|
|
20
|
+
"accountId",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
projectId: {
|
|
24
|
+
propDefinition: [
|
|
25
|
+
harvest,
|
|
26
|
+
"projectId",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
clientId: {
|
|
30
|
+
propDefinition: [
|
|
31
|
+
harvest,
|
|
32
|
+
"clientId",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
projectName: {
|
|
36
|
+
propDefinition: [
|
|
37
|
+
harvest,
|
|
38
|
+
"projectName",
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
isBillable: {
|
|
42
|
+
propDefinition: [
|
|
43
|
+
harvest,
|
|
44
|
+
"isBillable",
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
billBy: {
|
|
48
|
+
propDefinition: [
|
|
49
|
+
harvest,
|
|
50
|
+
"billBy",
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
budgetBy: {
|
|
54
|
+
propDefinition: [
|
|
55
|
+
harvest,
|
|
56
|
+
"budgetBy",
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
code: {
|
|
60
|
+
propDefinition: [
|
|
61
|
+
harvest,
|
|
62
|
+
"code",
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
isActive: {
|
|
66
|
+
propDefinition: [
|
|
67
|
+
harvest,
|
|
68
|
+
"isActive",
|
|
69
|
+
],
|
|
70
|
+
description: "Whether the project is active.",
|
|
71
|
+
},
|
|
72
|
+
notes: {
|
|
73
|
+
propDefinition: [
|
|
74
|
+
harvest,
|
|
75
|
+
"projectNotes",
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
isFixedFee: {
|
|
79
|
+
propDefinition: [
|
|
80
|
+
harvest,
|
|
81
|
+
"isFixedFee",
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
hourlyRate: {
|
|
85
|
+
propDefinition: [
|
|
86
|
+
harvest,
|
|
87
|
+
"projectHourlyRate",
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
budget: {
|
|
91
|
+
propDefinition: [
|
|
92
|
+
harvest,
|
|
93
|
+
"projectBudget",
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
costBudget: {
|
|
97
|
+
propDefinition: [
|
|
98
|
+
harvest,
|
|
99
|
+
"costBudget",
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
startsOn: {
|
|
103
|
+
propDefinition: [
|
|
104
|
+
harvest,
|
|
105
|
+
"startsOn",
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
endsOn: {
|
|
109
|
+
propDefinition: [
|
|
110
|
+
harvest,
|
|
111
|
+
"endsOn",
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
async run({ $ }) {
|
|
116
|
+
const response = await this.harvest.updateProject({
|
|
117
|
+
$,
|
|
118
|
+
projectId: this.projectId,
|
|
119
|
+
accountId: this.accountId,
|
|
120
|
+
data: {
|
|
121
|
+
client_id: this.clientId,
|
|
122
|
+
name: this.projectName,
|
|
123
|
+
is_billable: this.isBillable,
|
|
124
|
+
bill_by: this.billBy,
|
|
125
|
+
budget_by: this.budgetBy,
|
|
126
|
+
code: this.code,
|
|
127
|
+
is_active: this.isActive,
|
|
128
|
+
notes: this.notes,
|
|
129
|
+
is_fixed_fee: this.isFixedFee,
|
|
130
|
+
hourly_rate: this.hourlyRate,
|
|
131
|
+
budget: this.budget,
|
|
132
|
+
cost_budget: this.costBudget,
|
|
133
|
+
starts_on: this.startsOn,
|
|
134
|
+
ends_on: this.endsOn,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
$.export("$summary", `Successfully updated project ${response.id}: ${response.name}`);
|
|
138
|
+
return response;
|
|
139
|
+
},
|
|
140
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import harvest from "../../harvest.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "harvest-update-task-assignment",
|
|
5
|
+
name: "Update Task Assignment",
|
|
6
|
+
description: "Update a task assignment on a project. Use **List Task Assignments** to find IDs. Example: call with projectId, taskAssignmentId, and billable=false to stop billing that task on the project. [See the documentation](https://help.getharvest.com/api-v2/projects-api/projects/task-assignments/#update-a-task-assignment).",
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
type: "action",
|
|
9
|
+
ai: "optimized",
|
|
10
|
+
annotations: {
|
|
11
|
+
readOnlyHint: false,
|
|
12
|
+
destructiveHint: false,
|
|
13
|
+
openWorldHint: true,
|
|
14
|
+
},
|
|
15
|
+
props: {
|
|
16
|
+
harvest,
|
|
17
|
+
accountId: {
|
|
18
|
+
propDefinition: [
|
|
19
|
+
harvest,
|
|
20
|
+
"accountId",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
projectId: {
|
|
24
|
+
propDefinition: [
|
|
25
|
+
harvest,
|
|
26
|
+
"projectId",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
taskAssignmentId: {
|
|
30
|
+
propDefinition: [
|
|
31
|
+
harvest,
|
|
32
|
+
"taskAssignmentId",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
isActive: {
|
|
36
|
+
propDefinition: [
|
|
37
|
+
harvest,
|
|
38
|
+
"isActive",
|
|
39
|
+
],
|
|
40
|
+
description: "Whether the task assignment is active.",
|
|
41
|
+
},
|
|
42
|
+
billable: {
|
|
43
|
+
propDefinition: [
|
|
44
|
+
harvest,
|
|
45
|
+
"billable",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
hourlyRate: {
|
|
49
|
+
propDefinition: [
|
|
50
|
+
harvest,
|
|
51
|
+
"taskAssignmentHourlyRate",
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
budget: {
|
|
55
|
+
propDefinition: [
|
|
56
|
+
harvest,
|
|
57
|
+
"taskAssignmentBudget",
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
async run({ $ }) {
|
|
62
|
+
const response = await this.harvest.updateTaskAssignment({
|
|
63
|
+
$,
|
|
64
|
+
projectId: this.projectId,
|
|
65
|
+
taskAssignmentId: this.taskAssignmentId,
|
|
66
|
+
accountId: this.accountId,
|
|
67
|
+
data: {
|
|
68
|
+
is_active: this.isActive,
|
|
69
|
+
billable: this.billable,
|
|
70
|
+
hourly_rate: this.hourlyRate,
|
|
71
|
+
budget: this.budget,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
$.export("$summary", `Successfully updated task assignment ${response.id}`);
|
|
75
|
+
return response;
|
|
76
|
+
},
|
|
77
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import harvest from "../../harvest.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "harvest-update-time-entry",
|
|
5
|
+
name: "Update Time Entry",
|
|
6
|
+
description: "Update an existing time entry. Use **List Time Entries** to find a valid ID. Example: call with timeEntryId set to a logged entry's ID and hours set to a corrected value to fix a mistaken time entry. [See the documentation](https://help.getharvest.com/api-v2/timesheets-api/timesheets/time-entries/#update-a-time-entry).",
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
type: "action",
|
|
9
|
+
ai: "optimized",
|
|
10
|
+
annotations: {
|
|
11
|
+
readOnlyHint: false,
|
|
12
|
+
destructiveHint: false,
|
|
13
|
+
openWorldHint: true,
|
|
14
|
+
},
|
|
15
|
+
props: {
|
|
16
|
+
harvest,
|
|
17
|
+
accountId: {
|
|
18
|
+
propDefinition: [
|
|
19
|
+
harvest,
|
|
20
|
+
"accountId",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
timeEntryId: {
|
|
24
|
+
propDefinition: [
|
|
25
|
+
harvest,
|
|
26
|
+
"timeEntryId",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
projectId: {
|
|
30
|
+
propDefinition: [
|
|
31
|
+
harvest,
|
|
32
|
+
"projectId",
|
|
33
|
+
],
|
|
34
|
+
optional: true,
|
|
35
|
+
},
|
|
36
|
+
taskId: {
|
|
37
|
+
propDefinition: [
|
|
38
|
+
harvest,
|
|
39
|
+
"taskId",
|
|
40
|
+
],
|
|
41
|
+
optional: true,
|
|
42
|
+
},
|
|
43
|
+
spentDate: {
|
|
44
|
+
type: "string",
|
|
45
|
+
label: "Spent Date",
|
|
46
|
+
description: "Date of the entry, format `YYYY-MM-DD`, e.g. `2026-09-17`.",
|
|
47
|
+
optional: true,
|
|
48
|
+
},
|
|
49
|
+
startedTime: {
|
|
50
|
+
type: "string",
|
|
51
|
+
label: "Started Time",
|
|
52
|
+
description: "Start time, e.g. `8:00am`.",
|
|
53
|
+
optional: true,
|
|
54
|
+
},
|
|
55
|
+
endedTime: {
|
|
56
|
+
type: "string",
|
|
57
|
+
label: "Ended Time",
|
|
58
|
+
description: "End time, e.g. `9:00am`.",
|
|
59
|
+
optional: true,
|
|
60
|
+
},
|
|
61
|
+
hours: {
|
|
62
|
+
type: "string",
|
|
63
|
+
label: "Hours",
|
|
64
|
+
description: "Decimal hours, e.g. `3.5`.",
|
|
65
|
+
optional: true,
|
|
66
|
+
},
|
|
67
|
+
notes: {
|
|
68
|
+
type: "string",
|
|
69
|
+
label: "Notes",
|
|
70
|
+
description: "Notes for the entry.",
|
|
71
|
+
optional: true,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
async run({ $ }) {
|
|
75
|
+
const response = await this.harvest.updateTimeEntry({
|
|
76
|
+
$,
|
|
77
|
+
id: this.timeEntryId,
|
|
78
|
+
accountId: this.accountId,
|
|
79
|
+
data: {
|
|
80
|
+
project_id: this.projectId,
|
|
81
|
+
task_id: this.taskId,
|
|
82
|
+
spent_date: this.spentDate,
|
|
83
|
+
started_time: this.startedTime,
|
|
84
|
+
ended_time: this.endedTime,
|
|
85
|
+
hours: this.hours,
|
|
86
|
+
notes: this.notes,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
$.export("$summary", `Successfully updated time entry ${response.id}`);
|
|
90
|
+
return response;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import harvest from "../../harvest.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "harvest-update-user",
|
|
5
|
+
name: "Update User",
|
|
6
|
+
description: "Update an existing user. Use **List Users** to find a valid ID. Example: call with userId set to a user's ID and lastName set to a new value to update their name. [See the documentation](https://help.getharvest.com/api-v2/users-api/users/users/#update-a-user).",
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
type: "action",
|
|
9
|
+
ai: "optimized",
|
|
10
|
+
annotations: {
|
|
11
|
+
readOnlyHint: false,
|
|
12
|
+
destructiveHint: false,
|
|
13
|
+
openWorldHint: true,
|
|
14
|
+
},
|
|
15
|
+
props: {
|
|
16
|
+
harvest,
|
|
17
|
+
accountId: {
|
|
18
|
+
propDefinition: [
|
|
19
|
+
harvest,
|
|
20
|
+
"accountId",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
userId: {
|
|
24
|
+
propDefinition: [
|
|
25
|
+
harvest,
|
|
26
|
+
"userId",
|
|
27
|
+
],
|
|
28
|
+
optional: false,
|
|
29
|
+
},
|
|
30
|
+
firstName: {
|
|
31
|
+
propDefinition: [
|
|
32
|
+
harvest,
|
|
33
|
+
"firstName",
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
lastName: {
|
|
37
|
+
propDefinition: [
|
|
38
|
+
harvest,
|
|
39
|
+
"lastName",
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
email: {
|
|
43
|
+
propDefinition: [
|
|
44
|
+
harvest,
|
|
45
|
+
"email",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
timezone: {
|
|
49
|
+
propDefinition: [
|
|
50
|
+
harvest,
|
|
51
|
+
"timezone",
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
isContractor: {
|
|
55
|
+
propDefinition: [
|
|
56
|
+
harvest,
|
|
57
|
+
"isContractor",
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
isActive: {
|
|
61
|
+
propDefinition: [
|
|
62
|
+
harvest,
|
|
63
|
+
"isActive",
|
|
64
|
+
],
|
|
65
|
+
description: "Whether the user is active.",
|
|
66
|
+
},
|
|
67
|
+
weeklyCapacity: {
|
|
68
|
+
propDefinition: [
|
|
69
|
+
harvest,
|
|
70
|
+
"weeklyCapacity",
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
defaultHourlyRate: {
|
|
74
|
+
propDefinition: [
|
|
75
|
+
harvest,
|
|
76
|
+
"defaultHourlyRate",
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
accessRoles: {
|
|
80
|
+
propDefinition: [
|
|
81
|
+
harvest,
|
|
82
|
+
"accessRoles",
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
async run({ $ }) {
|
|
87
|
+
const response = await this.harvest.updateUser({
|
|
88
|
+
$,
|
|
89
|
+
userId: this.userId,
|
|
90
|
+
accountId: this.accountId,
|
|
91
|
+
data: {
|
|
92
|
+
first_name: this.firstName,
|
|
93
|
+
last_name: this.lastName,
|
|
94
|
+
email: this.email,
|
|
95
|
+
timezone: this.timezone,
|
|
96
|
+
is_contractor: this.isContractor,
|
|
97
|
+
is_active: this.isActive,
|
|
98
|
+
weekly_capacity: this.weeklyCapacity,
|
|
99
|
+
default_hourly_rate: this.defaultHourlyRate,
|
|
100
|
+
access_roles: this.accessRoles,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
$.export("$summary", `Successfully updated user ${response.id}: ${response.first_name} ${response.last_name}`);
|
|
104
|
+
return response;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import harvest from "../../harvest.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "harvest-update-user-assignment",
|
|
5
|
+
name: "Update User Assignment",
|
|
6
|
+
description: "Update a user assignment on a project. Use **List User Assignments** to find IDs. Example: call with projectId, userAssignmentId, and hourlyRate=\"150\" to set that person's custom billing rate on the project. [See the documentation](https://help.getharvest.com/api-v2/projects-api/projects/user-assignments/#update-a-user-assignment).",
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
type: "action",
|
|
9
|
+
ai: "optimized",
|
|
10
|
+
annotations: {
|
|
11
|
+
readOnlyHint: false,
|
|
12
|
+
destructiveHint: false,
|
|
13
|
+
openWorldHint: true,
|
|
14
|
+
},
|
|
15
|
+
props: {
|
|
16
|
+
harvest,
|
|
17
|
+
accountId: {
|
|
18
|
+
propDefinition: [
|
|
19
|
+
harvest,
|
|
20
|
+
"accountId",
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
projectId: {
|
|
24
|
+
propDefinition: [
|
|
25
|
+
harvest,
|
|
26
|
+
"projectId",
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
userAssignmentId: {
|
|
30
|
+
propDefinition: [
|
|
31
|
+
harvest,
|
|
32
|
+
"userAssignmentId",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
isActive: {
|
|
36
|
+
propDefinition: [
|
|
37
|
+
harvest,
|
|
38
|
+
"isActive",
|
|
39
|
+
],
|
|
40
|
+
description: "Whether the user assignment is active.",
|
|
41
|
+
},
|
|
42
|
+
isProjectManager: {
|
|
43
|
+
propDefinition: [
|
|
44
|
+
harvest,
|
|
45
|
+
"isProjectManager",
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
useDefaultRates: {
|
|
49
|
+
propDefinition: [
|
|
50
|
+
harvest,
|
|
51
|
+
"useDefaultRates",
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
hourlyRate: {
|
|
55
|
+
propDefinition: [
|
|
56
|
+
harvest,
|
|
57
|
+
"userAssignmentHourlyRate",
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
budget: {
|
|
61
|
+
propDefinition: [
|
|
62
|
+
harvest,
|
|
63
|
+
"userAssignmentBudget",
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
async run({ $ }) {
|
|
68
|
+
const response = await this.harvest.updateUserAssignment({
|
|
69
|
+
$,
|
|
70
|
+
projectId: this.projectId,
|
|
71
|
+
userAssignmentId: this.userAssignmentId,
|
|
72
|
+
accountId: this.accountId,
|
|
73
|
+
data: {
|
|
74
|
+
is_active: this.isActive,
|
|
75
|
+
is_project_manager: this.isProjectManager,
|
|
76
|
+
use_default_rates: this.useDefaultRates,
|
|
77
|
+
hourly_rate: this.hourlyRate,
|
|
78
|
+
budget: this.budget,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
$.export("$summary", `Successfully updated user assignment ${response.id}`);
|
|
82
|
+
return response;
|
|
83
|
+
},
|
|
84
|
+
};
|
package/common/constants.mjs
CHANGED
|
@@ -3,10 +3,60 @@ export default {
|
|
|
3
3
|
BASE_URL: "api.harvestapp.com",
|
|
4
4
|
VERSION_PATH: "/v2",
|
|
5
5
|
PAGE_SIZE: 100,
|
|
6
|
-
|
|
6
|
+
// Cap for tools that auto-paginate to completion (list-time-entries, list-invoices, etc.) —
|
|
7
|
+
// bounds worst-case wall clock and result size instead of fetching an account's entire
|
|
8
|
+
// history unbounded. Documented in each such tool's description. Kept modest rather than
|
|
9
|
+
// Harvest's own page-size ceiling (2000) because these tools return full, unshaped objects
|
|
10
|
+
// (nested project/task/user/client sub-objects) with no field-selection param — a large
|
|
11
|
+
// cap here produces a response too big for the calling agent to usefully read in one call.
|
|
12
|
+
MAX_AUTO_PAGINATE_RECORDS: 200,
|
|
13
|
+
// Paces per-item lookups (e.g. get-projects with explicit Project IDs) well under Harvest's
|
|
14
|
+
// account-wide rate limit of 100 requests per 15 seconds, leaving headroom for other
|
|
15
|
+
// concurrent API usage on the same account instead of racing right up to the ceiling.
|
|
16
|
+
RATE_LIMIT_BATCH_SIZE: 8,
|
|
17
|
+
RATE_LIMIT_BATCH_DELAY_MS: 1500,
|
|
18
|
+
RETRIABLE_STATUS_CODES: [
|
|
7
19
|
408,
|
|
8
20
|
429,
|
|
9
21
|
500,
|
|
10
22
|
],
|
|
11
23
|
DB_LAST_DATE_CHECK: "DB_LAST_DATE_CHECK",
|
|
24
|
+
REPORT_BY_OPTIONS: Object.freeze([
|
|
25
|
+
"clients",
|
|
26
|
+
"projects",
|
|
27
|
+
"tasks",
|
|
28
|
+
"team",
|
|
29
|
+
]),
|
|
30
|
+
BILL_BY_OPTIONS: Object.freeze([
|
|
31
|
+
"Project",
|
|
32
|
+
"Tasks",
|
|
33
|
+
"People",
|
|
34
|
+
"none",
|
|
35
|
+
]),
|
|
36
|
+
BUDGET_BY_OPTIONS: Object.freeze([
|
|
37
|
+
"project",
|
|
38
|
+
"project_cost",
|
|
39
|
+
"task",
|
|
40
|
+
"task_fees",
|
|
41
|
+
"person",
|
|
42
|
+
"none",
|
|
43
|
+
]),
|
|
44
|
+
INVOICE_STATE_OPTIONS: Object.freeze([
|
|
45
|
+
"draft",
|
|
46
|
+
"open",
|
|
47
|
+
"paid",
|
|
48
|
+
"closed",
|
|
49
|
+
]),
|
|
50
|
+
ACCESS_ROLE_OPTIONS: Object.freeze([
|
|
51
|
+
"member",
|
|
52
|
+
"manager",
|
|
53
|
+
"administrator",
|
|
54
|
+
"project_creator",
|
|
55
|
+
"billable_rates_manager",
|
|
56
|
+
"managed_projects_invoice_drafter",
|
|
57
|
+
"managed_projects_invoice_manager",
|
|
58
|
+
"client_and_task_manager",
|
|
59
|
+
"time_and_expenses_manager",
|
|
60
|
+
"estimates_manager",
|
|
61
|
+
]),
|
|
12
62
|
};
|