@worknice/js-sdk 0.0.2 → 0.0.3

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 (101) hide show
  1. package/dist/_types-BXw9D0Qi.d.ts +642 -0
  2. package/dist/api/WorkniceIntegrationLogger.d.ts +99 -0
  3. package/dist/api/WorkniceIntegrationLogger.js +173 -0
  4. package/dist/api/WorkniceIntegrationLogger.js.map +1 -0
  5. package/dist/api/_generated.d.ts +357 -22
  6. package/dist/api/_generated.js.map +1 -1
  7. package/dist/api/_types.d.ts +2 -2
  8. package/dist/api/_types.js +1 -0
  9. package/dist/api/_types.js.map +1 -1
  10. package/dist/api/createApiOperation.d.ts +1 -1
  11. package/dist/api/createWorkniceClient.d.ts +1 -1
  12. package/dist/api/createWorkniceClient.js +21 -1
  13. package/dist/api/createWorkniceClient.js.map +1 -1
  14. package/dist/api/operations/activateIntegration.d.ts +1 -1
  15. package/dist/api/operations/authorizeIntegration.d.ts +20 -0
  16. package/dist/api/operations/authorizeIntegration.js +23 -0
  17. package/dist/api/operations/authorizeIntegration.js.map +1 -0
  18. package/dist/api/operations/completeSync.d.ts +20 -0
  19. package/dist/api/operations/completeSync.js +23 -0
  20. package/dist/api/operations/completeSync.js.map +1 -0
  21. package/dist/api/operations/createApiToken.d.ts +1 -1
  22. package/dist/api/operations/createDataImport.d.ts +12 -0
  23. package/dist/api/operations/createDataImport.js +25 -0
  24. package/dist/api/operations/createDataImport.js.map +1 -0
  25. package/dist/api/operations/createPersonConnection.d.ts +132 -0
  26. package/dist/api/operations/createPersonConnection.js +65 -0
  27. package/dist/api/operations/createPersonConnection.js.map +1 -0
  28. package/dist/api/operations/createPersonDataImportLine.d.ts +22 -0
  29. package/dist/api/operations/createPersonDataImportLine.js +49 -0
  30. package/dist/api/operations/createPersonDataImportLine.js.map +1 -0
  31. package/dist/api/operations/deleteApiToken.d.ts +1 -1
  32. package/dist/api/operations/deletePersonConnection.d.ts +10 -0
  33. package/dist/api/operations/deletePersonConnection.js +21 -0
  34. package/dist/api/operations/deletePersonConnection.js.map +1 -0
  35. package/dist/api/operations/getApiTokens.d.ts +1 -1
  36. package/dist/api/operations/getIntegration.d.ts +65 -0
  37. package/dist/api/operations/getIntegration.js +32 -0
  38. package/dist/api/operations/getIntegration.js.map +1 -0
  39. package/dist/api/operations/getPeople.d.ts +65 -0
  40. package/dist/api/operations/getPeople.js +79 -0
  41. package/dist/api/operations/getPeople.js.map +1 -0
  42. package/dist/api/operations/getPersonConnections.d.ts +107 -0
  43. package/dist/api/operations/getPersonConnections.js +43 -0
  44. package/dist/api/operations/getPersonConnections.js.map +1 -0
  45. package/dist/api/operations/initializeIntegration.d.ts +1 -1
  46. package/dist/api/operations/updatePersonConnection.d.ts +132 -0
  47. package/dist/api/operations/updatePersonConnection.js +65 -0
  48. package/dist/api/operations/updatePersonConnection.js.map +1 -0
  49. package/dist/employee-records/EQUALITY_CHECKS.d.ts +1 -0
  50. package/dist/employee-records/EQUALITY_CHECKS.js +0 -1
  51. package/dist/employee-records/EQUALITY_CHECKS.js.map +1 -1
  52. package/dist/employee-records/_types.d.ts +13 -12
  53. package/dist/employee-records/comparePersonDataTransferLines.d.ts +1 -0
  54. package/dist/employee-records/comparePersonDataTransferLines.js +0 -3
  55. package/dist/employee-records/comparePersonDataTransferLines.js.map +1 -1
  56. package/dist/employee-records/index.d.ts +1 -0
  57. package/dist/employee-records/mergePersonDataTransferLines.d.ts +1 -0
  58. package/dist/employee-records/mergePersonDataTransferLines.js +0 -1
  59. package/dist/employee-records/mergePersonDataTransferLines.js.map +1 -1
  60. package/dist/employee-records/validatePersonDataTransferLine.d.ts +1 -0
  61. package/dist/employee-records/validatePersonDataTransferLineBankAccounts.d.ts +1 -0
  62. package/dist/employee-records/validatePersonDataTransferLineBankAccounts.js +10 -9
  63. package/dist/employee-records/validatePersonDataTransferLineBankAccounts.js.map +1 -1
  64. package/dist/employee-records/validatePersonDataTransferLineEmergencyContacts.d.ts +1 -0
  65. package/dist/employee-records/validatePersonDataTransferLinePersonalDetails.d.ts +1 -0
  66. package/dist/employee-records/validatePersonDataTransferLinePersonalDetails.js +0 -2
  67. package/dist/employee-records/validatePersonDataTransferLinePersonalDetails.js.map +1 -1
  68. package/dist/employee-records/validatePersonDataTransferLinePostalAddress.d.ts +1 -0
  69. package/dist/employee-records/validatePersonDataTransferLineResidentialAddress.d.ts +1 -0
  70. package/dist/employee-records/validatePersonDataTransferLineSuperFunds.d.ts +1 -0
  71. package/dist/employee-records/validatePersonDataTransferLineTaxDetails.d.ts +1 -0
  72. package/dist/employee-records/validatePersonDataTransferLineTenure.d.ts +1 -0
  73. package/dist/helpers/_types.d.ts +7 -6
  74. package/dist/helpers/handleCreateIntegrationWebhook.d.ts +2 -1
  75. package/dist/helpers/handleCreateIntegrationWebhook.js +6 -4
  76. package/dist/helpers/handleCreateIntegrationWebhook.js.map +1 -1
  77. package/dist/helpers/handleGetAuthorizationUrlWebhook.d.ts +2 -1
  78. package/dist/helpers/handleGetAuthorizationUrlWebhook.js +4 -1
  79. package/dist/helpers/handleGetAuthorizationUrlWebhook.js.map +1 -1
  80. package/dist/helpers/handleGetLeaveBalancesWebhook.d.ts +14 -0
  81. package/dist/helpers/handleGetLeaveBalancesWebhook.js +22 -0
  82. package/dist/helpers/handleGetLeaveBalancesWebhook.js.map +1 -0
  83. package/dist/helpers/handleRequestWithWorknice.d.ts +9 -14
  84. package/dist/helpers/handleRequestWithWorknice.js +40 -19
  85. package/dist/helpers/handleRequestWithWorknice.js.map +1 -1
  86. package/dist/helpers/handleTriggerIntegrationSyncWebhook.d.ts +72 -0
  87. package/dist/helpers/handleTriggerIntegrationSyncWebhook.js +600 -0
  88. package/dist/helpers/handleTriggerIntegrationSyncWebhook.js.map +1 -0
  89. package/dist/helpers/index.d.ts +7 -1
  90. package/dist/helpers/index.js +9 -1
  91. package/dist/helpers/index.js.map +1 -1
  92. package/dist/index.d.ts +1 -0
  93. package/dist/utils/disambiguatePersonConnections.d.ts +25 -0
  94. package/dist/utils/disambiguatePersonConnections.js +18 -0
  95. package/dist/utils/disambiguatePersonConnections.js.map +1 -0
  96. package/dist/utils/isNotNullable.d.ts +10 -0
  97. package/dist/utils/isNotNullable.js +6 -0
  98. package/dist/utils/isNotNullable.js.map +1 -0
  99. package/dist/webhooks.d.ts +13 -1
  100. package/package.json +8 -4
  101. package/dist/_types-DsB4q143.d.ts +0 -127
