@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.
Files changed (182) hide show
  1. package/LICENSE.MIT-AP +24 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +93 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/actions/create-company.d.ts +28 -0
  7. package/dist/lib/actions/create-company.d.ts.map +1 -0
  8. package/dist/lib/actions/create-company.js +461 -0
  9. package/dist/lib/actions/create-company.js.map +1 -0
  10. package/dist/lib/actions/create-file.d.ts +4 -0
  11. package/dist/lib/actions/create-file.d.ts.map +1 -0
  12. package/dist/lib/actions/create-file.js +48 -0
  13. package/dist/lib/actions/create-file.js.map +1 -0
  14. package/dist/lib/actions/create-manual-entry.d.ts +7 -0
  15. package/dist/lib/actions/create-manual-entry.d.ts.map +1 -0
  16. package/dist/lib/actions/create-manual-entry.js +426 -0
  17. package/dist/lib/actions/create-manual-entry.js.map +1 -0
  18. package/dist/lib/actions/create-person.d.ts +30 -0
  19. package/dist/lib/actions/create-person.d.ts.map +1 -0
  20. package/dist/lib/actions/create-person.js +477 -0
  21. package/dist/lib/actions/create-person.js.map +1 -0
  22. package/dist/lib/actions/create-product.d.ts +34 -0
  23. package/dist/lib/actions/create-product.d.ts.map +1 -0
  24. package/dist/lib/actions/create-product.js +527 -0
  25. package/dist/lib/actions/create-product.js.map +1 -0
  26. package/dist/lib/actions/create-project.d.ts +17 -0
  27. package/dist/lib/actions/create-project.d.ts.map +1 -0
  28. package/dist/lib/actions/create-project.js +316 -0
  29. package/dist/lib/actions/create-project.js.map +1 -0
  30. package/dist/lib/actions/create-sales-invoice.d.ts +25 -0
  31. package/dist/lib/actions/create-sales-invoice.d.ts.map +1 -0
  32. package/dist/lib/actions/create-sales-invoice.js +615 -0
  33. package/dist/lib/actions/create-sales-invoice.js.map +1 -0
  34. package/dist/lib/actions/create-sales-order.d.ts +25 -0
  35. package/dist/lib/actions/create-sales-order.d.ts.map +1 -0
  36. package/dist/lib/actions/create-sales-order.js +642 -0
  37. package/dist/lib/actions/create-sales-order.js.map +1 -0
  38. package/dist/lib/actions/create-sales-quote.d.ts +28 -0
  39. package/dist/lib/actions/create-sales-quote.d.ts.map +1 -0
  40. package/dist/lib/actions/create-sales-quote.js +666 -0
  41. package/dist/lib/actions/create-sales-quote.js.map +1 -0
  42. package/dist/lib/actions/create-time-tracking.d.ts +17 -0
  43. package/dist/lib/actions/create-time-tracking.d.ts.map +1 -0
  44. package/dist/lib/actions/create-time-tracking.js +380 -0
  45. package/dist/lib/actions/create-time-tracking.js.map +1 -0
  46. package/dist/lib/actions/export-invoice-pdf.d.ts +5 -0
  47. package/dist/lib/actions/export-invoice-pdf.d.ts.map +1 -0
  48. package/dist/lib/actions/export-invoice-pdf.js +94 -0
  49. package/dist/lib/actions/export-invoice-pdf.js.map +1 -0
  50. package/dist/lib/actions/find-account.d.ts +6 -0
  51. package/dist/lib/actions/find-account.d.ts.map +1 -0
  52. package/dist/lib/actions/find-account.js +107 -0
  53. package/dist/lib/actions/find-account.js.map +1 -0
  54. package/dist/lib/actions/find-company.d.ts +8 -0
  55. package/dist/lib/actions/find-company.d.ts.map +1 -0
  56. package/dist/lib/actions/find-company.js +160 -0
  57. package/dist/lib/actions/find-company.js.map +1 -0
  58. package/dist/lib/actions/find-country.d.ts +7 -0
  59. package/dist/lib/actions/find-country.d.ts.map +1 -0
  60. package/dist/lib/actions/find-country.js +125 -0
  61. package/dist/lib/actions/find-country.js.map +1 -0
  62. package/dist/lib/actions/find-person.d.ts +9 -0
  63. package/dist/lib/actions/find-person.d.ts.map +1 -0
  64. package/dist/lib/actions/find-person.js +175 -0
  65. package/dist/lib/actions/find-person.js.map +1 -0
  66. package/dist/lib/actions/find-product.d.ts +7 -0
  67. package/dist/lib/actions/find-product.d.ts.map +1 -0
  68. package/dist/lib/actions/find-product.js +124 -0
  69. package/dist/lib/actions/find-product.js.map +1 -0
  70. package/dist/lib/actions/search-invoice.d.ts +7 -0
  71. package/dist/lib/actions/search-invoice.d.ts.map +1 -0
  72. package/dist/lib/actions/search-invoice.js +140 -0
  73. package/dist/lib/actions/search-invoice.js.map +1 -0
  74. package/dist/lib/actions/search-order.d.ts +7 -0
  75. package/dist/lib/actions/search-order.d.ts.map +1 -0
  76. package/dist/lib/actions/search-order.js +139 -0
  77. package/dist/lib/actions/search-order.js.map +1 -0
  78. package/dist/lib/actions/search-quote.d.ts +7 -0
  79. package/dist/lib/actions/search-quote.d.ts.map +1 -0
  80. package/dist/lib/actions/search-quote.js +140 -0
  81. package/dist/lib/actions/search-quote.js.map +1 -0
  82. package/dist/lib/actions/send-sales-invoice.d.ts +9 -0
  83. package/dist/lib/actions/send-sales-invoice.d.ts.map +1 -0
  84. package/dist/lib/actions/send-sales-invoice.js +110 -0
  85. package/dist/lib/actions/send-sales-invoice.js.map +1 -0
  86. package/dist/lib/actions/update-company.d.ts +29 -0
  87. package/dist/lib/actions/update-company.d.ts.map +1 -0
  88. package/dist/lib/actions/update-company.js +506 -0
  89. package/dist/lib/actions/update-company.js.map +1 -0
  90. package/dist/lib/actions/update-person.d.ts +31 -0
  91. package/dist/lib/actions/update-person.d.ts.map +1 -0
  92. package/dist/lib/actions/update-person.js +524 -0
  93. package/dist/lib/actions/update-person.js.map +1 -0
  94. package/dist/lib/actions/update-product.d.ts +34 -0
  95. package/dist/lib/actions/update-product.d.ts.map +1 -0
  96. package/dist/lib/actions/update-product.js +556 -0
  97. package/dist/lib/actions/update-product.js.map +1 -0
  98. package/dist/lib/auth.d.ts +2 -0
  99. package/dist/lib/auth.d.ts.map +1 -0
  100. package/dist/lib/auth.js +51 -0
  101. package/dist/lib/auth.js.map +1 -0
  102. package/dist/lib/common/client.d.ts +13 -0
  103. package/dist/lib/common/client.d.ts.map +1 -0
  104. package/dist/lib/common/client.js +64 -0
  105. package/dist/lib/common/client.js.map +1 -0
  106. package/dist/lib/common/index.d.ts +5 -0
  107. package/dist/lib/common/index.d.ts.map +1 -0
  108. package/dist/lib/common/index.js +10 -0
  109. package/dist/lib/common/index.js.map +1 -0
  110. package/dist/lib/common/props.d.ts +14 -0
  111. package/dist/lib/common/props.d.ts.map +1 -0
  112. package/dist/lib/common/props.js +118 -0
  113. package/dist/lib/common/props.js.map +1 -0
  114. package/dist/lib/common/types.d.ts +89 -0
  115. package/dist/lib/common/types.d.ts.map +1 -0
  116. package/dist/lib/common/types.js +6 -0
  117. package/dist/lib/common/types.js.map +1 -0
  118. package/dist/lib/triggers/new-order.d.ts +11 -0
  119. package/dist/lib/triggers/new-order.d.ts.map +1 -0
  120. package/dist/lib/triggers/new-order.js +152 -0
  121. package/dist/lib/triggers/new-order.js.map +1 -0
  122. package/dist/lib/triggers/new-product.d.ts +3 -0
  123. package/dist/lib/triggers/new-product.d.ts.map +1 -0
  124. package/dist/lib/triggers/new-product.js +111 -0
  125. package/dist/lib/triggers/new-product.js.map +1 -0
  126. package/dist/lib/triggers/new-project.d.ts +11 -0
  127. package/dist/lib/triggers/new-project.d.ts.map +1 -0
  128. package/dist/lib/triggers/new-project.js +141 -0
  129. package/dist/lib/triggers/new-project.js.map +1 -0
  130. package/dist/lib/triggers/new-quote.d.ts +11 -0
  131. package/dist/lib/triggers/new-quote.d.ts.map +1 -0
  132. package/dist/lib/triggers/new-quote.js +153 -0
  133. package/dist/lib/triggers/new-quote.js.map +1 -0
  134. package/dist/lib/triggers/new-sales-invoice.d.ts +11 -0
  135. package/dist/lib/triggers/new-sales-invoice.d.ts.map +1 -0
  136. package/dist/lib/triggers/new-sales-invoice.js +153 -0
  137. package/dist/lib/triggers/new-sales-invoice.js.map +1 -0
  138. package/dist/lib/triggers/new-updated-company.d.ts +3 -0
  139. package/dist/lib/triggers/new-updated-company.d.ts.map +1 -0
  140. package/dist/lib/triggers/new-updated-company.js +122 -0
  141. package/dist/lib/triggers/new-updated-company.js.map +1 -0
  142. package/dist/lib/triggers/new-updated-person.d.ts +3 -0
  143. package/dist/lib/triggers/new-updated-person.d.ts.map +1 -0
  144. package/dist/lib/triggers/new-updated-person.js +122 -0
  145. package/dist/lib/triggers/new-updated-person.js.map +1 -0
  146. package/package.json +48 -0
  147. package/src/index.ts +89 -0
  148. package/src/lib/actions/create-company.ts +464 -0
  149. package/src/lib/actions/create-file.ts +62 -0
  150. package/src/lib/actions/create-manual-entry.ts +445 -0
  151. package/src/lib/actions/create-person.ts +481 -0
  152. package/src/lib/actions/create-product.ts +563 -0
  153. package/src/lib/actions/create-project.ts +344 -0
  154. package/src/lib/actions/create-sales-invoice.ts +656 -0
  155. package/src/lib/actions/create-sales-order.ts +689 -0
  156. package/src/lib/actions/create-sales-quote.ts +713 -0
  157. package/src/lib/actions/create-time-tracking.ts +418 -0
  158. package/src/lib/actions/export-invoice-pdf.ts +104 -0
  159. package/src/lib/actions/find-account.ts +114 -0
  160. package/src/lib/actions/find-company.ts +193 -0
  161. package/src/lib/actions/find-country.ts +127 -0
  162. package/src/lib/actions/find-person.ts +208 -0
  163. package/src/lib/actions/find-product.ts +161 -0
  164. package/src/lib/actions/search-invoice.ts +157 -0
  165. package/src/lib/actions/search-order.ts +155 -0
  166. package/src/lib/actions/search-quote.ts +157 -0
  167. package/src/lib/actions/send-sales-invoice.ts +118 -0
  168. package/src/lib/actions/update-company.ts +518 -0
  169. package/src/lib/actions/update-person.ts +536 -0
  170. package/src/lib/actions/update-product.ts +594 -0
  171. package/src/lib/auth.ts +44 -0
  172. package/src/lib/common/client.ts +65 -0
  173. package/src/lib/common/index.ts +5 -0
  174. package/src/lib/common/props.ts +127 -0
  175. package/src/lib/common/types.ts +99 -0
  176. package/src/lib/triggers/new-order.ts +184 -0
  177. package/src/lib/triggers/new-product.ts +154 -0
  178. package/src/lib/triggers/new-project.ts +165 -0
  179. package/src/lib/triggers/new-quote.ts +186 -0
  180. package/src/lib/triggers/new-sales-invoice.ts +186 -0
  181. package/src/lib/triggers/new-updated-company.ts +161 -0
  182. package/src/lib/triggers/new-updated-person.ts +161 -0
