@agnocon/piece-bexio 0.1.7
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/LICENSE.MIT-AP +24 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/actions/create-company.d.ts +28 -0
- package/dist/lib/actions/create-company.d.ts.map +1 -0
- package/dist/lib/actions/create-company.js +461 -0
- package/dist/lib/actions/create-company.js.map +1 -0
- package/dist/lib/actions/create-file.d.ts +4 -0
- package/dist/lib/actions/create-file.d.ts.map +1 -0
- package/dist/lib/actions/create-file.js +48 -0
- package/dist/lib/actions/create-file.js.map +1 -0
- package/dist/lib/actions/create-manual-entry.d.ts +7 -0
- package/dist/lib/actions/create-manual-entry.d.ts.map +1 -0
- package/dist/lib/actions/create-manual-entry.js +426 -0
- package/dist/lib/actions/create-manual-entry.js.map +1 -0
- package/dist/lib/actions/create-person.d.ts +30 -0
- package/dist/lib/actions/create-person.d.ts.map +1 -0
- package/dist/lib/actions/create-person.js +477 -0
- package/dist/lib/actions/create-person.js.map +1 -0
- package/dist/lib/actions/create-product.d.ts +34 -0
- package/dist/lib/actions/create-product.d.ts.map +1 -0
- package/dist/lib/actions/create-product.js +527 -0
- package/dist/lib/actions/create-product.js.map +1 -0
- package/dist/lib/actions/create-project.d.ts +17 -0
- package/dist/lib/actions/create-project.d.ts.map +1 -0
- package/dist/lib/actions/create-project.js +316 -0
- package/dist/lib/actions/create-project.js.map +1 -0
- package/dist/lib/actions/create-sales-invoice.d.ts +25 -0
- package/dist/lib/actions/create-sales-invoice.d.ts.map +1 -0
- package/dist/lib/actions/create-sales-invoice.js +615 -0
- package/dist/lib/actions/create-sales-invoice.js.map +1 -0
- package/dist/lib/actions/create-sales-order.d.ts +25 -0
- package/dist/lib/actions/create-sales-order.d.ts.map +1 -0
- package/dist/lib/actions/create-sales-order.js +642 -0
- package/dist/lib/actions/create-sales-order.js.map +1 -0
- package/dist/lib/actions/create-sales-quote.d.ts +28 -0
- package/dist/lib/actions/create-sales-quote.d.ts.map +1 -0
- package/dist/lib/actions/create-sales-quote.js +666 -0
- package/dist/lib/actions/create-sales-quote.js.map +1 -0
- package/dist/lib/actions/create-time-tracking.d.ts +17 -0
- package/dist/lib/actions/create-time-tracking.d.ts.map +1 -0
- package/dist/lib/actions/create-time-tracking.js +380 -0
- package/dist/lib/actions/create-time-tracking.js.map +1 -0
- package/dist/lib/actions/export-invoice-pdf.d.ts +5 -0
- package/dist/lib/actions/export-invoice-pdf.d.ts.map +1 -0
- package/dist/lib/actions/export-invoice-pdf.js +94 -0
- package/dist/lib/actions/export-invoice-pdf.js.map +1 -0
- package/dist/lib/actions/find-account.d.ts +6 -0
- package/dist/lib/actions/find-account.d.ts.map +1 -0
- package/dist/lib/actions/find-account.js +107 -0
- package/dist/lib/actions/find-account.js.map +1 -0
- package/dist/lib/actions/find-company.d.ts +8 -0
- package/dist/lib/actions/find-company.d.ts.map +1 -0
- package/dist/lib/actions/find-company.js +160 -0
- package/dist/lib/actions/find-company.js.map +1 -0
- package/dist/lib/actions/find-country.d.ts +7 -0
- package/dist/lib/actions/find-country.d.ts.map +1 -0
- package/dist/lib/actions/find-country.js +125 -0
- package/dist/lib/actions/find-country.js.map +1 -0
- package/dist/lib/actions/find-person.d.ts +9 -0
- package/dist/lib/actions/find-person.d.ts.map +1 -0
- package/dist/lib/actions/find-person.js +175 -0
- package/dist/lib/actions/find-person.js.map +1 -0
- package/dist/lib/actions/find-product.d.ts +7 -0
- package/dist/lib/actions/find-product.d.ts.map +1 -0
- package/dist/lib/actions/find-product.js +124 -0
- package/dist/lib/actions/find-product.js.map +1 -0
- package/dist/lib/actions/search-invoice.d.ts +7 -0
- package/dist/lib/actions/search-invoice.d.ts.map +1 -0
- package/dist/lib/actions/search-invoice.js +140 -0
- package/dist/lib/actions/search-invoice.js.map +1 -0
- package/dist/lib/actions/search-order.d.ts +7 -0
- package/dist/lib/actions/search-order.d.ts.map +1 -0
- package/dist/lib/actions/search-order.js +139 -0
- package/dist/lib/actions/search-order.js.map +1 -0
- package/dist/lib/actions/search-quote.d.ts +7 -0
- package/dist/lib/actions/search-quote.d.ts.map +1 -0
- package/dist/lib/actions/search-quote.js +140 -0
- package/dist/lib/actions/search-quote.js.map +1 -0
- package/dist/lib/actions/send-sales-invoice.d.ts +9 -0
- package/dist/lib/actions/send-sales-invoice.d.ts.map +1 -0
- package/dist/lib/actions/send-sales-invoice.js +110 -0
- package/dist/lib/actions/send-sales-invoice.js.map +1 -0
- package/dist/lib/actions/update-company.d.ts +29 -0
- package/dist/lib/actions/update-company.d.ts.map +1 -0
- package/dist/lib/actions/update-company.js +506 -0
- package/dist/lib/actions/update-company.js.map +1 -0
- package/dist/lib/actions/update-person.d.ts +31 -0
- package/dist/lib/actions/update-person.d.ts.map +1 -0
- package/dist/lib/actions/update-person.js +524 -0
- package/dist/lib/actions/update-person.js.map +1 -0
- package/dist/lib/actions/update-product.d.ts +34 -0
- package/dist/lib/actions/update-product.d.ts.map +1 -0
- package/dist/lib/actions/update-product.js +556 -0
- package/dist/lib/actions/update-product.js.map +1 -0
- package/dist/lib/auth.d.ts +2 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +51 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/common/client.d.ts +13 -0
- package/dist/lib/common/client.d.ts.map +1 -0
- package/dist/lib/common/client.js +64 -0
- package/dist/lib/common/client.js.map +1 -0
- package/dist/lib/common/index.d.ts +5 -0
- package/dist/lib/common/index.d.ts.map +1 -0
- package/dist/lib/common/index.js +10 -0
- package/dist/lib/common/index.js.map +1 -0
- package/dist/lib/common/props.d.ts +14 -0
- package/dist/lib/common/props.d.ts.map +1 -0
- package/dist/lib/common/props.js +118 -0
- package/dist/lib/common/props.js.map +1 -0
- package/dist/lib/common/types.d.ts +89 -0
- package/dist/lib/common/types.d.ts.map +1 -0
- package/dist/lib/common/types.js +6 -0
- package/dist/lib/common/types.js.map +1 -0
- package/dist/lib/triggers/new-order.d.ts +11 -0
- package/dist/lib/triggers/new-order.d.ts.map +1 -0
- package/dist/lib/triggers/new-order.js +152 -0
- package/dist/lib/triggers/new-order.js.map +1 -0
- package/dist/lib/triggers/new-product.d.ts +3 -0
- package/dist/lib/triggers/new-product.d.ts.map +1 -0
- package/dist/lib/triggers/new-product.js +111 -0
- package/dist/lib/triggers/new-product.js.map +1 -0
- package/dist/lib/triggers/new-project.d.ts +11 -0
- package/dist/lib/triggers/new-project.d.ts.map +1 -0
- package/dist/lib/triggers/new-project.js +141 -0
- package/dist/lib/triggers/new-project.js.map +1 -0
- package/dist/lib/triggers/new-quote.d.ts +11 -0
- package/dist/lib/triggers/new-quote.d.ts.map +1 -0
- package/dist/lib/triggers/new-quote.js +153 -0
- package/dist/lib/triggers/new-quote.js.map +1 -0
- package/dist/lib/triggers/new-sales-invoice.d.ts +11 -0
- package/dist/lib/triggers/new-sales-invoice.d.ts.map +1 -0
- package/dist/lib/triggers/new-sales-invoice.js +153 -0
- package/dist/lib/triggers/new-sales-invoice.js.map +1 -0
- package/dist/lib/triggers/new-updated-company.d.ts +3 -0
- package/dist/lib/triggers/new-updated-company.d.ts.map +1 -0
- package/dist/lib/triggers/new-updated-company.js +122 -0
- package/dist/lib/triggers/new-updated-company.js.map +1 -0
- package/dist/lib/triggers/new-updated-person.d.ts +3 -0
- package/dist/lib/triggers/new-updated-person.d.ts.map +1 -0
- package/dist/lib/triggers/new-updated-person.js +122 -0
- package/dist/lib/triggers/new-updated-person.js.map +1 -0
- package/package.json +48 -0
- package/src/index.ts +89 -0
- package/src/lib/actions/create-company.ts +464 -0
- package/src/lib/actions/create-file.ts +62 -0
- package/src/lib/actions/create-manual-entry.ts +445 -0
- package/src/lib/actions/create-person.ts +481 -0
- package/src/lib/actions/create-product.ts +563 -0
- package/src/lib/actions/create-project.ts +344 -0
- package/src/lib/actions/create-sales-invoice.ts +656 -0
- package/src/lib/actions/create-sales-order.ts +689 -0
- package/src/lib/actions/create-sales-quote.ts +713 -0
- package/src/lib/actions/create-time-tracking.ts +418 -0
- package/src/lib/actions/export-invoice-pdf.ts +104 -0
- package/src/lib/actions/find-account.ts +114 -0
- package/src/lib/actions/find-company.ts +193 -0
- package/src/lib/actions/find-country.ts +127 -0
- package/src/lib/actions/find-person.ts +208 -0
- package/src/lib/actions/find-product.ts +161 -0
- package/src/lib/actions/search-invoice.ts +157 -0
- package/src/lib/actions/search-order.ts +155 -0
- package/src/lib/actions/search-quote.ts +157 -0
- package/src/lib/actions/send-sales-invoice.ts +118 -0
- package/src/lib/actions/update-company.ts +518 -0
- package/src/lib/actions/update-person.ts +536 -0
- package/src/lib/actions/update-product.ts +594 -0
- package/src/lib/auth.ts +44 -0
- package/src/lib/common/client.ts +65 -0
- package/src/lib/common/index.ts +5 -0
- package/src/lib/common/props.ts +127 -0
- package/src/lib/common/types.ts +99 -0
- package/src/lib/triggers/new-order.ts +184 -0
- package/src/lib/triggers/new-product.ts +154 -0
- package/src/lib/triggers/new-project.ts +165 -0
- package/src/lib/triggers/new-quote.ts +186 -0
- package/src/lib/triggers/new-sales-invoice.ts +186 -0
- package/src/lib/triggers/new-updated-company.ts +161 -0
- package/src/lib/triggers/new-updated-person.ts +161 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { createAction, Property, OAuth2PropertyValue, DynamicPropsValue } from '@agnocon/pieces-framework';
|
|
2
|
+
import { bexioAuth } from '../auth';
|
|
3
|
+
import { BexioClient } from '../common/client';
|
|
4
|
+
|
|
5
|
+
export const createTimeTrackingAction = createAction({
|
|
6
|
+
auth: bexioAuth,
|
|
7
|
+
name: 'create_time_tracking',
|
|
8
|
+
displayName: 'Create Time Tracking',
|
|
9
|
+
description: 'Create a new timesheet entry',
|
|
10
|
+
audience: 'both',
|
|
11
|
+
aiMetadata: { description: 'Logs a new timesheet entry in Bexio for a user against a client service/business activity, recording time either as a duration on a date or as a from/to range. Use to record worked or billable hours, optionally tying it to a contact, project, or milestone. Requires a user, client service, billable flag, and the tracking details for the chosen mode. Not idempotent: each call creates a separate entry.', idempotent: false },
|
|
12
|
+
props: {
|
|
13
|
+
user_id: Property.Dropdown({
|
|
14
|
+
auth: bexioAuth,
|
|
15
|
+
displayName: 'User',
|
|
16
|
+
description: 'User for this timesheet entry',
|
|
17
|
+
required: true,
|
|
18
|
+
refreshers: [],
|
|
19
|
+
options: async ({ auth }) => {
|
|
20
|
+
if (!auth) {
|
|
21
|
+
return {
|
|
22
|
+
disabled: true,
|
|
23
|
+
placeholder: 'Connect your Bexio account first',
|
|
24
|
+
options: [],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const client = new BexioClient(auth);
|
|
30
|
+
const users = await client.get<Array<{
|
|
31
|
+
id: number;
|
|
32
|
+
firstname?: string | null;
|
|
33
|
+
lastname?: string | null;
|
|
34
|
+
email: string;
|
|
35
|
+
}>>('/3.0/users');
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
disabled: false,
|
|
39
|
+
options: users.map((user) => {
|
|
40
|
+
const name = user.firstname && user.lastname
|
|
41
|
+
? `${user.firstname} ${user.lastname}`
|
|
42
|
+
: user.email;
|
|
43
|
+
return {
|
|
44
|
+
label: name,
|
|
45
|
+
value: user.id,
|
|
46
|
+
};
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
} catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
disabled: true,
|
|
52
|
+
placeholder: 'Failed to load users',
|
|
53
|
+
options: [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
status_id: Property.Dropdown({
|
|
59
|
+
auth: bexioAuth,
|
|
60
|
+
displayName: 'Status',
|
|
61
|
+
description: 'Timesheet status',
|
|
62
|
+
required: false,
|
|
63
|
+
refreshers: [],
|
|
64
|
+
options: async ({ auth }) => {
|
|
65
|
+
if (!auth) {
|
|
66
|
+
return {
|
|
67
|
+
disabled: true,
|
|
68
|
+
placeholder: 'Connect your Bexio account first',
|
|
69
|
+
options: [],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const client = new BexioClient(auth);
|
|
75
|
+
// TODO: Need to confirm endpoint - assuming /2.0/timesheet_status
|
|
76
|
+
const statuses = await client.get<Array<{ id: number; name: string }>>('/2.0/timesheet_status').catch(() => []);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
disabled: false,
|
|
80
|
+
options: statuses.map((status) => ({
|
|
81
|
+
label: status.name,
|
|
82
|
+
value: status.id,
|
|
83
|
+
})),
|
|
84
|
+
};
|
|
85
|
+
} catch (error) {
|
|
86
|
+
return {
|
|
87
|
+
disabled: true,
|
|
88
|
+
placeholder: 'Failed to load timesheet statuses',
|
|
89
|
+
options: [],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
}),
|
|
94
|
+
client_service_id: Property.Dropdown({
|
|
95
|
+
auth: bexioAuth,
|
|
96
|
+
displayName: 'Client Service',
|
|
97
|
+
description: 'Business activity/client service',
|
|
98
|
+
required: true,
|
|
99
|
+
refreshers: [],
|
|
100
|
+
options: async ({ auth }) => {
|
|
101
|
+
if (!auth) {
|
|
102
|
+
return {
|
|
103
|
+
disabled: true,
|
|
104
|
+
placeholder: 'Connect your Bexio account first',
|
|
105
|
+
options: [],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const client = new BexioClient(auth);
|
|
111
|
+
// TODO: Need to confirm endpoint - assuming /2.0/client_service
|
|
112
|
+
const services = await client.get<Array<{ id: number; name: string }>>('/2.0/client_service').catch(() => []);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
disabled: false,
|
|
116
|
+
options: services.map((service) => ({
|
|
117
|
+
label: service.name,
|
|
118
|
+
value: service.id,
|
|
119
|
+
})),
|
|
120
|
+
};
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return {
|
|
123
|
+
disabled: true,
|
|
124
|
+
placeholder: 'Failed to load client services',
|
|
125
|
+
options: [],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
}),
|
|
130
|
+
text: Property.LongText({
|
|
131
|
+
displayName: 'Description',
|
|
132
|
+
description: 'Description of the work performed',
|
|
133
|
+
required: false,
|
|
134
|
+
}),
|
|
135
|
+
allowable_bill: Property.Checkbox({
|
|
136
|
+
displayName: 'Allowable Bill',
|
|
137
|
+
description: 'Whether this time is billable',
|
|
138
|
+
required: true,
|
|
139
|
+
defaultValue: true,
|
|
140
|
+
}),
|
|
141
|
+
charge: Property.ShortText({
|
|
142
|
+
displayName: 'Charge',
|
|
143
|
+
description: 'Charge amount',
|
|
144
|
+
required: false,
|
|
145
|
+
}),
|
|
146
|
+
contact_id: Property.Dropdown({
|
|
147
|
+
auth: bexioAuth,
|
|
148
|
+
displayName: 'Contact',
|
|
149
|
+
description: 'Contact associated with this timesheet',
|
|
150
|
+
required: false,
|
|
151
|
+
refreshers: [],
|
|
152
|
+
options: async ({ auth }) => {
|
|
153
|
+
if (!auth) {
|
|
154
|
+
return {
|
|
155
|
+
disabled: true,
|
|
156
|
+
placeholder: 'Connect your Bexio account first',
|
|
157
|
+
options: [],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const client = new BexioClient(auth);
|
|
163
|
+
const contacts = await client.get<Array<{
|
|
164
|
+
id: number;
|
|
165
|
+
contact_type_id: number;
|
|
166
|
+
name_1: string;
|
|
167
|
+
name_2?: string | null;
|
|
168
|
+
nr?: string | null;
|
|
169
|
+
}>>('/2.0/contact');
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
disabled: false,
|
|
173
|
+
options: contacts.map((contact) => {
|
|
174
|
+
const name = contact.name_2
|
|
175
|
+
? `${contact.name_2} ${contact.name_1}`
|
|
176
|
+
: contact.name_1;
|
|
177
|
+
const label = contact.nr ? `${name} (#${contact.nr})` : name;
|
|
178
|
+
return {
|
|
179
|
+
label,
|
|
180
|
+
value: contact.id,
|
|
181
|
+
};
|
|
182
|
+
}),
|
|
183
|
+
};
|
|
184
|
+
} catch (error) {
|
|
185
|
+
return {
|
|
186
|
+
disabled: true,
|
|
187
|
+
placeholder: 'Failed to load contacts',
|
|
188
|
+
options: [],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
}),
|
|
193
|
+
sub_contact_id: Property.Dropdown({
|
|
194
|
+
auth: bexioAuth,
|
|
195
|
+
displayName: 'Sub Contact',
|
|
196
|
+
description: 'Sub contact (optional)',
|
|
197
|
+
required: false,
|
|
198
|
+
refreshers: [],
|
|
199
|
+
options: async ({ auth }) => {
|
|
200
|
+
if (!auth) {
|
|
201
|
+
return {
|
|
202
|
+
disabled: true,
|
|
203
|
+
placeholder: 'Connect your Bexio account first',
|
|
204
|
+
options: [],
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
const client = new BexioClient(auth);
|
|
210
|
+
const contacts = await client.get<Array<{
|
|
211
|
+
id: number;
|
|
212
|
+
contact_type_id: number;
|
|
213
|
+
name_1: string;
|
|
214
|
+
name_2?: string | null;
|
|
215
|
+
nr?: string | null;
|
|
216
|
+
}>>('/2.0/contact');
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
disabled: false,
|
|
220
|
+
options: contacts.map((contact) => {
|
|
221
|
+
const name = contact.name_2
|
|
222
|
+
? `${contact.name_2} ${contact.name_1}`
|
|
223
|
+
: contact.name_1;
|
|
224
|
+
const label = contact.nr ? `${name} (#${contact.nr})` : name;
|
|
225
|
+
return {
|
|
226
|
+
label,
|
|
227
|
+
value: contact.id,
|
|
228
|
+
};
|
|
229
|
+
}),
|
|
230
|
+
};
|
|
231
|
+
} catch (error) {
|
|
232
|
+
return {
|
|
233
|
+
disabled: true,
|
|
234
|
+
placeholder: 'Failed to load contacts',
|
|
235
|
+
options: [],
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
}),
|
|
240
|
+
pr_project_id: Property.Dropdown({
|
|
241
|
+
auth: bexioAuth,
|
|
242
|
+
displayName: 'Project',
|
|
243
|
+
description: 'Project associated with this timesheet',
|
|
244
|
+
required: false,
|
|
245
|
+
refreshers: [],
|
|
246
|
+
options: async ({ auth }) => {
|
|
247
|
+
if (!auth) {
|
|
248
|
+
return {
|
|
249
|
+
disabled: true,
|
|
250
|
+
placeholder: 'Connect your Bexio account first',
|
|
251
|
+
options: [],
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
const client = new BexioClient(auth);
|
|
257
|
+
const projects = await client.get<Array<{
|
|
258
|
+
id: number;
|
|
259
|
+
name: string;
|
|
260
|
+
nr?: string;
|
|
261
|
+
}>>('/2.0/pr_project');
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
disabled: false,
|
|
265
|
+
options: projects.map((project) => ({
|
|
266
|
+
label: project.nr ? `${project.name} (#${project.nr})` : project.name,
|
|
267
|
+
value: project.id,
|
|
268
|
+
})),
|
|
269
|
+
};
|
|
270
|
+
} catch (error) {
|
|
271
|
+
return {
|
|
272
|
+
disabled: true,
|
|
273
|
+
placeholder: 'Failed to load projects',
|
|
274
|
+
options: [],
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
}),
|
|
279
|
+
pr_package_id: Property.Number({
|
|
280
|
+
displayName: 'Package ID',
|
|
281
|
+
description: 'Project package ID',
|
|
282
|
+
required: false,
|
|
283
|
+
}),
|
|
284
|
+
pr_milestone_id: Property.Number({
|
|
285
|
+
displayName: 'Milestone ID',
|
|
286
|
+
description: 'Project milestone ID',
|
|
287
|
+
required: false,
|
|
288
|
+
}),
|
|
289
|
+
estimated_time: Property.ShortText({
|
|
290
|
+
displayName: 'Estimated Time',
|
|
291
|
+
description: 'Estimated time (format: HH:MM)',
|
|
292
|
+
required: false,
|
|
293
|
+
}),
|
|
294
|
+
tracking_type: Property.StaticDropdown({
|
|
295
|
+
displayName: 'Tracking Type',
|
|
296
|
+
description: 'Type of time tracking',
|
|
297
|
+
required: true,
|
|
298
|
+
defaultValue: 'duration',
|
|
299
|
+
options: {
|
|
300
|
+
disabled: false,
|
|
301
|
+
options: [
|
|
302
|
+
{ label: 'Duration', value: 'duration' },
|
|
303
|
+
{ label: 'Range', value: 'range' },
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
}),
|
|
307
|
+
tracking_details: Property.DynamicProperties({
|
|
308
|
+
auth: bexioAuth,
|
|
309
|
+
displayName: 'Tracking Details',
|
|
310
|
+
description: 'Time tracking details',
|
|
311
|
+
required: true,
|
|
312
|
+
refreshers: ['tracking_type'],
|
|
313
|
+
props: async ({ tracking_type }) => {
|
|
314
|
+
const type = (tracking_type as unknown as string) || 'duration';
|
|
315
|
+
const dynamicProps: Record<string, any> = {};
|
|
316
|
+
|
|
317
|
+
if (type === 'duration') {
|
|
318
|
+
dynamicProps['date'] = Property.ShortText({
|
|
319
|
+
displayName: 'Date',
|
|
320
|
+
description: 'Date of the timesheet entry (YYYY-MM-DD)',
|
|
321
|
+
required: true,
|
|
322
|
+
});
|
|
323
|
+
dynamicProps['duration'] = Property.ShortText({
|
|
324
|
+
displayName: 'Duration',
|
|
325
|
+
description: 'Duration of time tracked (format: HH:MM)',
|
|
326
|
+
required: true,
|
|
327
|
+
});
|
|
328
|
+
} else {
|
|
329
|
+
// Range type
|
|
330
|
+
dynamicProps['from'] = Property.DateTime({
|
|
331
|
+
displayName: 'From',
|
|
332
|
+
description: 'Start date and time',
|
|
333
|
+
required: true,
|
|
334
|
+
});
|
|
335
|
+
dynamicProps['to'] = Property.DateTime({
|
|
336
|
+
displayName: 'To',
|
|
337
|
+
description: 'End date and time',
|
|
338
|
+
required: true,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return dynamicProps;
|
|
343
|
+
},
|
|
344
|
+
}),
|
|
345
|
+
},
|
|
346
|
+
async run({ auth, propsValue }) {
|
|
347
|
+
const client = new BexioClient(auth);
|
|
348
|
+
const props = propsValue;
|
|
349
|
+
|
|
350
|
+
const requestBody: Record<string, unknown> = {
|
|
351
|
+
user_id: props['user_id'],
|
|
352
|
+
client_service_id: props['client_service_id'],
|
|
353
|
+
allowable_bill: props['allowable_bill'],
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
if (props['status_id']) {
|
|
357
|
+
requestBody['status_id'] = props['status_id'];
|
|
358
|
+
}
|
|
359
|
+
if (props['text']) {
|
|
360
|
+
requestBody['text'] = props['text'];
|
|
361
|
+
}
|
|
362
|
+
if (props['charge']) {
|
|
363
|
+
requestBody['charge'] = props['charge'];
|
|
364
|
+
}
|
|
365
|
+
if (props['contact_id']) {
|
|
366
|
+
requestBody['contact_id'] = props['contact_id'];
|
|
367
|
+
}
|
|
368
|
+
if (props['sub_contact_id']) {
|
|
369
|
+
requestBody['sub_contact_id'] = props['sub_contact_id'];
|
|
370
|
+
}
|
|
371
|
+
if (props['pr_project_id']) {
|
|
372
|
+
requestBody['pr_project_id'] = props['pr_project_id'];
|
|
373
|
+
}
|
|
374
|
+
if (props['pr_package_id']) {
|
|
375
|
+
requestBody['pr_package_id'] = props['pr_package_id'];
|
|
376
|
+
}
|
|
377
|
+
if (props['pr_milestone_id']) {
|
|
378
|
+
requestBody['pr_milestone_id'] = props['pr_milestone_id'];
|
|
379
|
+
}
|
|
380
|
+
if (props['estimated_time']) {
|
|
381
|
+
requestBody['estimated_time'] = props['estimated_time'];
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Build tracking object
|
|
385
|
+
const trackingType = props['tracking_type'] as string;
|
|
386
|
+
const trackingDetails = props['tracking_details'] as DynamicPropsValue;
|
|
387
|
+
const tracking: Record<string, unknown> = {
|
|
388
|
+
type: trackingType,
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
if (trackingType === 'duration') {
|
|
392
|
+
tracking['date'] = trackingDetails['date'];
|
|
393
|
+
tracking['duration'] = trackingDetails['duration'];
|
|
394
|
+
} else {
|
|
395
|
+
// Range type
|
|
396
|
+
tracking['from'] = trackingDetails['from'];
|
|
397
|
+
tracking['to'] = trackingDetails['to'];
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
requestBody['tracking'] = tracking;
|
|
401
|
+
|
|
402
|
+
const response = await client.post<{
|
|
403
|
+
id: number;
|
|
404
|
+
user_id: number;
|
|
405
|
+
client_service_id: number;
|
|
406
|
+
tracking: {
|
|
407
|
+
type: string;
|
|
408
|
+
date?: string;
|
|
409
|
+
duration?: string;
|
|
410
|
+
from?: string;
|
|
411
|
+
to?: string;
|
|
412
|
+
};
|
|
413
|
+
}>('/2.0/timesheet', requestBody);
|
|
414
|
+
|
|
415
|
+
return response;
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { createAction, Property, OAuth2PropertyValue } from '@agnocon/pieces-framework';
|
|
2
|
+
import { bexioAuth } from '../auth';
|
|
3
|
+
import { BexioClient } from '../common/client';
|
|
4
|
+
|
|
5
|
+
export const exportInvoicePdfAction = createAction({
|
|
6
|
+
auth: bexioAuth,
|
|
7
|
+
name: 'export_invoice_pdf',
|
|
8
|
+
displayName: 'Export Invoice to PDF',
|
|
9
|
+
description: 'Export an existing sales invoice as a PDF document',
|
|
10
|
+
audience: 'both',
|
|
11
|
+
aiMetadata: { description: 'Renders an existing Bexio sales invoice as a PDF and returns the downloadable file, keyed by the invoice id. Use when an agent needs the document itself (to attach or store); pick Send Sales Invoice to email it to a recipient instead. Optionally toggle the letterhead. Read-only and idempotent: it generates the file without changing the invoice.', idempotent: true },
|
|
12
|
+
props: {
|
|
13
|
+
invoice_id: Property.Dropdown({
|
|
14
|
+
auth: bexioAuth,
|
|
15
|
+
displayName: 'Invoice',
|
|
16
|
+
description: 'Select the invoice to export',
|
|
17
|
+
required: true,
|
|
18
|
+
refreshers: [],
|
|
19
|
+
options: async ({ auth }) => {
|
|
20
|
+
if (!auth) {
|
|
21
|
+
return {
|
|
22
|
+
disabled: true,
|
|
23
|
+
placeholder: 'Connect your Bexio account first',
|
|
24
|
+
options: [],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const client = new BexioClient(auth);
|
|
30
|
+
const invoices = await client.get<Array<{
|
|
31
|
+
id: number;
|
|
32
|
+
document_nr: string;
|
|
33
|
+
title?: string | null;
|
|
34
|
+
contact_id?: number | null;
|
|
35
|
+
total?: string;
|
|
36
|
+
kb_item_status_id?: number;
|
|
37
|
+
}>>('/2.0/kb_invoice');
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
disabled: false,
|
|
41
|
+
options: invoices.map((invoice) => {
|
|
42
|
+
const label = invoice.title
|
|
43
|
+
? `${invoice.document_nr} - ${invoice.title}`
|
|
44
|
+
: invoice.document_nr;
|
|
45
|
+
return {
|
|
46
|
+
label,
|
|
47
|
+
value: invoice.id,
|
|
48
|
+
};
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return {
|
|
53
|
+
disabled: true,
|
|
54
|
+
placeholder: 'Failed to load invoices',
|
|
55
|
+
options: [],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
}),
|
|
60
|
+
logopaper: Property.StaticDropdown({
|
|
61
|
+
displayName: 'Letterhead',
|
|
62
|
+
description: 'Whether to include letterhead in the PDF',
|
|
63
|
+
required: false,
|
|
64
|
+
defaultValue: 1,
|
|
65
|
+
options: {
|
|
66
|
+
disabled: false,
|
|
67
|
+
options: [
|
|
68
|
+
{ label: 'With Letterhead', value: 1 },
|
|
69
|
+
{ label: 'Without Letterhead', value: 0 },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
74
|
+
async run({ auth, propsValue, files }) {
|
|
75
|
+
const client = new BexioClient(auth);
|
|
76
|
+
const invoiceId = propsValue['invoice_id'] as number;
|
|
77
|
+
const logopaper = propsValue['logopaper'] as number | undefined;
|
|
78
|
+
|
|
79
|
+
const queryParams: Record<string, string> = {};
|
|
80
|
+
if (logopaper !== undefined) {
|
|
81
|
+
queryParams['logopaper'] = logopaper.toString();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const response = await client.get<{
|
|
85
|
+
name: string;
|
|
86
|
+
size: number;
|
|
87
|
+
mime: string;
|
|
88
|
+
content: string;
|
|
89
|
+
}>(`/2.0/kb_invoice/${invoiceId}/pdf`, queryParams);
|
|
90
|
+
|
|
91
|
+
const fileUrl = await files.write({
|
|
92
|
+
fileName: response.name || `invoice_${invoiceId}.pdf`,
|
|
93
|
+
data: Buffer.from(response.content, 'base64'),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
file: fileUrl,
|
|
98
|
+
fileName: response.name,
|
|
99
|
+
size: response.size,
|
|
100
|
+
mimeType: response.mime,
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { createAction, Property, OAuth2PropertyValue } from '@agnocon/pieces-framework';
|
|
2
|
+
import { bexioAuth } from '../auth';
|
|
3
|
+
import { BexioClient } from '../common/client';
|
|
4
|
+
|
|
5
|
+
export const findAccountAction = createAction({
|
|
6
|
+
auth: bexioAuth,
|
|
7
|
+
name: 'find_account',
|
|
8
|
+
displayName: 'Find Account',
|
|
9
|
+
description: 'Search for accounts using various criteria',
|
|
10
|
+
audience: 'both',
|
|
11
|
+
aiMetadata: { description: 'Searches the Bexio chart of accounts by number, name, type, or account group with operators such as contains, equals, or comparison, with paging. Use to resolve an account to its id before booking a manual entry or assigning an account on a product/position. Read-only and idempotent.', idempotent: true },
|
|
12
|
+
props: {
|
|
13
|
+
search_criteria: Property.Array({
|
|
14
|
+
displayName: 'Search Criteria',
|
|
15
|
+
description: 'Search criteria for finding accounts',
|
|
16
|
+
required: true,
|
|
17
|
+
properties: {
|
|
18
|
+
field: Property.StaticDropdown({
|
|
19
|
+
displayName: 'Search Field',
|
|
20
|
+
description: 'Field to search in',
|
|
21
|
+
required: true,
|
|
22
|
+
options: {
|
|
23
|
+
disabled: false,
|
|
24
|
+
options: [
|
|
25
|
+
{ label: 'Account Number', value: 'account_no' },
|
|
26
|
+
{ label: 'Account Name', value: 'name' },
|
|
27
|
+
{ label: 'Account Type', value: 'account_type' },
|
|
28
|
+
{ label: 'Account Group ID', value: 'fibu_account_group_id' },
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
value: Property.ShortText({
|
|
33
|
+
displayName: 'Search Value',
|
|
34
|
+
description: 'Value to search for',
|
|
35
|
+
required: true,
|
|
36
|
+
}),
|
|
37
|
+
criteria: Property.StaticDropdown({
|
|
38
|
+
displayName: 'Criteria',
|
|
39
|
+
description: 'Search criteria type',
|
|
40
|
+
required: false,
|
|
41
|
+
defaultValue: 'like',
|
|
42
|
+
options: {
|
|
43
|
+
disabled: false,
|
|
44
|
+
options: [
|
|
45
|
+
{ label: 'Contains (like)', value: 'like' },
|
|
46
|
+
{ label: 'Exact match (=)', value: '=' },
|
|
47
|
+
{ label: 'Exact match (equal)', value: 'equal' },
|
|
48
|
+
{ label: 'Not equal (!=)', value: '!=' },
|
|
49
|
+
{ label: 'Not equal (not_equal)', value: 'not_equal' },
|
|
50
|
+
{ label: 'Greater than (>)', value: '>' },
|
|
51
|
+
{ label: 'Greater than (greater_than)', value: 'greater_than' },
|
|
52
|
+
{ label: 'Greater or equal (>=)', value: '>=' },
|
|
53
|
+
{ label: 'Greater or equal (greater_equal)', value: 'greater_equal' },
|
|
54
|
+
{ label: 'Less than (<)', value: '<' },
|
|
55
|
+
{ label: 'Less than (less_than)', value: 'less_than' },
|
|
56
|
+
{ label: 'Less or equal (<=)', value: '<=' },
|
|
57
|
+
{ label: 'Less or equal (less_equal)', value: 'less_equal' },
|
|
58
|
+
{ label: 'Does not contain (not_like)', value: 'not_like' },
|
|
59
|
+
{ label: 'Is NULL', value: 'is_null' },
|
|
60
|
+
{ label: 'Is not NULL', value: 'not_null' },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
limit: Property.Number({
|
|
67
|
+
displayName: 'Limit',
|
|
68
|
+
description: 'Maximum number of results to return (max 2000)',
|
|
69
|
+
required: false,
|
|
70
|
+
defaultValue: 500,
|
|
71
|
+
}),
|
|
72
|
+
offset: Property.Number({
|
|
73
|
+
displayName: 'Offset',
|
|
74
|
+
description: 'Number of results to skip',
|
|
75
|
+
required: false,
|
|
76
|
+
defaultValue: 0,
|
|
77
|
+
}),
|
|
78
|
+
},
|
|
79
|
+
async run({ auth, propsValue }) {
|
|
80
|
+
const client = new BexioClient(auth);
|
|
81
|
+
const searchCriteria = propsValue['search_criteria'] as Array<Record<string, unknown>>;
|
|
82
|
+
const limit = propsValue['limit'] as number | undefined;
|
|
83
|
+
const offset = propsValue['offset'] as number | undefined;
|
|
84
|
+
|
|
85
|
+
const searchBody = searchCriteria.map((criteria) => ({
|
|
86
|
+
field: criteria['field'] as string,
|
|
87
|
+
value: criteria['value'] as string,
|
|
88
|
+
criteria: (criteria['criteria'] as string) || 'like',
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
const queryParams: Record<string, string> = {};
|
|
92
|
+
if (limit !== undefined) {
|
|
93
|
+
queryParams['limit'] = limit.toString();
|
|
94
|
+
}
|
|
95
|
+
if (offset !== undefined) {
|
|
96
|
+
queryParams['offset'] = offset.toString();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const response = await client.post<Array<{
|
|
100
|
+
id: number;
|
|
101
|
+
uuid: string;
|
|
102
|
+
account_no: string;
|
|
103
|
+
name: string;
|
|
104
|
+
account_type: number;
|
|
105
|
+
tax_id?: number;
|
|
106
|
+
fibu_account_group_id?: number;
|
|
107
|
+
is_active: boolean;
|
|
108
|
+
is_locked: boolean;
|
|
109
|
+
}>>('/2.0/accounts/search', searchBody, queryParams);
|
|
110
|
+
|
|
111
|
+
return response;
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|