@@ -0,0 +1,600 @@
1
+ import { Temporal } from "temporal-polyfill";
2
+ import { ConnectionStatus } from "../api/_types.js";
3
+ import comparePersonDataTransferLines from "../employee-records/comparePersonDataTransferLines.js";
4
+ import mergePersonDataTransferLines from "../employee-records/mergePersonDataTransferLines.js";
5
+ import validatePersonDataTransferLineBankAccounts from "../employee-records/validatePersonDataTransferLineBankAccounts.js";
6
+ import validatePersonDataTransferLinePersonalDetails from "../employee-records/validatePersonDataTransferLinePersonalDetails.js";
7
+ import validatePersonDataTransferLineResidentialAddress from "../employee-records/validatePersonDataTransferLineResidentialAddress.js";
8
+ import isAfter from "../utils/isAfter.js";
9
+ import handleRequestWithWorknice from "./handleRequestWithWorknice.js";
10
+ const handleTriggerIntegrationSyncWebhook = async (request, {
11
+ createRemotePerson,
12
+ getApiToken,
13
+ getConfig,
14
+ getEnv,
15
+ getRemotePeople,
16
+ updateRemotePerson
17
+ }, options) => handleRequestWithWorknice(
18
+ request,
19
+ {
20
+ getApiToken,
21
+ getEnv,
22
+ handleRequest: async (context) => {
23
+ const { logger, payload, worknice } = context;
24
+ try {
25
+ logger.connect(worknice, payload.integrationId);
26
+ logger.indent("Retrieving Worknice data\u2026");
27
+ const integration = await worknice.getIntegration({
28
+ integrationId: payload.integrationId
29
+ });
30
+ if (integration.archived) {
31
+ logger.info("Integration is archived. Skipping sync.");
32
+ return;
33
+ }
34
+ if (integration.status !== "SYNCING") {
35
+ logger.info("Integration does not have a syncing status. Skipping sync.");
36
+ return;
37
+ }
38
+ logger.info("Retrieved integration from Worknice.");
39
+ const personConnections = await worknice.getPersonConnections({
40
+ integrationId: payload.integrationId
41
+ });
42
+ logger.info(`Retrieved ${personConnections.length} person connection(s) from Worknice.`);
43
+ const people = await worknice.getPeople({ orgId: integration.org.id });
44
+ logger.info(`Retrieved ${people.length} person(s) from Worknice.`);
45
+ logger.dedent("Completed retrieving Worknice data.");
46
+ const contextWithIntegration = {
47
+ ...context,
48
+ integration
49
+ };
50
+ logger.indent("Loading configuration details\u2026");
51
+ const config = await getConfig(contextWithIntegration);
52
+ logger.info(
53
+ config.automaticMatching ? "Automatic matching enabled." : "Automatic matching disabled."
54
+ );
55
+ logger.info(`Using a "${config.mode}" sync mode.`);
56
+ logger.dedent("Finished loading configuration details.");
57
+ logger.indent(`Retrieving ${config.appName} data\u2026`);
58
+ const remotePeople = await getRemotePeople(contextWithIntegration);
59
+ logger.info(`Retrieved ${remotePeople.length} people from ${config.appName}.`);
60
+ logger.dedent(`Completed retrieving ${config.appName} data.`);
61
+ logger.indent("Updating person connections\u2026");
62
+ for (const remotePerson of remotePeople) {
63
+ const remotePersonName = `${remotePerson.personalDetails?.givenName} ${remotePerson.personalDetails?.familyName}`;
64
+ try {
65
+ const remotePersonConnection = personConnections.find(
66
+ (connection) => connection.remote?.id === remotePerson.metadata.sourceId
67
+ );
68
+ if (remotePerson.metadata.deleted) {
69
+ if (remotePersonConnection) {
70
+ await worknice.deletePersonConnection({
71
+ personConnectionId: remotePersonConnection.id
72
+ });
73
+ logger.info(
74
+ `Deleted connection for "${remotePerson.personalDetails?.givenName} ${remotePerson.personalDetails?.familyName}" in ${config.appName} because they have been terminated.`
75
+ );
76
+ }
77
+ } else {
78
+ if (remotePersonConnection && (remotePersonConnection.status === ConnectionStatus.Connected || remotePersonConnection.status === ConnectionStatus.Merged)) {
79
+ if (remotePersonConnection.remote?.name !== remotePersonName) {
80
+ const connection = await worknice.updatePersonConnection({
81
+ personConnectionId: remotePersonConnection.id,
82
+ personId: remotePersonConnection.person.id,
83
+ remote: {
84
+ id: remotePerson.metadata.sourceId,
85
+ name: remotePersonName
86
+ },
87
+ status: remotePersonConnection.status
88
+ });
89
+ personConnections.splice(
90
+ personConnections.indexOf(remotePersonConnection),
91
+ 1,
92
+ connection
93
+ );
94
+ logger.info(
95
+ `Updated person connection remote name from "${remotePersonConnection.remote?.name}" to "${remotePersonName}".`
96
+ );
97
+ }
98
+ } else {
99
+ if (remotePersonConnection && remotePersonConnection.remote?.name !== remotePersonName) {
100
+ const connection = await worknice.updatePersonConnection({
101
+ personConnectionId: remotePersonConnection.id,
102
+ remote: {
103
+ id: remotePerson.metadata.sourceId,
104
+ name: remotePersonName
105
+ },
106
+ status: remotePersonConnection.status
107
+ });
108
+ personConnections.splice(
109
+ personConnections.indexOf(remotePersonConnection),
110
+ 1,
111
+ connection
112
+ );
113
+ logger.info(
114
+ `Updated person connection remote name from "${remotePersonConnection.remote?.name}" to "${remotePersonName}".`
115
+ );
116
+ }
117
+ const matchingWorknicePerson = people.find(
118
+ (person) => person.employeeCode !== null && person.employeeCode === remotePerson.metadata.employeeCode || person.personalEmail !== null && person.personalEmail === remotePerson.personalDetails?.personalEmail || person.profileEmail !== null && person.profileEmail === remotePerson.profile?.profileEmail
119
+ ) ?? null;
120
+ if (config.automaticMatching === true && matchingWorknicePerson) {
121
+ const personConnection = personConnections.find(
122
+ (connection) => connection.person?.id === matchingWorknicePerson.id
123
+ );
124
+ if (personConnection?.status === ConnectionStatus.Connected || personConnection?.status === ConnectionStatus.Merged) {
125
+ logger.info(
126
+ `Unable to automatically match person "${matchingWorknicePerson.displayName}" in Worknice to person "${remotePersonName}" in ${config.appName} because the Worknice person has already been matched to a different ${config.appName} person.`
127
+ );
128
+ } else {
129
+ if (personConnection) {
130
+ if (remotePersonConnection) {
131
+ await worknice.deletePersonConnection({
132
+ personConnectionId: personConnection.id
133
+ });
134
+ personConnections.splice(personConnections.indexOf(personConnection), 1);
135
+ const updatedConnection = await worknice.updatePersonConnection({
136
+ personConnectionId: remotePersonConnection.id,
137
+ personId: matchingWorknicePerson.id,
138
+ remote: {
139
+ id: remotePerson.metadata.sourceId,
140
+ name: remotePersonName
141
+ },
142
+ status: ConnectionStatus.Connected
143
+ });
144
+ personConnections.splice(
145
+ personConnections.indexOf(remotePersonConnection),
146
+ 1,
147
+ updatedConnection
148
+ );
149
+ logger.info(
150
+ `Automatically matched and combined person connections for person "${matchingWorknicePerson.displayName}" in Worknice and person "${remotePersonName}" in ${config.appName}.`
151
+ );
152
+ } else {
153
+ const updatedConnection = await worknice.updatePersonConnection({
154
+ personConnectionId: personConnection.id,
155
+ personId: personConnection.person.id,
156
+ remote: {
157
+ id: remotePerson.metadata.sourceId,
158
+ name: remotePersonName
159
+ },
160
+ status: ConnectionStatus.Connected
161
+ });
162
+ personConnections.splice(
163
+ personConnections.indexOf(personConnection),
164
+ 1,
165
+ updatedConnection
166
+ );
167
+ logger.info(
168
+ `Automatically matched existing person connection for person "${matchingWorknicePerson.displayName}" in Worknice to person "${remotePersonName}" in ${config.appName}.`
169
+ );
170
+ }
171
+ } else {
172
+ if (remotePersonConnection) {
173
+ const updatedConnection = await worknice.updatePersonConnection({
174
+ personConnectionId: remotePersonConnection.id,
175
+ personId: matchingWorknicePerson.id,
176
+ remote: {
177
+ ...remotePersonConnection.remote,
178
+ name: remotePersonName
179
+ },
180
+ status: ConnectionStatus.Connected
181
+ });
182
+ personConnections.splice(
183
+ personConnections.indexOf(remotePersonConnection),
184
+ 1,
185
+ updatedConnection
186
+ );
187
+ logger.info(
188
+ `Automatically matched existing person connection for person "${remotePersonName}" in ${config.appName} to person "${matchingWorknicePerson.displayName}" in Worknice.`
189
+ );
190
+ } else {
191
+ const newPersonConnection = await worknice.createPersonConnection({
192
+ integrationId: payload.integrationId,
193
+ personId: matchingWorknicePerson.id,
194
+ remote: {
195
+ id: remotePerson.metadata.sourceId,
196
+ name: remotePersonName
197
+ },
198
+ status: ConnectionStatus.Connected
199
+ });
200
+ personConnections.push(newPersonConnection);
201
+ logger.info(
202
+ `Created new person connection for person "${remotePersonName}" in ${config.appName} and automatically matched to person "${matchingWorknicePerson.displayName}" in Worknice.`
203
+ );
204
+ }
205
+ }
206
+ }
207
+ } else if (remotePersonConnection === void 0) {
208
+ const newPersonConnection = await worknice.createPersonConnection({
209
+ integrationId: payload.integrationId,
210
+ remote: {
211
+ id: remotePerson.metadata.sourceId,
212
+ name: remotePersonName
213
+ },
214
+ status: ConnectionStatus.RemoteOnly
215
+ });
216
+ personConnections.push(newPersonConnection);
217
+ logger.info(
218
+ `New person connection created for person "${remotePersonName}" in ${config.appName}.`
219
+ );
220
+ }
221
+ }
222
+ }
223
+ } catch (error) {
224
+ logger.info(
225
+ `Unable to update person connection for person "${remotePersonName}" in ${config.appName} because of the following error:
226
+
227
+ ${error instanceof Error ? error.message : error}
228
+ `
229
+ );
230
+ }
231
+ }
232
+ logger.dedent("Finished updating person connections.");
233
+ if (config.mode === "one-way" || config.mode === "two-way") {
234
+ const dataImport = await worknice.createDataImport({
235
+ integrationId: payload.integrationId
236
+ });
237
+ logger.indent("Updating people with connections marked as merged\u2026");
238
+ const mergedConnections = personConnections.filter(
239
+ (personConnection) => personConnection.status === ConnectionStatus.Merged
240
+ );
241
+ for (const personConnection of mergedConnections) {
242
+ const worknicePerson = people.find(
243
+ (person) => person.id === personConnection.person.id
244
+ );
245
+ const remotePerson = remotePeople.find(
246
+ (person) => person.metadata.sourceId === personConnection.remote.id
247
+ );
248
+ if (!worknicePerson) {
249
+ throw Error(
250
+ `Unable to find person in Worknice with the ID "${personConnection.person.id}".`
251
+ );
252
+ }
253
+ if (!remotePerson) {
254
+ throw Error(
255
+ `Unable to find person in ${config.appName} with the ID "${personConnection.remote.id}".`
256
+ );
257
+ }
258
+ const remotePersonName = `${remotePerson.personalDetails?.givenName} ${remotePerson.personalDetails?.familyName}`;
259
+ const worknicePersonDataTransferLine = {
260
+ ...worknicePersonToPersonDataTransferLine(worknicePerson),
261
+ metadata: {
262
+ deleted: false,
263
+ employeeCode: worknicePerson.employeeCode ?? null,
264
+ sourceId: worknicePerson.id,
265
+ targetId: remotePerson.metadata.sourceId,
266
+ updatedAt: worknicePerson.updatedAt
267
+ },
268
+ profile: {
269
+ profileEmail: worknicePerson.profileEmail ?? null
270
+ }
271
+ };
272
+ const myobPersonDataTransferLine = remotePerson;
273
+ const comparison = comparePersonDataTransferLines(
274
+ worknicePersonDataTransferLine,
275
+ myobPersonDataTransferLine
276
+ );
277
+ if (comparison.hasDifferences && (comparison.sections.bankAccounts.hasDifferences || comparison.sections.personalDetails.hasDifferences || comparison.sections.residentialAddress.hasDifferences)) {
278
+ const worknicePersonUpdatedAt = Temporal.Instant.from(worknicePerson.updatedAt);
279
+ const myobEmployeeUpdatedAt = Temporal.PlainDateTime.from(
280
+ remotePerson.metadata.updatedAt
281
+ ).toZonedDateTime(Temporal.TimeZone.from("UTC")).toInstant();
282
+ if (isAfter(worknicePersonUpdatedAt, myobEmployeeUpdatedAt)) {
283
+ if (config.mode === "two-way") {
284
+ if (!updateRemotePerson) {
285
+ throw Error(
286
+ "No updateRemotePerson function supplied to handleTriggerIntegrationSyncWebhook."
287
+ );
288
+ }
289
+ try {
290
+ await updateRemotePerson(
291
+ worknicePersonDataTransferLine,
292
+ contextWithIntegration
293
+ );
294
+ logger.info(`Updated person "${remotePersonName}" in ${config.appName}.`);
295
+ } catch (error) {
296
+ logger.info(
297
+ `Unable to update person "${remotePersonName}" in ${config.appName} because of the following error:
298
+
299
+ ${error instanceof Error ? error.message : error}
300
+ `
301
+ );
302
+ }
303
+ }
304
+ } else {
305
+ try {
306
+ const personalDetails = validatePersonDataTransferLinePersonalDetails(
307
+ myobPersonDataTransferLine.personalDetails
308
+ );
309
+ const bankAccounts = validatePersonDataTransferLineBankAccounts(
310
+ myobPersonDataTransferLine.bankAccounts
311
+ );
312
+ const residentialAddress = validatePersonDataTransferLineResidentialAddress(
313
+ myobPersonDataTransferLine.residentialAddress
314
+ );
315
+ await worknice.createPersonDataImportLine({
316
+ bankAccounts,
317
+ config: {
318
+ bankAccounts: config.syncFields?.bankAccounts ?? false,
319
+ emergencyContacts: config.syncFields?.emergencyContacts ?? false,
320
+ personalDetails: config.syncFields?.personalDetails ?? false,
321
+ postalAddress: config.syncFields?.personalDetails ?? false,
322
+ profile: config.syncFields?.profile ?? false,
323
+ remuneration: config.syncFields?.remuneration ?? false,
324
+ residentialAddress: config.syncFields?.residentialAddress ?? false,
325
+ superFunds: config.syncFields?.superFunds ?? false,
326
+ taxDetails: config.syncFields?.taxDetails ?? false,
327
+ tenure: config.syncFields?.tenure ?? false
328
+ },
329
+ dataImportId: dataImport.id,
330
+ emergencyContacts: null,
331
+ personalDetails,
332
+ personId: worknicePerson.id,
333
+ postalAddress: null,
334
+ residentialAddress,
335
+ // TODO: Enable syncing super funds. See PROD-2216.
336
+ superFunds: null,
337
+ // TODO: Enable syncing tax details. See PROD-2375.
338
+ taxDetails: null,
339
+ // TODO: Enable syncing tenure. See PROD-1371.
340
+ tenure: null
341
+ });
342
+ logger.info(`Updated person "${worknicePerson.displayName}" in Worknice.`);
343
+ } catch (error) {
344
+ logger.info(
345
+ `Unable to update person "${worknicePerson.displayName}" in Worknice because of the following error:
346
+
347
+ ${error instanceof Error ? error.message : error}
348
+ `
349
+ );
350
+ }
351
+ }
352
+ }
353
+ }
354
+ logger.dedent("Finished updating people with connections marked as merged.");
355
+ logger.indent("Merging unmerged connections\u2026");
356
+ const connectedConnections = personConnections.filter(
357
+ (personConnection) => personConnection.status === ConnectionStatus.Connected
358
+ );
359
+ for (const personConnection of connectedConnections) {
360
+ const worknicePerson = people.find(
361
+ (person) => person.id === personConnection.person.id
362
+ );
363
+ const remotePerson = remotePeople.find(
364
+ (person) => person.metadata.sourceId === personConnection.remote.id
365
+ );
366
+ if (!worknicePerson) {
367
+ throw Error(
368
+ `Unable to find person in Worknice with the ID "${personConnection.person.id}".`
369
+ );
370
+ }
371
+ if (!remotePerson) {
372
+ throw Error(
373
+ `Unable to find person in ${config.appName} with the ID "${personConnection.remote.id}".`
374
+ );
375
+ }
376
+ const remotePersonName = `${remotePerson.personalDetails?.givenName} ${remotePerson.personalDetails?.familyName}`;
377
+ logger.indent(
378
+ `Merging Worknice person "${worknicePerson.displayName}" with ${config.appName} person "${remotePersonName}"\u2026`
379
+ );
380
+ try {
381
+ const worknicePersonUpdatedAt = Temporal.Instant.from(worknicePerson.updatedAt);
382
+ const myobEmployeeUpdatedAt = Temporal.PlainDateTime.from(
383
+ remotePerson.metadata.updatedAt
384
+ ).toZonedDateTime(Temporal.TimeZone.from("UTC")).toInstant();
385
+ const [primaryDataTransferLine, secondaryDataTransferLine] = isAfter(
386
+ worknicePersonUpdatedAt,
387
+ myobEmployeeUpdatedAt
388
+ ) ? [worknicePersonToPersonDataTransferLine(worknicePerson), remotePerson] : [remotePerson, worknicePersonToPersonDataTransferLine(worknicePerson)];
389
+ const mergedDataTransferLine = mergePersonDataTransferLines(
390
+ primaryDataTransferLine,
391
+ secondaryDataTransferLine
392
+ );
393
+ const personalDetails = validatePersonDataTransferLinePersonalDetails(
394
+ mergedDataTransferLine.personalDetails
395
+ );
396
+ const bankAccounts = validatePersonDataTransferLineBankAccounts(
397
+ mergedDataTransferLine.bankAccounts
398
+ );
399
+ const residentialAddress = validatePersonDataTransferLineResidentialAddress(
400
+ mergedDataTransferLine.residentialAddress
401
+ );
402
+ await worknice.createPersonDataImportLine({
403
+ bankAccounts,
404
+ config: {
405
+ bankAccounts: config.syncFields?.bankAccounts ?? false,
406
+ emergencyContacts: config.syncFields?.emergencyContacts ?? false,
407
+ personalDetails: config.syncFields?.personalDetails ?? false,
408
+ postalAddress: config.syncFields?.personalDetails ?? false,
409
+ profile: config.syncFields?.profile ?? false,
410
+ remuneration: config.syncFields?.remuneration ?? false,
411
+ residentialAddress: config.syncFields?.residentialAddress ?? false,
412
+ superFunds: config.syncFields?.superFunds ?? false,
413
+ taxDetails: config.syncFields?.taxDetails ?? false,
414
+ tenure: config.syncFields?.tenure ?? false
415
+ },
416
+ dataImportId: dataImport.id,
417
+ emergencyContacts: null,
418
+ personalDetails,
419
+ personId: worknicePerson.id,
420
+ postalAddress: null,
421
+ residentialAddress,
422
+ // TODO: Enable syncing super funds. See PROD-2216.
423
+ superFunds: null,
424
+ // TODO: Enable syncing tax details. See PROD-2375.
425
+ taxDetails: null,
426
+ // TODO: Enable syncing tenure. See PROD-1371.
427
+ tenure: null
428
+ });
429
+ logger.info(`Updated person "${worknicePerson.displayName}" in Worknice.`);
430
+ if (config.mode === "two-way") {
431
+ if (!updateRemotePerson) {
432
+ throw Error(
433
+ "No updateRemotePerson function supplied to handleTriggerIntegrationSyncWebhook."
434
+ );
435
+ }
436
+ await updateRemotePerson(
437
+ {
438
+ ...mergedDataTransferLine,
439
+ metadata: {
440
+ deleted: false,
441
+ employeeCode: worknicePerson.employeeCode ?? null,
442
+ sourceId: worknicePerson.id,
443
+ targetId: remotePerson.metadata.sourceId,
444
+ updatedAt: worknicePerson.updatedAt
445
+ },
446
+ profile: {
447
+ profileEmail: worknicePerson.profileEmail ?? null
448
+ }
449
+ },
450
+ contextWithIntegration
451
+ );
452
+ logger.info(`Updated person "${remotePersonName}" in ${config.appName}.`);
453
+ }
454
+ await worknice.updatePersonConnection({
455
+ personConnectionId: personConnection.id,
456
+ personId: personConnection.person.id,
457
+ remote: {
458
+ id: remotePerson.metadata.sourceId,
459
+ name: remotePersonName
460
+ },
461
+ status: ConnectionStatus.Merged
462
+ });
463
+ logger.dedent(`Finished merging.`);
464
+ } catch (error) {
465
+ logger.info(
466
+ `Unable to merge ${config.appName} person "${remotePersonName}" and Worknice person "${worknicePerson.displayName}" because of the following error:
467
+
468
+ ${error instanceof Error ? error.message : error}
469
+ `
470
+ );
471
+ logger.dedent();
472
+ }
473
+ }
474
+ logger.dedent("Finished merging unmerged connections.");
475
+ if (config.mode === "two-way") {
476
+ logger.indent(`Adding new people to ${config.appName}\u2026`);
477
+ const localOnlyConnections = personConnections.filter(
478
+ (personConnection) => personConnection.status === ConnectionStatus.LocalOnly
479
+ );
480
+ for (const personConnection of localOnlyConnections) {
481
+ const worknicePerson = people.find(
482
+ (person) => person.id === personConnection.person.id
483
+ );
484
+ if (!worknicePerson) {
485
+ throw Error(
486
+ `Unable to find person in Worknice with the ID "${personConnection.person.id}".`
487
+ );
488
+ }
489
+ try {
490
+ if (!createRemotePerson) {
491
+ throw Error(
492
+ "No createRemotePerson function supplied to handleTriggerIntegrationSyncWebhook."
493
+ );
494
+ }
495
+ const remote = await createRemotePerson(
496
+ {
497
+ ...worknicePersonToPersonDataTransferLine(worknicePerson),
498
+ metadata: {
499
+ deleted: false,
500
+ employeeCode: worknicePerson.employeeCode ?? null,
501
+ sourceId: worknicePerson.id,
502
+ targetId: null,
503
+ updatedAt: worknicePerson.updatedAt
504
+ },
505
+ profile: {
506
+ profileEmail: worknicePerson.profileEmail ?? null
507
+ }
508
+ },
509
+ contextWithIntegration
510
+ );
511
+ await worknice.updatePersonConnection({
512
+ personConnectionId: personConnection.id,
513
+ personId: personConnection.person.id,
514
+ remote,
515
+ status: ConnectionStatus.Merged
516
+ });
517
+ logger.info(`Added new person "${remote.name}" to ${config.appName}.`);
518
+ } catch (error) {
519
+ logger.info(
520
+ `Unable to add person "${worknicePerson.displayName}" in Worknice to ${config.appName} because of the following error:
521
+
522
+ ${error instanceof Error ? error.message : error}
523
+ `
524
+ );
525
+ }
526
+ }
527
+ logger.dedent(`Finished adding new people to ${config.appName}.`);
528
+ }
529
+ }
530
+ await worknice.completeSync({ integrationId: payload.integrationId });
531
+ logger.info("Sync completed.");
532
+ } catch (error) {
533
+ await worknice.completeSync({ integrationId: payload.integrationId });
534
+ throw error;
535
+ }
536
+ },
537
+ parsePayload: async ({ request: request2 }) => request2.json()
538
+ },
539
+ options
540
+ );
541
+ const worknicePersonToPersonDataTransferLine = (worknicePerson) => ({
542
+ bankAccounts: worknicePerson.bankAccount1AllocationMethod ? {
543
+ bankAccount1Allocation: worknicePerson.bankAccount1Allocation ?? null,
544
+ bankAccount1AllocationMethod: worknicePerson.bankAccount1AllocationMethod,
545
+ bankAccount1Bsb: worknicePerson.bankAccount1Bsb ?? null,
546
+ bankAccount1Name: worknicePerson.bankAccount1Name ?? null,
547
+ bankAccount1Number: worknicePerson.bankAccount1Number ?? null,
548
+ bankAccount2Allocation: worknicePerson.bankAccount2Allocation ?? null,
549
+ bankAccount2AllocationMethod: worknicePerson.bankAccount2AllocationMethod ?? null,
550
+ bankAccount2Bsb: worknicePerson.bankAccount2Bsb ?? null,
551
+ bankAccount2Name: worknicePerson.bankAccount2Name ?? null,
552
+ bankAccount2Number: worknicePerson.bankAccount2Number ?? null,
553
+ bankAccount3Allocation: worknicePerson.bankAccount3Allocation ?? null,
554
+ bankAccount3AllocationMethod: worknicePerson.bankAccount3AllocationMethod ?? null,
555
+ bankAccount3Bsb: worknicePerson.bankAccount3Bsb ?? null,
556
+ bankAccount3Name: worknicePerson.bankAccount3Name ?? null,
557
+ bankAccount3Number: worknicePerson.bankAccount3Number ?? null,
558
+ bankAccount4Allocation: worknicePerson.bankAccount4Allocation ?? null,
559
+ bankAccount4AllocationMethod: worknicePerson.bankAccount4AllocationMethod ?? null,
560
+ bankAccount4Bsb: worknicePerson.bankAccount4Bsb ?? null,
561
+ bankAccount4Name: worknicePerson.bankAccount4Name ?? null,
562
+ bankAccount4Number: worknicePerson.bankAccount4Number ?? null,
563
+ bankAccount5Allocation: worknicePerson.bankAccount5Allocation ?? null,
564
+ bankAccount5AllocationMethod: worknicePerson.bankAccount5AllocationMethod ?? null,
565
+ bankAccount5Bsb: worknicePerson.bankAccount5Bsb ?? null,
566
+ bankAccount5Name: worknicePerson.bankAccount5Name ?? null,
567
+ bankAccount5Number: worknicePerson.bankAccount5Number ?? null
568
+ } : null,
569
+ emergencyContacts: null,
570
+ personalDetails: worknicePerson.givenName ? {
571
+ dateOfBirth: worknicePerson.dateOfBirth ?? null,
572
+ familyName: worknicePerson.familyName ?? null,
573
+ gender: worknicePerson.gender ?? null,
574
+ givenName: worknicePerson.givenName ?? null,
575
+ otherGivenNames: worknicePerson.otherGivenNames ?? null,
576
+ personalEmail: worknicePerson.personalEmail ?? null,
577
+ personalPhone: worknicePerson.personalPhone ?? null
578
+ } : null,
579
+ postalAddress: null,
580
+ residentialAddress: worknicePerson.residentialAddressLine1 ? {
581
+ residentialAddressCity: worknicePerson.residentialAddressCity ?? null,
582
+ // FIXME: This should not default to "Australia". See PROD-1085.
583
+ residentialAddressCountry: worknicePerson.residentialAddressCountry ?? "Australia",
584
+ residentialAddressLine1: worknicePerson.residentialAddressLine1 ?? null,
585
+ residentialAddressLine2: worknicePerson.residentialAddressLine2 ?? null,
586
+ residentialAddressPostcode: worknicePerson.residentialAddressPostcode ?? null,
587
+ residentialAddressState: worknicePerson.residentialAddressState ?? null
588
+ } : null,
589
+ // TODO: Enable syncing super funds. See PROD-2216.
590
+ superFunds: null,
591
+ // TODO: Enable syncing tax details. See PROD-2375.
592
+ taxDetails: null,
593
+ // TODO: Enable syncing tenure. See PROD-1371.
594
+ tenure: null
595
+ });
596
+ var handleTriggerIntegrationSyncWebhook_default = handleTriggerIntegrationSyncWebhook;
597
+ export {
598
+ handleTriggerIntegrationSyncWebhook_default as default
599
+ };
600
+ //# sourceMappingURL=handleTriggerIntegrationSyncWebhook.js.map