@@ -0,0 +1,656 @@
1
+ import { createAction, Property, OAuth2PropertyValue } from '@agnocon/pieces-framework';
2
+ import { bexioAuth } from '../auth';
3
+ import { BexioClient } from '../common/client';
4
+ import { bexioCommonProps } from '../common/props';
5
+
6
+ export const createSalesInvoiceAction = createAction({
7
+ auth: bexioAuth,
8
+ name: 'create_sales_invoice',
9
+ displayName: 'Create Sales Invoice',
10
+ description: 'Create a new product-based sales invoice',
11
+ audience: 'both',
12
+ aiMetadata: { description: 'Creates a new sales invoice in Bexio from one or more line-item positions (custom, article, text, subtotal, discount, or page-break). Use when billing a customer for products or services; requires a user, language, bank account, currency, payment type, tax handling, and at least one position. Not idempotent: each call creates a separate invoice, so guard against duplicates.', idempotent: false },
13
+ props: {
14
+ document_nr: Property.ShortText({
15
+ displayName: 'Document Number',
16
+ description: 'Invoice number (required if automatic numbering is disabled)',
17
+ required: false,
18
+ }),
19
+ title: Property.ShortText({
20
+ displayName: 'Title',
21
+ description: 'Invoice title',
22
+ required: false,
23
+ }),
24
+ contact_id: Property.Dropdown({
25
+ auth: bexioAuth,
26
+ displayName: 'Contact',
27
+ description: 'The contact for this invoice',
28
+ required: false,
29
+ refreshers: [],
30
+ options: async ({ auth }) => {
31
+ if (!auth) {
32
+ return {
33
+ disabled: true,
34
+ placeholder: 'Connect your Bexio account first',
35
+ options: [],
36
+ };
37
+ }
38
+ try {
39
+ const client = new BexioClient(auth);
40
+ const contacts = await client.get<Array<{
41
+ id: number;
42
+ contact_type_id: number;
43
+ name_1: string;
44
+ name_2?: string | null;
45
+ nr?: string | null;
46
+ }>>('/2.0/contact');
47
+
48
+ return {
49
+ disabled: false,
50
+ options: contacts.map((contact) => {
51
+ const name = contact.name_2
52
+ ? `${contact.name_2} ${contact.name_1}`
53
+ : contact.name_1;
54
+ const label = contact.nr ? `${name} (#${contact.nr})` : name;
55
+ return {
56
+ label,
57
+ value: contact.id,
58
+ };
59
+ }),
60
+ };
61
+ } catch (error) {
62
+ return {
63
+ disabled: true,
64
+ placeholder: 'Failed to load contacts',
65
+ options: [],
66
+ };
67
+ }
68
+ },
69
+ }),
70
+ contact_sub_id: Property.Dropdown({
71
+ auth: bexioAuth,
72
+ displayName: 'Contact Sub',
73
+ description: 'Contact sub-address (optional)',
74
+ required: false,
75
+ refreshers: [],
76
+ options: async ({ auth }) => {
77
+ if (!auth) {
78
+ return {
79
+ disabled: true,
80
+ placeholder: 'Connect your Bexio account first',
81
+ options: [],
82
+ };
83
+ }
84
+
85
+ try {
86
+ const client = new BexioClient(auth);
87
+ const contacts = await client.get<Array<{
88
+ id: number;
89
+ contact_type_id: number;
90
+ name_1: string;
91
+ name_2?: string | null;
92
+ nr?: string | null;
93
+ }>>('/2.0/contact');
94
+
95
+ return {
96
+ disabled: false,
97
+ options: contacts.map((contact) => {
98
+ const name = contact.name_2
99
+ ? `${contact.name_2} ${contact.name_1}`
100
+ : contact.name_1;
101
+ const label = contact.nr ? `${name} (#${contact.nr})` : name;
102
+ return {
103
+ label,
104
+ value: contact.id,
105
+ };
106
+ }),
107
+ };
108
+ } catch (error) {
109
+ return {
110
+ disabled: true,
111
+ placeholder: 'Failed to load contacts',
112
+ options: [],
113
+ };
114
+ }
115
+ },
116
+ }),
117
+ user_id: Property.Dropdown({
118
+ auth: bexioAuth,
119
+ displayName: 'User',
120
+ description: 'User assigned to this invoice',
121
+ required: true,
122
+ refreshers: [],
123
+ options: async ({ auth }) => {
124
+ if (!auth) {
125
+ return {
126
+ disabled: true,
127
+ placeholder: 'Connect your Bexio account first',
128
+ options: [],
129
+ };
130
+ }
131
+
132
+ try {
133
+ const client = new BexioClient(auth);
134
+ const users = await client.get<Array<{ id: number; firstname: string | null; lastname: string | null; email: string }>>('/3.0/users');
135
+
136
+ return {
137
+ disabled: false,
138
+ options: users.map((user) => ({
139
+ label: `${user.firstname || ''} ${user.lastname || ''}`.trim() || user.email,
140
+ value: user.id,
141
+ })),
142
+ };
143
+ } catch (error) {
144
+ return {
145
+ disabled: true,
146
+ placeholder: 'Failed to load users',
147
+ options: [],
148
+ };
149
+ }
150
+ },
151
+ }),
152
+ pr_project_id: Property.Dropdown({
153
+ auth: bexioAuth,
154
+ displayName: 'Project',
155
+ description: 'Project associated with this invoice',
156
+ required: false,
157
+ refreshers: [],
158
+ options: async ({ auth }) => {
159
+ if (!auth) {
160
+ return {
161
+ disabled: true,
162
+ placeholder: 'Connect your Bexio account first',
163
+ options: [],
164
+ };
165
+ }
166
+
167
+ try {
168
+ const client = new BexioClient(auth);
169
+ const projects = await client.get<Array<{
170
+ id: number;
171
+ name: string;
172
+ nr?: string;
173
+ }>>('/2.0/pr_project');
174
+
175
+ return {
176
+ disabled: false,
177
+ options: projects.map((project) => ({
178
+ label: project.nr ? `${project.name} (#${project.nr})` : project.name,
179
+ value: project.id,
180
+ })),
181
+ };
182
+ } catch (error) {
183
+ return {
184
+ disabled: true,
185
+ placeholder: 'Failed to load projects',
186
+ options: [],
187
+ };
188
+ }
189
+ },
190
+ }),
191
+ language_id: Property.Dropdown({
192
+ auth: bexioAuth,
193
+ displayName: 'Language',
194
+ description: 'Language for the invoice',
195
+ required: true,
196
+ refreshers: [],
197
+ options: async ({ auth }) => {
198
+ if (!auth) {
199
+ return {
200
+ disabled: true,
201
+ placeholder: 'Connect your Bexio account first',
202
+ options: [],
203
+ };
204
+ }
205
+
206
+ try {
207
+ const client = new BexioClient(auth);
208
+ const languages = await client.get<Array<{ id: number; name: string }>>('/2.0/language');
209
+
210
+ return {
211
+ disabled: false,
212
+ options: languages.map((lang) => ({
213
+ label: lang.name,
214
+ value: lang.id,
215
+ })),
216
+ };
217
+ } catch (error) {
218
+ return {
219
+ disabled: true,
220
+ placeholder: 'Failed to load languages',
221
+ options: [],
222
+ };
223
+ }
224
+ },
225
+ }),
226
+ bank_account_id: Property.Dropdown({
227
+ auth: bexioAuth,
228
+ displayName: 'Bank Account',
229
+ description: 'Bank account for payment',
230
+ required: true,
231
+ refreshers: [],
232
+ options: async ({ auth }) => {
233
+ if (!auth) {
234
+ return {
235
+ disabled: true,
236
+ placeholder: 'Connect your Bexio account first',
237
+ options: [],
238
+ };
239
+ }
240
+
241
+ try {
242
+ const client = new BexioClient(auth);
243
+ const bankAccounts = await client.get<Array<{
244
+ id: number;
245
+ name: string;
246
+ iban_nr?: string;
247
+ bank_account_nr?: string;
248
+ }>>('/3.0/banking/accounts');
249
+
250
+ return {
251
+ disabled: false,
252
+ options: bankAccounts.map((account) => {
253
+ const iban = account.iban_nr || account.bank_account_nr;
254
+ return {
255
+ label: iban ? `${account.name} (${iban})` : account.name,
256
+ value: account.id,
257
+ };
258
+ }),
259
+ };
260
+ } catch (error) {
261
+ return {
262
+ disabled: true,
263
+ placeholder: 'Failed to load bank accounts',
264
+ options: [],
265
+ };
266
+ }
267
+ },
268
+ }),
269
+ currency_id: bexioCommonProps.currency({
270
+ displayName: 'Currency',
271
+ required: true,
272
+ }),
273
+ payment_type_id: Property.Dropdown({
274
+ auth: bexioAuth,
275
+ displayName: 'Payment Type',
276
+ description: 'Payment type for this invoice',
277
+ required: true,
278
+ refreshers: [],
279
+ options: async ({ auth }) => {
280
+ if (!auth) {
281
+ return {
282
+ disabled: true,
283
+ placeholder: 'Connect your Bexio account first',
284
+ options: [],
285
+ };
286
+ }
287
+
288
+ try {
289
+ const client = new BexioClient(auth);
290
+ const paymentTypes = await client.get<Array<{ id: number; name: string }>>('/2.0/payment_type');
291
+
292
+ return {
293
+ disabled: false,
294
+ options: paymentTypes.map((type) => ({
295
+ label: type.name,
296
+ value: type.id,
297
+ })),
298
+ };
299
+ } catch (error) {
300
+ return {
301
+ disabled: true,
302
+ placeholder: 'Failed to load payment types',
303
+ options: [],
304
+ };
305
+ }
306
+ },
307
+ }),
308
+ header: Property.LongText({
309
+ displayName: 'Header',
310
+ description: 'Header text for the invoice',
311
+ required: false,
312
+ }),
313
+ footer: Property.LongText({
314
+ displayName: 'Footer',
315
+ description: 'Footer text for the invoice',
316
+ required: false,
317
+ }),
318
+ mwst_type: Property.StaticDropdown({
319
+ displayName: 'Tax Type',
320
+ description: 'How taxes are handled',
321
+ required: true,
322
+ defaultValue: 0,
323
+ options: {
324
+ disabled: false,
325
+ options: [
326
+ { label: 'Including taxes', value: 0 },
327
+ { label: 'Excluding taxes', value: 1 },
328
+ { label: 'Exempt from taxes', value: 2 },
329
+ ],
330
+ },
331
+ }),
332
+ mwst_is_net: Property.Checkbox({
333
+ displayName: 'Tax is Net',
334
+ description: 'If taxes are included, set to true to add taxes to total, false to include in total',
335
+ required: false,
336
+ defaultValue: false,
337
+ }),
338
+ show_position_taxes: Property.Checkbox({
339
+ displayName: 'Show Position Taxes',
340
+ description: 'Show taxes for each position',
341
+ required: false,
342
+ defaultValue: false,
343
+ }),
344
+ is_valid_from: Property.ShortText({
345
+ displayName: 'Valid From',
346
+ description: 'Invoice valid from date (YYYY-MM-DD)',
347
+ required: false,
348
+ }),
349
+ is_valid_to: Property.ShortText({
350
+ displayName: 'Valid To',
351
+ description: 'Invoice valid to date (YYYY-MM-DD)',
352
+ required: false,
353
+ }),
354
+ contact_address_manual: Property.LongText({
355
+ displayName: 'Manual Contact Address',
356
+ description: 'Override contact address (leave empty to use contact address)',
357
+ required: false,
358
+ }),
359
+ reference: Property.ShortText({
360
+ displayName: 'Reference',
361
+ description: 'Reference number',
362
+ required: false,
363
+ }),
364
+ api_reference: Property.ShortText({
365
+ displayName: 'API Reference',
366
+ description: 'Reference for API use (can only be edited via API)',
367
+ required: false,
368
+ }),
369
+ template_slug: Property.Dropdown({
370
+ auth: bexioAuth,
371
+ displayName: 'Document Template',
372
+ description: 'Document template for the invoice',
373
+ required: false,
374
+ refreshers: [],
375
+ options: async ({ auth }) => {
376
+ if (!auth) {
377
+ return {
378
+ disabled: true,
379
+ placeholder: 'Connect your Bexio account first',
380
+ options: [],
381
+ };
382
+ }
383
+
384
+ try {
385
+ const client = new BexioClient(auth);
386
+ const templates = await client.get<Array<{
387
+ template_slug: string;
388
+ name: string;
389
+ is_default: boolean;
390
+ default_for_document_types: string[];
391
+ }>>('/3.0/document_templates');
392
+
393
+ return {
394
+ disabled: false,
395
+ options: templates.map((template) => ({
396
+ label: template.is_default ? `${template.name} (Default)` : template.name,
397
+ value: template.template_slug,
398
+ })),
399
+ };
400
+ } catch (error) {
401
+ return {
402
+ disabled: true,
403
+ placeholder: 'Failed to load templates',
404
+ options: [],
405
+ };
406
+ }
407
+ },
408
+ }),
409
+ positionFields: Property.DynamicProperties({
410
+ auth: bexioAuth,
411
+ displayName: 'Invoice Positions',
412
+ description: 'Configure invoice line items',
413
+ required: true,
414
+ refreshers: ['auth'],
415
+ props: async ({ auth }) => {
416
+ let units: Array<{ id: number; name: string }> = [];
417
+ let accounts: Array<{ id: number; account_no: string; name: string }> = [];
418
+ let taxes: Array<{ id: number; name: string; percentage: string }> = [];
419
+
420
+ if (auth) {
421
+ try {
422
+ const client = new BexioClient(auth);
423
+ units = await client.get<Array<{ id: number; name: string }>>('/2.0/unit').catch(() => []);
424
+ accounts = await client.get<Array<{ id: number; account_no: string; name: string }>>('/accounts').catch(() => []);
425
+ const taxesResponse = await client.get<Array<{
426
+ id: number;
427
+ name: string;
428
+ value: number;
429
+ display_name?: string;
430
+ }>>('/3.0/taxes?types=sales_tax&scope=active').catch(() => []);
431
+ taxes = taxesResponse.map((tax) => ({
432
+ id: tax.id,
433
+ name: tax.display_name || tax.name,
434
+ percentage: tax.value.toString(),
435
+ }));
436
+ } catch (error) {
437
+ // Ignore error, use empty array as fallback
438
+ }
439
+ }
440
+
441
+ const unitOptions = units.map((unit) => ({ label: unit.name, value: unit.id }));
442
+ const accountOptions = accounts.map((acc) => ({ label: `${acc.account_no} - ${acc.name}`, value: acc.id }));
443
+ const taxOptions = taxes.map((tax) => ({ label: `${tax.name} (${tax.percentage}%)`, value: tax.id }));
444
+
445
+ return {
446
+ positions: Property.Array({
447
+ displayName: 'Positions',
448
+ description: 'Invoice line items',
449
+ required: true,
450
+ properties: {
451
+ type: Property.StaticDropdown({
452
+ displayName: 'Position Type',
453
+ description: 'Type of invoice position',
454
+ required: true,
455
+ defaultValue: 'KbPositionCustom',
456
+ options: {
457
+ disabled: false,
458
+ options: [
459
+ { label: 'Custom Position', value: 'KbPositionCustom' },
460
+ { label: 'Article Position', value: 'KbPositionArticle' },
461
+ { label: 'Text Position', value: 'KbPositionText' },
462
+ { label: 'Subtotal Position', value: 'KbPositionSubtotal' },
463
+ { label: 'Page Break Position', value: 'KbPositionPagebreak' },
464
+ { label: 'Discount Position', value: 'KbPositionDiscount' },
465
+ ],
466
+ },
467
+ }),
468
+ amount: Property.ShortText({
469
+ displayName: 'Amount',
470
+ description: 'Quantity/amount',
471
+ required: true,
472
+ }),
473
+ unit_id: unitOptions.length > 0
474
+ ? Property.StaticDropdown({
475
+ displayName: 'Unit',
476
+ description: 'Unit of measurement',
477
+ required: false,
478
+ options: {
479
+ disabled: false,
480
+ options: unitOptions,
481
+ },
482
+ })
483
+ : Property.Number({
484
+ displayName: 'Unit ID',
485
+ description: 'Unit ID (use List Units action to find IDs)',
486
+ required: false,
487
+ }),
488
+ account_id: accountOptions.length > 0
489
+ ? Property.StaticDropdown({
490
+ displayName: 'Account',
491
+ description: 'Account for this position',
492
+ required: false,
493
+ options: {
494
+ disabled: false,
495
+ options: accountOptions,
496
+ },
497
+ })
498
+ : Property.Number({
499
+ displayName: 'Account ID',
500
+ description: 'Account ID (use List Accounts action to find IDs)',
501
+ required: false,
502
+ }),
503
+ tax_id: taxOptions.length > 0
504
+ ? Property.StaticDropdown({
505
+ displayName: 'Tax',
506
+ description: 'Tax rate (only active sales taxes)',
507
+ required: false,
508
+ options: {
509
+ disabled: false,
510
+ options: taxOptions,
511
+ },
512
+ })
513
+ : Property.Number({
514
+ displayName: 'Tax ID',
515
+ description: 'Tax ID (use List Taxes action to find IDs)',
516
+ required: false,
517
+ }),
518
+ text: Property.LongText({
519
+ displayName: 'Description',
520
+ description: 'Position description/text',
521
+ required: false,
522
+ }),
523
+ unit_price: Property.ShortText({
524
+ displayName: 'Unit Price',
525
+ description: 'Price per unit (max 6 decimals)',
526
+ required: false,
527
+ }),
528
+ discount_in_percent: Property.ShortText({
529
+ displayName: 'Discount (%)',
530
+ description: 'Discount percentage (max 6 decimals)',
531
+ required: false,
532
+ }),
533
+ parent_id: Property.Number({
534
+ displayName: 'Parent ID',
535
+ description: 'Parent position ID (for grouped positions)',
536
+ required: false,
537
+ }),
538
+ },
539
+ }),
540
+ };
541
+ },
542
+ }),
543
+ },
544
+ async run(context) {
545
+ const client = new BexioClient(context.auth);
546
+ const props = context.propsValue;
547
+
548
+ const requestBody: Record<string, unknown> = {};
549
+
550
+ if (props['user_id']) {
551
+ requestBody['user_id'] = props['user_id'];
552
+ }
553
+ if (props['language_id']) {
554
+ requestBody['language_id'] = props['language_id'];
555
+ }
556
+ if (props['bank_account_id']) {
557
+ requestBody['bank_account_id'] = props['bank_account_id'];
558
+ }
559
+ if (props['currency_id']) {
560
+ requestBody['currency_id'] = props['currency_id'];
561
+ }
562
+ if (props['payment_type_id']) {
563
+ requestBody['payment_type_id'] = props['payment_type_id'];
564
+ }
565
+
566
+ if (props['document_nr']) {
567
+ requestBody['document_nr'] = props['document_nr'];
568
+ }
569
+ if (props['title'] !== undefined) {
570
+ requestBody['title'] = props['title'] || null;
571
+ }
572
+ if (props['contact_id']) {
573
+ requestBody['contact_id'] = props['contact_id'];
574
+ }
575
+ if (props['contact_sub_id']) {
576
+ requestBody['contact_sub_id'] = props['contact_sub_id'];
577
+ }
578
+ if (props['pr_project_id']) {
579
+ requestBody['pr_project_id'] = props['pr_project_id'];
580
+ }
581
+ if (props['header']) {
582
+ requestBody['header'] = props['header'];
583
+ }
584
+ if (props['footer']) {
585
+ requestBody['footer'] = props['footer'];
586
+ }
587
+ if (props['mwst_type'] !== undefined) {
588
+ requestBody['mwst_type'] = props['mwst_type'];
589
+ }
590
+ if (props['mwst_is_net'] !== undefined) {
591
+ requestBody['mwst_is_net'] = props['mwst_is_net'];
592
+ }
593
+ if (props['show_position_taxes'] !== undefined) {
594
+ requestBody['show_position_taxes'] = props['show_position_taxes'];
595
+ }
596
+ if (props['is_valid_from']) {
597
+ requestBody['is_valid_from'] = props['is_valid_from'];
598
+ }
599
+ if (props['is_valid_to']) {
600
+ requestBody['is_valid_to'] = props['is_valid_to'];
601
+ }
602
+ if (props['contact_address_manual']) {
603
+ requestBody['contact_address_manual'] = props['contact_address_manual'];
604
+ }
605
+ if (props['reference']) {
606
+ requestBody['reference'] = props['reference'];
607
+ }
608
+ if (props['api_reference']) {
609
+ requestBody['api_reference'] = props['api_reference'];
610
+ }
611
+ if (props['template_slug']) {
612
+ requestBody['template_slug'] = props['template_slug'];
613
+ }
614
+
615
+ const positionFields = props['positionFields'] as Record<string, unknown>;
616
+ if (positionFields && positionFields['positions'] && Array.isArray(positionFields['positions'])) {
617
+ requestBody['positions'] = (positionFields['positions'] as Array<Record<string, unknown>>).map((position) => {
618
+ const pos: Record<string, unknown> = {
619
+ type: position['type'] || 'KbPositionCustom',
620
+ };
621
+
622
+ if (position['amount']) {
623
+ pos['amount'] = position['amount'];
624
+ }
625
+ if (position['unit_id']) {
626
+ pos['unit_id'] = position['unit_id'];
627
+ }
628
+ if (position['account_id']) {
629
+ pos['account_id'] = position['account_id'];
630
+ }
631
+ if (position['tax_id']) {
632
+ pos['tax_id'] = position['tax_id'];
633
+ }
634
+ if (position['text']) {
635
+ pos['text'] = position['text'];
636
+ }
637
+ if (position['unit_price']) {
638
+ pos['unit_price'] = position['unit_price'];
639
+ }
640
+ if (position['discount_in_percent']) {
641
+ pos['discount_in_percent'] = position['discount_in_percent'];
642
+ }
643
+ if (position['parent_id']) {
644
+ pos['parent_id'] = position['parent_id'];
645
+ }
646
+
647
+ return pos;
648
+ });
649
+ }
650
+
651
+ const response = await client.post('/2.0/kb_invoice', requestBody);
652
+
653
+ return response;
654
+ },
655
+ });
656
+