@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,127 @@
1
+ import { Property, OAuth2PropertyValue } from '@agnocon/pieces-framework';
2
+ import { BexioClient } from './client';
3
+ import { BexioAccount, BexioTax, BexioCurrency } from './types';
4
+ import { bexioAuth } from '../auth';
5
+
6
+ export const bexioCommonProps = {
7
+ account: (options: {
8
+ displayName: string;
9
+ description?: string;
10
+ required: boolean;
11
+ }) => {
12
+ return Property.Dropdown({
13
+ auth: bexioAuth,
14
+ displayName: options.displayName,
15
+ description: options.description,
16
+ required: options.required,
17
+ refreshers: [],
18
+ options: async ({ auth }) => {
19
+ if (!auth) {
20
+ return {
21
+ disabled: true,
22
+ placeholder: 'Connect your Bexio account first',
23
+ options: [],
24
+ };
25
+ }
26
+
27
+ try {
28
+ const client = new BexioClient(auth);
29
+ const accounts = await client.get<BexioAccount[]>('/accounts');
30
+
31
+ return {
32
+ disabled: false,
33
+ options: accounts.map((account) => ({
34
+ label: `${account.account_no} - ${account.name}`,
35
+ value: account.id,
36
+ })),
37
+ };
38
+ } catch (error) {
39
+ return {
40
+ disabled: true,
41
+ placeholder: 'Failed to load accounts',
42
+ options: [],
43
+ };
44
+ }
45
+ },
46
+ });
47
+ },
48
+
49
+ tax: Property.Dropdown({
50
+ auth: bexioAuth,
51
+ displayName: 'Tax',
52
+ description: 'Select a tax rate',
53
+ required: false,
54
+ refreshers: [],
55
+ options: async ({ auth }) => {
56
+ if (!auth) {
57
+ return {
58
+ disabled: true,
59
+ placeholder: 'Connect your Bexio account first',
60
+ options: [],
61
+ };
62
+ }
63
+
64
+ try {
65
+ const client = new BexioClient(auth);
66
+ const taxes = await client.get<BexioTax[]>('/taxes');
67
+
68
+ return {
69
+ disabled: false,
70
+ options: taxes.map((tax) => ({
71
+ label: `${tax.name} (${tax.percentage}%)`,
72
+ value: tax.id,
73
+ })),
74
+ };
75
+ } catch (error) {
76
+ return {
77
+ disabled: true,
78
+ placeholder: 'Failed to load taxes',
79
+ options: [],
80
+ };
81
+ }
82
+ },
83
+ }),
84
+
85
+ currency: (options: {
86
+ displayName: string;
87
+ description?: string;
88
+ required: boolean;
89
+ }) => {
90
+ return Property.Dropdown({
91
+ auth: bexioAuth,
92
+ displayName: options.displayName,
93
+ description: options.description,
94
+ required: options.required,
95
+ refreshers: [],
96
+ options: async ({ auth }) => {
97
+ if (!auth) {
98
+ return {
99
+ disabled: true,
100
+ placeholder: 'Connect your Bexio account first',
101
+ options: [],
102
+ };
103
+ }
104
+
105
+ try {
106
+ const client = new BexioClient(auth);
107
+ const currencies = await client.get<BexioCurrency[]>('/3.0/currencies');
108
+
109
+ return {
110
+ disabled: false,
111
+ options: currencies.map((currency) => ({
112
+ label: currency.name,
113
+ value: currency.id,
114
+ })),
115
+ };
116
+ } catch (error) {
117
+ return {
118
+ disabled: true,
119
+ placeholder: 'Failed to load currencies',
120
+ options: [],
121
+ };
122
+ }
123
+ },
124
+ });
125
+ },
126
+ };
127
+
@@ -0,0 +1,99 @@
1
+ // Common types for Bexio API
2
+
3
+ export interface BexioContact {
4
+ id: number;
5
+ nr: string;
6
+ contact_type_id: number;
7
+ name_1: string;
8
+ name_2?: string;
9
+ salutation_id?: number;
10
+ salutation_form?: number;
11
+ title_id?: number;
12
+ birthday?: string;
13
+ address?: string;
14
+ postcode?: string;
15
+ city?: string;
16
+ country_id?: number;
17
+ mail?: string;
18
+ mail_second?: string;
19
+ phone_fixed?: string;
20
+ phone_fixed_second?: string;
21
+ phone_mobile?: string;
22
+ fax?: string;
23
+ url?: string;
24
+ skype_name?: string;
25
+ remarks?: string;
26
+ language_id?: number;
27
+ contact_group_ids?: string;
28
+ contact_branch_ids?: string;
29
+ user_id?: number;
30
+ owner_id?: number;
31
+ }
32
+
33
+ export interface BexioCompany {
34
+ id: number;
35
+ name: string;
36
+ address?: string;
37
+ address_nr?: string;
38
+ postcode?: string;
39
+ city?: string;
40
+ country_id?: number;
41
+ legal_form?: string;
42
+ }
43
+
44
+ export interface BexioAccount {
45
+ id: number;
46
+ account_no: string;
47
+ name: string;
48
+ account_type: number;
49
+ }
50
+
51
+ export interface BexioTax {
52
+ id: number;
53
+ name: string;
54
+ percentage: string;
55
+ }
56
+
57
+ export interface BexioCurrency {
58
+ id: number;
59
+ name: string;
60
+ }
61
+
62
+ export interface BexioManualEntry {
63
+ debit_account_id?: number;
64
+ credit_account_id?: number;
65
+ tax_id?: number;
66
+ tax_account_id?: number;
67
+ description?: string;
68
+ amount?: number;
69
+ currency_id?: number;
70
+ currency_factor?: number;
71
+ }
72
+
73
+ export interface BexioManualEntryResponse {
74
+ id: number;
75
+ type: 'manual_single_entry' | 'manual_compound_entry' | 'manual_group_entry';
76
+ date: string;
77
+ reference_nr?: string;
78
+ created_by_user_id?: number;
79
+ edited_by_user_id?: number;
80
+ entries: BexioManualEntry[];
81
+ is_locked?: boolean;
82
+ locked_info?: string;
83
+ }
84
+
85
+ export interface BexioError {
86
+ error_code: number;
87
+ message: string;
88
+ }
89
+
90
+ export interface BexioListResponse<T> {
91
+ data: T[];
92
+ paging?: {
93
+ page: number;
94
+ page_size: number;
95
+ page_count: number;
96
+ item_count: number;
97
+ };
98
+ }
99
+
@@ -0,0 +1,184 @@
1
+ import { createTrigger, TriggerStrategy, PiecePropValueSchema, Property, AppConnectionValueForAuthProperty } from '@agnocon/pieces-framework';
2
+ import { DedupeStrategy, Polling, pollingHelper } from '@agnocon/pieces-common';
3
+ import { bexioAuth } from '../auth';
4
+ import { BexioClient } from '../common/client';
5
+ import { OAuth2PropertyValue } from '@agnocon/pieces-framework';
6
+ import dayjs from 'dayjs';
7
+
8
+ const polling: Polling<
9
+ AppConnectionValueForAuthProperty<typeof bexioAuth>,
10
+ { status_id?: number }
11
+ > = {
12
+ strategy: DedupeStrategy.TIMEBASED,
13
+ items: async ({ auth, lastFetchEpochMS, propsValue }) => {
14
+ const client = new BexioClient(auth);
15
+
16
+ const isTest = lastFetchEpochMS === 0;
17
+
18
+ const lastFetchDate = isTest
19
+ ? dayjs().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss')
20
+ : dayjs(lastFetchEpochMS).format('YYYY-MM-DD HH:mm:ss');
21
+
22
+ const searchBody: Array<{ field: string; value: string; criteria: string }> = [
23
+ {
24
+ field: 'updated_at',
25
+ value: lastFetchDate,
26
+ criteria: '>=',
27
+ },
28
+ ];
29
+
30
+ if (propsValue.status_id !== undefined && propsValue.status_id !== null) {
31
+ searchBody.push({
32
+ field: 'kb_item_status_id',
33
+ value: propsValue.status_id.toString(),
34
+ criteria: '=',
35
+ });
36
+ }
37
+
38
+ const queryParams: Record<string, string> = {
39
+ order_by: 'updated_at_desc',
40
+ limit: isTest ? '5' : '500',
41
+ };
42
+
43
+ const orders = await client.post<Array<{
44
+ id: number;
45
+ document_nr: string;
46
+ title: string | null;
47
+ contact_id: number | null;
48
+ contact_sub_id: number | null;
49
+ user_id: number;
50
+ project_id: number | null;
51
+ language_id: number;
52
+ bank_account_id: number;
53
+ currency_id: number;
54
+ payment_type_id: number;
55
+ total_gross: string;
56
+ total_net: string;
57
+ total_taxes: string;
58
+ total: string;
59
+ kb_item_status_id: number;
60
+ is_valid_from: string;
61
+ updated_at: string;
62
+ }>>('/2.0/kb_order/search', searchBody, queryParams);
63
+
64
+ return orders.map((order) => {
65
+ const updatedAt = order.updated_at || new Date().toISOString();
66
+ const epochMilliSeconds = dayjs(updatedAt).valueOf();
67
+
68
+ return {
69
+ epochMilliSeconds,
70
+ data: order,
71
+ };
72
+ });
73
+ },
74
+ };
75
+
76
+ export const newOrderTrigger = createTrigger({
77
+ auth: bexioAuth,
78
+ name: 'new_order',
79
+ displayName: 'New Order',
80
+ description: 'Triggers when an Order is created or updated with the chosen status',
81
+ aiMetadata: {
82
+ description: 'Fires when a sales order is created or its updated timestamp changes in Bexio, optionally filtered to a chosen order status. Emits each matching order with its document number, contact, totals (gross, net, taxes), valid-from date, and status. Use to react to new or modified orders.',
83
+ },
84
+ type: TriggerStrategy.POLLING,
85
+ props: {
86
+ status_id: Property.Dropdown({
87
+ auth: bexioAuth,
88
+ displayName: 'Status',
89
+ description: 'Filter orders by status (leave empty to trigger for all statuses)',
90
+ required: false,
91
+ refreshers: [],
92
+ options: async ({ auth }) => {
93
+ if (!auth) {
94
+ return {
95
+ disabled: true,
96
+ placeholder: 'Connect your Bexio account first',
97
+ options: [],
98
+ };
99
+ }
100
+
101
+ try {
102
+ const client = new BexioClient(auth);
103
+ const statuses = await client.get<Array<{
104
+ id: number;
105
+ name: string;
106
+ }>>('/2.0/kb_order_status').catch(() => []);
107
+
108
+ if (statuses.length === 0) {
109
+ return {
110
+ disabled: false,
111
+ placeholder: 'Status filter not available - will trigger for all statuses',
112
+ options: [],
113
+ };
114
+ }
115
+
116
+ return {
117
+ disabled: false,
118
+ options: statuses.map((status) => ({
119
+ label: status.name,
120
+ value: status.id,
121
+ })),
122
+ };
123
+ } catch (error) {
124
+ return {
125
+ disabled: false,
126
+ placeholder: 'Enter status ID manually or leave empty for all statuses',
127
+ options: [],
128
+ };
129
+ }
130
+ },
131
+ }),
132
+ },
133
+ sampleData: {
134
+ id: 4,
135
+ document_nr: 'AU-00001',
136
+ title: null,
137
+ contact_id: 14,
138
+ contact_sub_id: null,
139
+ user_id: 1,
140
+ project_id: null,
141
+ language_id: 1,
142
+ bank_account_id: 1,
143
+ currency_id: 1,
144
+ payment_type_id: 1,
145
+ total_gross: '17.800000',
146
+ total_net: '17.800000',
147
+ total_taxes: '1.3706',
148
+ total: '19.150000',
149
+ kb_item_status_id: 5,
150
+ is_valid_from: '2019-06-24',
151
+ updated_at: '2019-04-08 13:17:32',
152
+ },
153
+ onEnable: async (context) => {
154
+ await pollingHelper.onEnable(polling, {
155
+ auth: context.auth,
156
+ store: context.store,
157
+ propsValue: context.propsValue,
158
+ });
159
+ },
160
+ onDisable: async (context) => {
161
+ await pollingHelper.onDisable(polling, {
162
+ auth: context.auth,
163
+ store: context.store,
164
+ propsValue: context.propsValue,
165
+ });
166
+ },
167
+ test: async (context) => {
168
+ return await pollingHelper.test(polling, {
169
+ auth: context.auth,
170
+ store: context.store,
171
+ propsValue: context.propsValue,
172
+ files: context.files,
173
+ });
174
+ },
175
+ run: async (context) => {
176
+ return await pollingHelper.poll(polling, {
177
+ auth: context.auth,
178
+ store: context.store,
179
+ propsValue: context.propsValue,
180
+ files: context.files,
181
+ });
182
+ },
183
+ });
184
+
@@ -0,0 +1,154 @@
1
+ import { createTrigger, TriggerStrategy, AppConnectionValueForAuthProperty } from '@agnocon/pieces-framework';
2
+ import { DedupeStrategy, Polling, pollingHelper } from '@agnocon/pieces-common';
3
+ import { bexioAuth } from '../auth';
4
+ import { BexioClient } from '../common/client';
5
+
6
+ const polling: Polling<
7
+ AppConnectionValueForAuthProperty<typeof bexioAuth>,
8
+ Record<string, never>
9
+ > = {
10
+ strategy: DedupeStrategy.LAST_ITEM,
11
+ items: async ({ auth, lastItemId }) => {
12
+ const client = new BexioClient(auth);
13
+
14
+ // Use GET endpoint to fetch all articles, then sort by ID descending
15
+ // This avoids the issue with empty search arrays
16
+ const queryParams: Record<string, string> = {
17
+ limit: '500',
18
+ };
19
+
20
+ const products = await client.get<Array<{
21
+ id: number;
22
+ user_id: number;
23
+ article_type_id: number;
24
+ contact_id: number | null;
25
+ deliverer_code: string | null;
26
+ deliverer_name: string | null;
27
+ deliverer_description: string | null;
28
+ intern_code: string;
29
+ intern_name: string;
30
+ intern_description: string | null;
31
+ purchase_price: string | null;
32
+ sale_price: string | null;
33
+ purchase_total: number | null;
34
+ sale_total: number | null;
35
+ currency_id: number | null;
36
+ tax_income_id: number | null;
37
+ tax_id: number | null;
38
+ tax_expense_id: number | null;
39
+ unit_id: number | null;
40
+ is_stock: boolean;
41
+ stock_id: number | null;
42
+ stock_place_id: number | null;
43
+ stock_nr: number;
44
+ stock_min_nr: number;
45
+ stock_reserved_nr: number;
46
+ stock_available_nr: number;
47
+ stock_picked_nr: number;
48
+ stock_disposed_nr: number;
49
+ stock_ordered_nr: number;
50
+ width: number | null;
51
+ height: number | null;
52
+ weight: number | null;
53
+ volume: number | null;
54
+ html_text: string | null;
55
+ remarks: string | null;
56
+ delivery_price: number | null;
57
+ article_group_id: number | null;
58
+ account_id: number | null;
59
+ expense_account_id: number | null;
60
+ }>>('/2.0/article', queryParams);
61
+
62
+ // Sort by ID descending to get newest first (since GET doesn't support order_by)
63
+ const sortedProducts = products.sort((a, b) => b.id - a.id);
64
+
65
+ return sortedProducts.map((product) => ({
66
+ id: product.id,
67
+ data: product,
68
+ }));
69
+ },
70
+ };
71
+
72
+ export const newProductTrigger = createTrigger({
73
+ auth: bexioAuth,
74
+ name: 'new_product',
75
+ displayName: 'New Product',
76
+ description: 'Triggers when a new product is created',
77
+ aiMetadata: {
78
+ description: 'Fires when a new product (article) is created in Bexio. Polls the article list and emits each newly added product, including its codes, names, pricing, stock levels, and accounting references. Use to react to additions to the product catalog.',
79
+ },
80
+ type: TriggerStrategy.POLLING,
81
+ props: {},
82
+ sampleData: {
83
+ id: 4,
84
+ user_id: 1,
85
+ article_type_id: 1,
86
+ contact_id: 14,
87
+ deliverer_code: null,
88
+ deliverer_name: null,
89
+ deliverer_description: null,
90
+ intern_code: 'wh-2019',
91
+ intern_name: 'Webhosting',
92
+ intern_description: null,
93
+ purchase_price: null,
94
+ sale_price: null,
95
+ purchase_total: null,
96
+ sale_total: null,
97
+ currency_id: null,
98
+ tax_income_id: null,
99
+ tax_id: null,
100
+ tax_expense_id: null,
101
+ unit_id: null,
102
+ is_stock: false,
103
+ stock_id: null,
104
+ stock_place_id: null,
105
+ stock_nr: 0,
106
+ stock_min_nr: 0,
107
+ stock_reserved_nr: 0,
108
+ stock_available_nr: 0,
109
+ stock_picked_nr: 0,
110
+ stock_disposed_nr: 0,
111
+ stock_ordered_nr: 0,
112
+ width: null,
113
+ height: null,
114
+ weight: null,
115
+ volume: null,
116
+ html_text: null,
117
+ remarks: null,
118
+ delivery_price: null,
119
+ article_group_id: null,
120
+ account_id: null,
121
+ expense_account_id: null,
122
+ },
123
+ onEnable: async (context) => {
124
+ await pollingHelper.onEnable(polling, {
125
+ auth: context.auth,
126
+ store: context.store,
127
+ propsValue: context.propsValue,
128
+ });
129
+ },
130
+ onDisable: async (context) => {
131
+ await pollingHelper.onDisable(polling, {
132
+ auth: context.auth,
133
+ store: context.store,
134
+ propsValue: context.propsValue,
135
+ });
136
+ },
137
+ test: async (context) => {
138
+ return await pollingHelper.test(polling, {
139
+ auth: context.auth,
140
+ store: context.store,
141
+ propsValue: context.propsValue,
142
+ files: context.files,
143
+ });
144
+ },
145
+ run: async (context) => {
146
+ return await pollingHelper.poll(polling, {
147
+ auth: context.auth,
148
+ store: context.store,
149
+ propsValue: context.propsValue,
150
+ files: context.files,
151
+ });
152
+ },
153
+ });
154
+