@open-mercato/core 0.6.2-develop.3461.1.605f31c2c9 → 0.6.2

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 (173) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/helpers/integration/queue-runner.js +15 -3
  3. package/dist/helpers/integration/queue-runner.js.map +2 -2
  4. package/dist/helpers/integration/queue.js +1 -1
  5. package/dist/helpers/integration/queue.js.map +2 -2
  6. package/dist/helpers/integration/salesUi.js +24 -1
  7. package/dist/helpers/integration/salesUi.js.map +2 -2
  8. package/dist/modules/auth/api/roles/acl/route.js +37 -1
  9. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  10. package/dist/modules/auth/api/roles/route.js +36 -2
  11. package/dist/modules/auth/api/roles/route.js.map +2 -2
  12. package/dist/modules/auth/api/users/acl/route.js +36 -1
  13. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  14. package/dist/modules/auth/api/users/route.js +101 -13
  15. package/dist/modules/auth/api/users/route.js.map +2 -2
  16. package/dist/modules/auth/backend/roles/[id]/edit/page.js +32 -14
  17. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  18. package/dist/modules/auth/backend/users/[id]/edit/page.js +1 -1
  19. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  20. package/dist/modules/auth/backend/users/create/page.js +1 -1
  21. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  22. package/dist/modules/auth/backend/users/roleOptions.js +1 -1
  23. package/dist/modules/auth/backend/users/roleOptions.js.map +2 -2
  24. package/dist/modules/auth/commands/roles.js +8 -0
  25. package/dist/modules/auth/commands/roles.js.map +2 -2
  26. package/dist/modules/auth/commands/users.js +3 -0
  27. package/dist/modules/auth/commands/users.js.map +2 -2
  28. package/dist/modules/auth/components/AclEditor.js +53 -26
  29. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  30. package/dist/modules/auth/frontend/login.js +35 -0
  31. package/dist/modules/auth/frontend/login.js.map +2 -2
  32. package/dist/modules/auth/lib/grantChecks.js +97 -2
  33. package/dist/modules/auth/lib/grantChecks.js.map +2 -2
  34. package/dist/modules/business_rules/lib/expression-evaluator.js +9 -7
  35. package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
  36. package/dist/modules/business_rules/lib/rule-evaluator.js +3 -3
  37. package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
  38. package/dist/modules/customers/ai-agents.js +10 -1
  39. package/dist/modules/customers/ai-agents.js.map +2 -2
  40. package/dist/modules/customers/ai-tools/settings-pack.js +55 -1
  41. package/dist/modules/customers/ai-tools/settings-pack.js.map +2 -2
  42. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +13 -5
  43. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  44. package/dist/modules/customers/lib/personCompanyLinkTable.js +4 -30
  45. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
  46. package/dist/modules/customers/migrations/Migration20260521175027.js +12 -0
  47. package/dist/modules/customers/migrations/Migration20260521175027.js.map +7 -0
  48. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +41 -12
  49. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  50. package/dist/modules/data_sync/api/options.js +2 -0
  51. package/dist/modules/data_sync/api/options.js.map +2 -2
  52. package/dist/modules/data_sync/api/run.js +77 -58
  53. package/dist/modules/data_sync/api/run.js.map +2 -2
  54. package/dist/modules/data_sync/backend/data-sync/page.js +3 -2
  55. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  56. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +8 -3
  57. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  58. package/dist/modules/integrations/backend/integrations/[id]/page.js +15 -13
  59. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  60. package/dist/modules/integrations/data/validators.js +9 -6
  61. package/dist/modules/integrations/data/validators.js.map +2 -2
  62. package/dist/modules/messages/api/route.js +2 -2
  63. package/dist/modules/messages/api/route.js.map +2 -2
  64. package/dist/modules/messages/commands/messages.js +42 -2
  65. package/dist/modules/messages/commands/messages.js.map +2 -2
  66. package/dist/modules/messages/components/MessagesInboxPageClient.js +70 -89
  67. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  68. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js +8 -6
  69. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js.map +2 -2
  70. package/dist/modules/messages/components/inboxFilters.js +133 -0
  71. package/dist/modules/messages/components/inboxFilters.js.map +7 -0
  72. package/dist/modules/messages/components/messageListLabels.js +14 -0
  73. package/dist/modules/messages/components/messageListLabels.js.map +7 -0
  74. package/dist/modules/messages/components/useMessagesInboxBulkActions.js +47 -23
  75. package/dist/modules/messages/components/useMessagesInboxBulkActions.js.map +2 -2
  76. package/dist/modules/messages/data/validators.js +8 -6
  77. package/dist/modules/messages/data/validators.js.map +2 -2
  78. package/dist/modules/progress/api/jobs/route.js +26 -16
  79. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  80. package/dist/modules/query_index/di.js +8 -6
  81. package/dist/modules/query_index/di.js.map +2 -2
  82. package/dist/modules/query_index/lib/indexer.js +12 -10
  83. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  84. package/dist/modules/query_index/subscribers/upsert_one.js +7 -1
  85. package/dist/modules/query_index/subscribers/upsert_one.js.map +2 -2
  86. package/dist/modules/sales/api/order-adjustments/route.js.map +2 -2
  87. package/dist/modules/sales/api/quote-adjustments/route.js.map +2 -2
  88. package/dist/modules/sales/commands/documents.js +104 -0
  89. package/dist/modules/sales/commands/documents.js.map +2 -2
  90. package/dist/modules/sales/data/validators.js +20 -1
  91. package/dist/modules/sales/data/validators.js.map +2 -2
  92. package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
  93. package/dist/modules/sync_excel/api/import/route.js +126 -116
  94. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  95. package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
  96. package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
  97. package/dist/modules/translations/components/TranslationManager.js +9 -4
  98. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  99. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  100. package/dist/modules/workflows/lib/event-trigger-service.js +23 -11
  101. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  102. package/jest.config.cjs +4 -1
  103. package/package.json +15 -16
  104. package/src/helpers/integration/queue-runner.ts +21 -2
  105. package/src/helpers/integration/queue.ts +1 -1
  106. package/src/helpers/integration/salesUi.ts +26 -1
  107. package/src/modules/auth/api/roles/acl/route.ts +39 -1
  108. package/src/modules/auth/api/roles/route.ts +38 -2
  109. package/src/modules/auth/api/users/acl/route.ts +41 -1
  110. package/src/modules/auth/api/users/route.ts +105 -12
  111. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +35 -13
  112. package/src/modules/auth/backend/users/[id]/edit/page.tsx +1 -1
  113. package/src/modules/auth/backend/users/create/page.tsx +1 -1
  114. package/src/modules/auth/backend/users/roleOptions.ts +2 -1
  115. package/src/modules/auth/commands/roles.ts +8 -0
  116. package/src/modules/auth/commands/users.ts +3 -0
  117. package/src/modules/auth/components/AclEditor.tsx +50 -24
  118. package/src/modules/auth/frontend/login.tsx +40 -0
  119. package/src/modules/auth/lib/grantChecks.ts +116 -2
  120. package/src/modules/business_rules/lib/expression-evaluator.ts +9 -13
  121. package/src/modules/business_rules/lib/rule-evaluator.ts +3 -3
  122. package/src/modules/customers/ai-agents.ts +10 -1
  123. package/src/modules/customers/ai-tools/settings-pack.ts +62 -1
  124. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +18 -7
  125. package/src/modules/customers/lib/personCompanyLinkTable.ts +33 -41
  126. package/src/modules/customers/migrations/Migration20260521175027.ts +39 -0
  127. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +38 -12
  128. package/src/modules/data_sync/api/options.ts +2 -0
  129. package/src/modules/data_sync/api/run.ts +80 -61
  130. package/src/modules/data_sync/backend/data-sync/page.tsx +10 -0
  131. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +17 -3
  132. package/src/modules/data_sync/i18n/de.json +3 -0
  133. package/src/modules/data_sync/i18n/en.json +3 -0
  134. package/src/modules/data_sync/i18n/es.json +3 -0
  135. package/src/modules/data_sync/i18n/pl.json +3 -0
  136. package/src/modules/data_sync/lib/adapter.ts +9 -0
  137. package/src/modules/integrations/backend/integrations/[id]/page.tsx +15 -13
  138. package/src/modules/integrations/data/validators.ts +5 -4
  139. package/src/modules/messages/api/route.ts +2 -2
  140. package/src/modules/messages/commands/messages.ts +54 -2
  141. package/src/modules/messages/components/MessagesInboxPageClient.tsx +80 -92
  142. package/src/modules/messages/components/defaults/DefaultMessageListItem.tsx +9 -5
  143. package/src/modules/messages/components/inboxFilters.ts +162 -0
  144. package/src/modules/messages/components/messageListLabels.ts +29 -0
  145. package/src/modules/messages/components/useMessagesInboxBulkActions.ts +58 -26
  146. package/src/modules/messages/data/validators.ts +7 -5
  147. package/src/modules/messages/i18n/de.json +7 -4
  148. package/src/modules/messages/i18n/en.json +7 -4
  149. package/src/modules/messages/i18n/es.json +7 -4
  150. package/src/modules/messages/i18n/pl.json +7 -4
  151. package/src/modules/progress/api/jobs/route.ts +30 -20
  152. package/src/modules/query_index/di.ts +9 -7
  153. package/src/modules/query_index/lib/indexer.ts +13 -11
  154. package/src/modules/query_index/subscribers/upsert_one.ts +9 -1
  155. package/src/modules/sales/api/order-adjustments/route.ts +2 -1
  156. package/src/modules/sales/api/quote-adjustments/route.ts +2 -1
  157. package/src/modules/sales/commands/documents.ts +116 -0
  158. package/src/modules/sales/data/validators.ts +38 -0
  159. package/src/modules/sales/i18n/de.json +2 -0
  160. package/src/modules/sales/i18n/en.json +2 -0
  161. package/src/modules/sales/i18n/es.json +2 -0
  162. package/src/modules/sales/i18n/pl.json +2 -0
  163. package/src/modules/sales/lib/makeSalesLineRoute.ts +2 -1
  164. package/src/modules/staff/i18n/de.json +1 -0
  165. package/src/modules/staff/i18n/en.json +1 -0
  166. package/src/modules/staff/i18n/es.json +1 -0
  167. package/src/modules/staff/i18n/pl.json +1 -0
  168. package/src/modules/sync_excel/api/import/route.ts +141 -131
  169. package/src/modules/sync_excel/lib/adapters/customers.ts +1 -0
  170. package/src/modules/translations/components/TranslationManager.tsx +9 -4
  171. package/src/modules/workflows/lib/activity-executor.ts +4 -3
  172. package/src/modules/workflows/lib/event-trigger-service.ts +24 -11
  173. package/tsconfig.json +1 -0
@@ -37,124 +37,134 @@ const openApi = {
37
37
  }
38
38
  };
39
39
  async function POST(request) {
40
- const auth = await getAuthFromRequest(request);
41
- if (!auth?.tenantId) {
42
- return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
43
- }
44
- const payload = await readJsonSafe(request);
45
- const parsedPayload = syncExcelImportRequestSchema.safeParse(payload);
46
- if (!parsedPayload.success) {
47
- return NextResponse.json({ error: "Invalid import payload." }, { status: 422 });
48
- }
49
- const container = await createRequestContainer();
50
- const em = container.resolve("em");
51
- const syncRunService = container.resolve("dataSyncRunService");
52
- const progressService = container.resolve("progressService");
53
- const credentialsService = container.resolve("integrationCredentialsService");
54
- const integrationStateService = container.resolve("integrationStateService");
55
- const scopeResult = await resolveSyncExcelConcreteScope({ auth, container, request });
56
- if (!scopeResult.ok) {
57
- return NextResponse.json({ error: scopeResult.error }, { status: scopeResult.status });
58
- }
59
- const { scope } = scopeResult;
60
- const upload = await findOneWithDecryption(
61
- em,
62
- SyncExcelUpload,
63
- {
64
- id: parsedPayload.data.uploadId,
65
- organizationId: scope.organizationId,
66
- tenantId: scope.tenantId
67
- },
68
- void 0,
69
- scope
70
- );
71
- if (!upload) {
72
- return NextResponse.json({ error: "Upload preview not found." }, { status: 404 });
73
- }
74
- const attachment = await findOneWithDecryption(
75
- em,
76
- Attachment,
77
- {
78
- id: upload.attachmentId,
79
- organizationId: scope.organizationId,
80
- tenantId: scope.tenantId
81
- },
82
- void 0,
83
- scope
84
- );
85
- if (!attachment) {
86
- return NextResponse.json({ error: "Upload attachment not found." }, { status: 404 });
87
- }
88
- if (upload.entityType !== parsedPayload.data.entityType) {
89
- return NextResponse.json({ error: "Upload entity type does not match requested import target." }, { status: 422 });
90
- }
91
- if (parsedPayload.data.mapping.entityType !== parsedPayload.data.entityType) {
92
- return NextResponse.json({ error: "Mapping entity type does not match requested import target." }, { status: 422 });
93
- }
94
- const overlap = await syncRunService.findRunningOverlap("sync_excel", parsedPayload.data.entityType, "import", scope);
95
- if (overlap) {
96
- return NextResponse.json({ error: "A sync_excel import is already in progress for this entity type." }, { status: 409 });
97
- }
98
- const existingMapping = await findOneWithDecryption(
99
- em,
100
- SyncMapping,
101
- {
102
- integrationId: "sync_excel",
103
- entityType: parsedPayload.data.entityType,
104
- organizationId: scope.organizationId,
105
- tenantId: scope.tenantId
106
- },
107
- void 0,
108
- scope
109
- );
110
- if (existingMapping) {
111
- existingMapping.mapping = parsedPayload.data.mapping;
112
- } else {
113
- em.persist(em.create(SyncMapping, {
114
- integrationId: "sync_excel",
115
- entityType: parsedPayload.data.entityType,
116
- mapping: parsedPayload.data.mapping,
117
- organizationId: scope.organizationId,
118
- tenantId: scope.tenantId
119
- }));
120
- }
121
- await credentialsService.save("sync_excel", {}, scope);
122
- await integrationStateService.upsert("sync_excel", { isEnabled: true }, scope);
123
- await em.flush();
124
- const { run, progressJob } = await startDataSyncRun({
125
- syncRunService,
126
- progressService,
127
- scope: {
128
- ...scope,
129
- userId: auth.sub
130
- },
131
- input: {
132
- integrationId: "sync_excel",
133
- entityType: parsedPayload.data.entityType,
134
- direction: "import",
135
- cursor: createCursor(upload.id, 0),
136
- triggeredBy: auth.sub,
137
- batchSize: parsedPayload.data.batchSize ?? 100,
138
- progressJob: {
139
- jobType: "sync_excel:import",
140
- name: `CSV import \u2014 ${parsedPayload.data.entityType}`,
141
- description: upload.filename,
142
- meta: {
143
- integrationId: "sync_excel",
144
- uploadId: upload.id,
145
- hiddenFromTopBar: false
40
+ try {
41
+ const auth = await getAuthFromRequest(request);
42
+ if (!auth?.tenantId) {
43
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
44
+ }
45
+ const payload = await readJsonSafe(request);
46
+ const parsedPayload = syncExcelImportRequestSchema.safeParse(payload);
47
+ if (!parsedPayload.success) {
48
+ return NextResponse.json({ error: "Invalid import payload." }, { status: 422 });
49
+ }
50
+ const container = await createRequestContainer();
51
+ const em = container.resolve("em");
52
+ const syncRunService = container.resolve("dataSyncRunService");
53
+ const progressService = container.resolve("progressService");
54
+ const credentialsService = container.resolve("integrationCredentialsService");
55
+ const integrationStateService = container.resolve("integrationStateService");
56
+ const scopeResult = await resolveSyncExcelConcreteScope({ auth, container, request });
57
+ if (!scopeResult.ok) {
58
+ return NextResponse.json({ error: scopeResult.error }, { status: scopeResult.status });
59
+ }
60
+ const { scope } = scopeResult;
61
+ const upload = await findOneWithDecryption(
62
+ em,
63
+ SyncExcelUpload,
64
+ {
65
+ id: parsedPayload.data.uploadId,
66
+ organizationId: scope.organizationId,
67
+ tenantId: scope.tenantId
68
+ },
69
+ void 0,
70
+ scope
71
+ );
72
+ if (!upload) {
73
+ return NextResponse.json({ error: "Upload preview not found." }, { status: 404 });
74
+ }
75
+ const attachment = await findOneWithDecryption(
76
+ em,
77
+ Attachment,
78
+ {
79
+ id: upload.attachmentId,
80
+ organizationId: scope.organizationId,
81
+ tenantId: scope.tenantId
82
+ },
83
+ void 0,
84
+ scope
85
+ );
86
+ if (!attachment) {
87
+ return NextResponse.json({ error: "Upload attachment not found." }, { status: 404 });
88
+ }
89
+ if (upload.entityType !== parsedPayload.data.entityType) {
90
+ return NextResponse.json({ error: "Upload entity type does not match requested import target." }, { status: 422 });
91
+ }
92
+ if (parsedPayload.data.mapping.entityType !== parsedPayload.data.entityType) {
93
+ return NextResponse.json({ error: "Mapping entity type does not match requested import target." }, { status: 422 });
94
+ }
95
+ const overlap = await syncRunService.findRunningOverlap("sync_excel", parsedPayload.data.entityType, "import", scope);
96
+ if (overlap) {
97
+ return NextResponse.json({ error: "A sync_excel import is already in progress for this entity type." }, { status: 409 });
98
+ }
99
+ const existingMapping = await findOneWithDecryption(
100
+ em,
101
+ SyncMapping,
102
+ {
103
+ integrationId: "sync_excel",
104
+ entityType: parsedPayload.data.entityType,
105
+ organizationId: scope.organizationId,
106
+ tenantId: scope.tenantId
107
+ },
108
+ void 0,
109
+ scope
110
+ );
111
+ if (existingMapping) {
112
+ existingMapping.mapping = parsedPayload.data.mapping;
113
+ } else {
114
+ em.persist(em.create(SyncMapping, {
115
+ integrationId: "sync_excel",
116
+ entityType: parsedPayload.data.entityType,
117
+ mapping: parsedPayload.data.mapping,
118
+ organizationId: scope.organizationId,
119
+ tenantId: scope.tenantId
120
+ }));
121
+ }
122
+ await credentialsService.save("sync_excel", {}, scope);
123
+ await integrationStateService.upsert("sync_excel", { isEnabled: true }, scope);
124
+ await em.flush();
125
+ const { run, progressJob } = await startDataSyncRun({
126
+ syncRunService,
127
+ progressService,
128
+ scope: {
129
+ ...scope,
130
+ userId: auth.sub
131
+ },
132
+ input: {
133
+ integrationId: "sync_excel",
134
+ entityType: parsedPayload.data.entityType,
135
+ direction: "import",
136
+ cursor: createCursor(upload.id, 0),
137
+ triggeredBy: auth.sub,
138
+ batchSize: parsedPayload.data.batchSize ?? 100,
139
+ progressJob: {
140
+ jobType: "sync_excel:import",
141
+ name: `CSV import \u2014 ${parsedPayload.data.entityType}`,
142
+ description: upload.filename,
143
+ meta: {
144
+ integrationId: "sync_excel",
145
+ uploadId: upload.id,
146
+ hiddenFromTopBar: false
147
+ }
146
148
  }
147
149
  }
148
- }
149
- });
150
- upload.syncRunId = run.id;
151
- upload.status = "importing";
152
- await em.flush();
153
- return NextResponse.json(syncExcelImportResponseSchema.parse({
154
- runId: run.id,
155
- progressJobId: progressJob?.id ?? null,
156
- status: run.status
157
- }), { status: 201 });
150
+ });
151
+ upload.syncRunId = run.id;
152
+ upload.status = "importing";
153
+ await em.flush();
154
+ return NextResponse.json(syncExcelImportResponseSchema.parse({
155
+ runId: run.id,
156
+ progressJobId: progressJob?.id ?? null,
157
+ status: run.status
158
+ }), { status: 201 });
159
+ } catch (error) {
160
+ const message = error instanceof Error ? error.message : String(error);
161
+ const stack = error instanceof Error ? error.stack : void 0;
162
+ console.error("[sync_excel.import] unhandled error", { message, stack });
163
+ return NextResponse.json(
164
+ { error: "Failed to start sync_excel import.", message, stack },
165
+ { status: 500 }
166
+ );
167
+ }
158
168
  }
159
169
  export {
160
170
  POST,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sync_excel/api/import/route.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { z } from 'zod'\nimport type { ProgressService } from '@open-mercato/core/modules/progress/lib/progressService'\nimport type { SyncRunService } from '@open-mercato/core/modules/data_sync/lib/sync-run-service'\nimport { startDataSyncRun } from '@open-mercato/core/modules/data_sync/lib/start-run'\nimport { SyncMapping } from '@open-mercato/core/modules/data_sync/data/entities'\nimport type { CredentialsService } from '@open-mercato/core/modules/integrations/lib/credentials-service'\nimport type { IntegrationStateService } from '@open-mercato/core/modules/integrations/lib/state-service'\nimport { SyncExcelUpload } from '../../data/entities'\nimport { Attachment } from '../../../attachments/data/entities'\nimport { createCursor } from '../../lib/adapters/customers'\nimport {\n syncExcelImportRequestSchema,\n syncExcelImportResponseSchema,\n} from '../../data/validators'\nimport { resolveSyncExcelConcreteScope } from '../../lib/scope'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['sync_excel.run'] },\n}\n\nconst errorSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi = {\n tags: ['SyncExcel'],\n summary: 'Start a CSV import run for a stored sync_excel upload',\n methods: {\n POST: {\n summary: 'Start CSV import',\n responses: [\n { status: 201, description: 'Import run started', schema: syncExcelImportResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorSchema },\n { status: 404, description: 'Upload not found', schema: errorSchema },\n { status: 409, description: 'Import overlap detected', schema: errorSchema },\n { status: 422, description: 'Invalid import payload', schema: errorSchema },\n ],\n },\n },\n}\n\nexport async function POST(request: Request) {\n const auth = await getAuthFromRequest(request)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const payload = await readJsonSafe(request)\n const parsedPayload = syncExcelImportRequestSchema.safeParse(payload)\n if (!parsedPayload.success) {\n return NextResponse.json({ error: 'Invalid import payload.' }, { status: 422 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const syncRunService = container.resolve('dataSyncRunService') as SyncRunService\n const progressService = container.resolve('progressService') as ProgressService\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const integrationStateService = container.resolve('integrationStateService') as IntegrationStateService\n const scopeResult = await resolveSyncExcelConcreteScope({ auth, container, request })\n if (!scopeResult.ok) {\n return NextResponse.json({ error: scopeResult.error }, { status: scopeResult.status })\n }\n const { scope } = scopeResult\n\n const upload = await findOneWithDecryption(\n em,\n SyncExcelUpload,\n {\n id: parsedPayload.data.uploadId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (!upload) {\n return NextResponse.json({ error: 'Upload preview not found.' }, { status: 404 })\n }\n\n const attachment = await findOneWithDecryption(\n em,\n Attachment,\n {\n id: upload.attachmentId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (!attachment) {\n return NextResponse.json({ error: 'Upload attachment not found.' }, { status: 404 })\n }\n\n if (upload.entityType !== parsedPayload.data.entityType) {\n return NextResponse.json({ error: 'Upload entity type does not match requested import target.' }, { status: 422 })\n }\n\n if (parsedPayload.data.mapping.entityType !== parsedPayload.data.entityType) {\n return NextResponse.json({ error: 'Mapping entity type does not match requested import target.' }, { status: 422 })\n }\n\n const overlap = await syncRunService.findRunningOverlap('sync_excel', parsedPayload.data.entityType, 'import', scope)\n if (overlap) {\n return NextResponse.json({ error: 'A sync_excel import is already in progress for this entity type.' }, { status: 409 })\n }\n\n const existingMapping = await findOneWithDecryption(\n em,\n SyncMapping,\n {\n integrationId: 'sync_excel',\n entityType: parsedPayload.data.entityType,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (existingMapping) {\n existingMapping.mapping = parsedPayload.data.mapping\n } else {\n em.persist(em.create(SyncMapping, {\n integrationId: 'sync_excel',\n entityType: parsedPayload.data.entityType,\n mapping: parsedPayload.data.mapping,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }))\n }\n\n await credentialsService.save('sync_excel', {}, scope)\n await integrationStateService.upsert('sync_excel', { isEnabled: true }, scope)\n await em.flush()\n\n const { run, progressJob } = await startDataSyncRun({\n syncRunService,\n progressService,\n scope: {\n ...scope,\n userId: auth.sub,\n },\n input: {\n integrationId: 'sync_excel',\n entityType: parsedPayload.data.entityType,\n direction: 'import',\n cursor: createCursor(upload.id, 0),\n triggeredBy: auth.sub,\n batchSize: parsedPayload.data.batchSize ?? 100,\n progressJob: {\n jobType: 'sync_excel:import',\n name: `CSV import \u2014 ${parsedPayload.data.entityType}`,\n description: upload.filename,\n meta: {\n integrationId: 'sync_excel',\n uploadId: upload.id,\n hiddenFromTopBar: false,\n },\n },\n },\n })\n\n upload.syncRunId = run.id\n upload.status = 'importing'\n await em.flush()\n\n return NextResponse.json(syncExcelImportResponseSchema.parse({\n runId: run.id,\n progressJobId: progressJob?.id ?? null,\n status: run.status,\n }), { status: 201 })\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { z } from 'zod'\nimport type { ProgressService } from '@open-mercato/core/modules/progress/lib/progressService'\nimport type { SyncRunService } from '@open-mercato/core/modules/data_sync/lib/sync-run-service'\nimport { startDataSyncRun } from '@open-mercato/core/modules/data_sync/lib/start-run'\nimport { SyncMapping } from '@open-mercato/core/modules/data_sync/data/entities'\nimport type { CredentialsService } from '@open-mercato/core/modules/integrations/lib/credentials-service'\nimport type { IntegrationStateService } from '@open-mercato/core/modules/integrations/lib/state-service'\nimport { SyncExcelUpload } from '../../data/entities'\nimport { Attachment } from '../../../attachments/data/entities'\nimport { createCursor } from '../../lib/adapters/customers'\nimport {\n syncExcelImportRequestSchema,\n syncExcelImportResponseSchema,\n} from '../../data/validators'\nimport { resolveSyncExcelConcreteScope } from '../../lib/scope'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['sync_excel.run'] },\n}\n\nconst errorSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi = {\n tags: ['SyncExcel'],\n summary: 'Start a CSV import run for a stored sync_excel upload',\n methods: {\n POST: {\n summary: 'Start CSV import',\n responses: [\n { status: 201, description: 'Import run started', schema: syncExcelImportResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorSchema },\n { status: 404, description: 'Upload not found', schema: errorSchema },\n { status: 409, description: 'Import overlap detected', schema: errorSchema },\n { status: 422, description: 'Invalid import payload', schema: errorSchema },\n ],\n },\n },\n}\n\nexport async function POST(request: Request) {\n try {\n const auth = await getAuthFromRequest(request)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const payload = await readJsonSafe(request)\n const parsedPayload = syncExcelImportRequestSchema.safeParse(payload)\n if (!parsedPayload.success) {\n return NextResponse.json({ error: 'Invalid import payload.' }, { status: 422 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const syncRunService = container.resolve('dataSyncRunService') as SyncRunService\n const progressService = container.resolve('progressService') as ProgressService\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const integrationStateService = container.resolve('integrationStateService') as IntegrationStateService\n const scopeResult = await resolveSyncExcelConcreteScope({ auth, container, request })\n if (!scopeResult.ok) {\n return NextResponse.json({ error: scopeResult.error }, { status: scopeResult.status })\n }\n const { scope } = scopeResult\n\n const upload = await findOneWithDecryption(\n em,\n SyncExcelUpload,\n {\n id: parsedPayload.data.uploadId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (!upload) {\n return NextResponse.json({ error: 'Upload preview not found.' }, { status: 404 })\n }\n\n const attachment = await findOneWithDecryption(\n em,\n Attachment,\n {\n id: upload.attachmentId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (!attachment) {\n return NextResponse.json({ error: 'Upload attachment not found.' }, { status: 404 })\n }\n\n if (upload.entityType !== parsedPayload.data.entityType) {\n return NextResponse.json({ error: 'Upload entity type does not match requested import target.' }, { status: 422 })\n }\n\n if (parsedPayload.data.mapping.entityType !== parsedPayload.data.entityType) {\n return NextResponse.json({ error: 'Mapping entity type does not match requested import target.' }, { status: 422 })\n }\n\n const overlap = await syncRunService.findRunningOverlap('sync_excel', parsedPayload.data.entityType, 'import', scope)\n if (overlap) {\n return NextResponse.json({ error: 'A sync_excel import is already in progress for this entity type.' }, { status: 409 })\n }\n\n const existingMapping = await findOneWithDecryption(\n em,\n SyncMapping,\n {\n integrationId: 'sync_excel',\n entityType: parsedPayload.data.entityType,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (existingMapping) {\n existingMapping.mapping = parsedPayload.data.mapping\n } else {\n em.persist(em.create(SyncMapping, {\n integrationId: 'sync_excel',\n entityType: parsedPayload.data.entityType,\n mapping: parsedPayload.data.mapping,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }))\n }\n\n await credentialsService.save('sync_excel', {}, scope)\n await integrationStateService.upsert('sync_excel', { isEnabled: true }, scope)\n await em.flush()\n\n const { run, progressJob } = await startDataSyncRun({\n syncRunService,\n progressService,\n scope: {\n ...scope,\n userId: auth.sub,\n },\n input: {\n integrationId: 'sync_excel',\n entityType: parsedPayload.data.entityType,\n direction: 'import',\n cursor: createCursor(upload.id, 0),\n triggeredBy: auth.sub,\n batchSize: parsedPayload.data.batchSize ?? 100,\n progressJob: {\n jobType: 'sync_excel:import',\n name: `CSV import \u2014 ${parsedPayload.data.entityType}`,\n description: upload.filename,\n meta: {\n integrationId: 'sync_excel',\n uploadId: upload.id,\n hiddenFromTopBar: false,\n },\n },\n },\n })\n\n upload.syncRunId = run.id\n upload.status = 'importing'\n await em.flush()\n\n return NextResponse.json(syncExcelImportResponseSchema.parse({\n runId: run.id,\n progressJobId: progressJob?.id ?? null,\n status: run.status,\n }), { status: 201 })\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n const stack = error instanceof Error ? error.stack : undefined\n console.error('[sync_excel.import] unhandled error', { message, stack })\n return NextResponse.json(\n { error: 'Failed to start sync_excel import.', message, stack },\n { status: 500 },\n )\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -753,6 +753,7 @@ async function processRow(params) {
753
753
  }
754
754
  const syncExcelCustomersAdapter = {
755
755
  providerKey: "excel",
756
+ runMode: "provider",
756
757
  operationalTelemetry: true,
757
758
  direction: "import",
758
759
  supportedEntities: ["customers.person"],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sync_excel/lib/adapters/customers.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { extractPhoneDigits, validatePhoneNumber } from '@open-mercato/shared/lib/phone'\nimport type {\n DataMapping,\n DataSyncAdapter,\n FieldMapping,\n ImportBatch,\n ImportItem,\n TenantScope,\n} from '../../../data_sync/lib/adapter'\nimport type { ExternalIdMappingService } from '../../../data_sync/lib/id-mapping'\nimport { SyncMapping } from '../../../data_sync/data/entities'\nimport { CustomerAddress, CustomerEntity } from '../../../customers/data/entities'\nimport { Attachment } from '../../../attachments/data/entities'\nimport { CustomFieldDef } from '../../../entities/data/entities'\nimport { SyncExcelUpload } from '../../data/entities'\nimport { parseCsvDocument, type CsvPreviewRow } from '../parser'\nimport { readSyncExcelUploadBuffer } from '../upload-storage'\nimport { E } from '#generated/entities.ids.generated'\n\ntype SyncExcelCursor = {\n uploadId: string\n offset: number\n}\n\ntype Container = Awaited<ReturnType<typeof createRequestContainer>>\n\nconst CUSTOMER_IMPORT_COVERAGE_ENTITY_TYPES = [\n E.customers.customer_entity,\n E.customers.customer_person_profile,\n E.customers.customer_address,\n]\n\ntype PersonFieldValues = {\n externalId?: string | null\n firstName?: string | null\n lastName?: string | null\n displayName?: string | null\n primaryEmail?: string | null\n primaryPhone?: string | null\n jobTitle?: string | null\n status?: string | null\n source?: string | null\n description?: string | null\n}\n\ntype AddressFieldValues = {\n name?: string | null\n purpose?: string | null\n companyName?: string | null\n addressLine1?: string | null\n addressLine2?: string | null\n buildingNumber?: string | null\n flatNumber?: string | null\n city?: string | null\n region?: string | null\n postalCode?: string | null\n country?: string | null\n latitude?: number | null\n longitude?: number | null\n}\n\ntype PersonRowValues = {\n values: PersonFieldValues\n customFields: Record<string, unknown>\n addressValues: AddressFieldValues\n}\n\ntype ImportCustomFieldDefinition = {\n key: string\n kind: string\n entityId: string\n organizationId?: string | null\n tenantId?: string | null\n updatedAt?: Date | string | null\n}\n\ntype EmailDedupeIndex = Map<string, string>\n\ntype BuiltPersonPayload = {\n values: PersonFieldValues\n customFields: Record<string, unknown>\n addressValues: AddressFieldValues\n createInput: {\n organizationId: string\n tenantId: string\n firstName: string\n lastName: string\n displayName: string\n primaryEmail?: string\n primaryPhone?: string\n jobTitle?: string\n status?: string\n source?: string\n description?: string\n customFields?: Record<string, unknown>\n } | null\n updateInput: {\n organizationId: string\n tenantId: string\n primaryEmail?: string\n primaryPhone?: string\n jobTitle?: string\n status?: string\n source?: string\n description?: string\n firstName?: string\n lastName?: string\n displayName?: string\n customFields?: Record<string, unknown>\n }\n sourceIdentifier: string | null\n}\n\nfunction normalizeOptionalString(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction normalizeEmail(value: unknown): string | null {\n const normalized = normalizeOptionalString(value)\n return normalized ? normalized.toLowerCase() : null\n}\n\nconst COUNTRY_DIAL_CODES: Record<string, string> = {\n canada: '1',\n england: '44',\n greatbritain: '44',\n poland: '48',\n scotland: '44',\n uk: '44',\n unitedkingdom: '44',\n unitedstates: '1',\n unitedstatesofamerica: '1',\n usa: '1',\n wales: '44',\n}\n\nfunction normalizeCountryKey(value: unknown): string | null {\n const normalized = normalizeOptionalString(value)\n if (!normalized) return null\n return normalized.toLowerCase().replace(/[^a-z]/g, '')\n}\n\nfunction resolveCountryDialCode(row: CsvPreviewRow): string | null {\n const countryCandidates = [\n row.Country,\n row.country,\n row['Country/Region'],\n row['country/region'],\n ]\n\n for (const candidate of countryCandidates) {\n const countryKey = normalizeCountryKey(candidate)\n if (!countryKey) continue\n const dialCode = COUNTRY_DIAL_CODES[countryKey]\n if (dialCode) return dialCode\n }\n\n return null\n}\n\nfunction stripPhoneExtension(value: string): string {\n return value\n .replace(/\\s*(ext\\.?|extension|x)\\s*\\d+$/i, '')\n .replace(/^\\+\\s+/, '+')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction normalizeImportedPhone(value: unknown, row: CsvPreviewRow): string | null {\n const normalized = normalizeOptionalString(value)\n if (!normalized) return null\n\n const directValidation = validatePhoneNumber(normalized)\n if (directValidation.valid) {\n return directValidation.normalized\n }\n\n const sanitized = stripPhoneExtension(normalized)\n const sanitizedValidation = validatePhoneNumber(sanitized)\n if (sanitizedValidation.valid) {\n return sanitizedValidation.normalized\n }\n\n const digits = extractPhoneDigits(sanitized)\n if (!digits) return null\n\n if (digits.length >= 9 && digits.length <= 15 && sanitized.startsWith('00')) {\n const internationalCandidate = `+${digits.slice(2)}`\n const internationalValidation = validatePhoneNumber(internationalCandidate)\n if (internationalValidation.valid) {\n return internationalValidation.normalized\n }\n }\n\n const dialCode = resolveCountryDialCode(row)\n if (!dialCode) return null\n\n let nationalDigits = digits\n if (nationalDigits.startsWith(dialCode)) {\n nationalDigits = nationalDigits.slice(dialCode.length)\n } else {\n nationalDigits = nationalDigits.replace(/^0+/, '')\n }\n\n if (!nationalDigits) return null\n\n const localizedCandidate = `+${dialCode}${nationalDigits}`\n const localizedValidation = validatePhoneNumber(localizedCandidate)\n return localizedValidation.valid ? localizedValidation.normalized : null\n}\n\nfunction normalizeOptionalNumber(value: unknown): number | null {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? value : null\n }\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n if (trimmed.length === 0) return null\n const parsed = Number(trimmed)\n return Number.isFinite(parsed) ? parsed : null\n}\n\nfunction normalizeCustomFieldDate(value: string): string | null {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime())) return null\n return parsed.toISOString().slice(0, 10)\n}\n\nfunction normalizeCustomFieldBoolean(value: string): boolean | null {\n const normalized = value.trim().toLowerCase()\n if (['true', '1', 'yes', 'y', 't', 'tak'].includes(normalized)) return true\n if (['false', '0', 'no', 'n', 'f', 'nie'].includes(normalized)) return false\n return null\n}\n\nfunction coerceCustomFieldValue(\n key: string,\n value: unknown,\n definitions: Map<string, ImportCustomFieldDefinition>,\n): { ok: true; value: unknown } | { ok: false; error: string } {\n if (typeof value === 'string' && value.trim().length === 0) {\n return { ok: true, value: null }\n }\n\n const definition = definitions.get(key)\n if (!definition) {\n return { ok: true, value: typeof value === 'string' ? value.trim() : value }\n }\n\n if (value === null || value === undefined) {\n return { ok: true, value: null }\n }\n\n const text = typeof value === 'string' ? value.trim() : String(value)\n if (text.length === 0) {\n return { ok: true, value: null }\n }\n\n const kind = definition.kind.toLowerCase()\n if (kind === 'boolean') {\n const booleanValue = normalizeCustomFieldBoolean(text)\n if (booleanValue === null) {\n return { ok: false, error: `Custom field \"${key}\" expects a boolean value.` }\n }\n return { ok: true, value: booleanValue }\n }\n\n if (kind === 'integer') {\n const numberValue = Number(text)\n if (!Number.isInteger(numberValue)) {\n return { ok: false, error: `Custom field \"${key}\" expects an integer value.` }\n }\n return { ok: true, value: numberValue }\n }\n\n if (kind === 'float' || kind === 'currency' || kind === 'number') {\n const numberValue = Number(text)\n if (!Number.isFinite(numberValue)) {\n return { ok: false, error: `Custom field \"${key}\" expects a number value.` }\n }\n return { ok: true, value: numberValue }\n }\n\n if (kind === 'date' || kind === 'datetime') {\n const dateValue = normalizeCustomFieldDate(text)\n if (!dateValue) {\n return { ok: false, error: `Custom field \"${key}\" expects a date value.` }\n }\n return { ok: true, value: dateValue }\n }\n\n return { ok: true, value: text }\n}\n\nfunction coerceCustomFields(\n values: Record<string, unknown>,\n definitions: Map<string, ImportCustomFieldDefinition>,\n): { ok: true; values: Record<string, unknown> } | { ok: false; error: string } {\n const coerced: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(values)) {\n const result = coerceCustomFieldValue(key, value, definitions)\n if (!result.ok) return result\n coerced[key] = result.value\n }\n return { ok: true, values: coerced }\n}\n\nfunction customFieldDefinitionScopeScore(definition: ImportCustomFieldDefinition): number {\n return (definition.tenantId ? 2 : 0) + (definition.organizationId ? 1 : 0)\n}\n\nfunction customFieldDefinitionUpdatedAt(definition: ImportCustomFieldDefinition): number {\n if (!definition.updatedAt) return 0\n const value = definition.updatedAt instanceof Date\n ? definition.updatedAt.getTime()\n : new Date(definition.updatedAt).getTime()\n return Number.isFinite(value) ? value : 0\n}\n\nfunction preferCustomFieldDefinition(\n current: ImportCustomFieldDefinition | undefined,\n candidate: ImportCustomFieldDefinition,\n): boolean {\n if (!current) return true\n const candidateScore = customFieldDefinitionScopeScore(candidate)\n const currentScore = customFieldDefinitionScopeScore(current)\n if (candidateScore !== currentScore) return candidateScore > currentScore\n return customFieldDefinitionUpdatedAt(candidate) >= customFieldDefinitionUpdatedAt(current)\n}\n\nasync function loadImportCustomFieldDefinitions(\n em: EntityManager,\n scope: TenantScope,\n): Promise<Map<string, ImportCustomFieldDefinition>> {\n const definitions = await findWithDecryption(\n em,\n CustomFieldDef,\n {\n entityId: { $in: [E.customers.customer_entity, E.customers.customer_person_profile] as string[] },\n deletedAt: null,\n isActive: true,\n $and: [\n { $or: [{ tenantId: scope.tenantId }, { tenantId: null }] },\n { $or: [{ organizationId: scope.organizationId }, { organizationId: null }] },\n ],\n },\n undefined,\n scope,\n )\n\n const byKey = new Map<string, ImportCustomFieldDefinition>()\n for (const definition of definitions) {\n const candidate: ImportCustomFieldDefinition = {\n key: definition.key,\n kind: definition.kind,\n entityId: definition.entityId,\n organizationId: definition.organizationId ?? null,\n tenantId: definition.tenantId ?? null,\n updatedAt: definition.updatedAt ?? null,\n }\n if (preferCustomFieldDefinition(byKey.get(candidate.key), candidate)) {\n byKey.set(candidate.key, candidate)\n }\n }\n return byKey\n}\n\nfunction buildCommandContext(container: Container, scope: TenantScope): CommandRuntimeContext {\n return {\n container,\n auth: null,\n organizationScope: {\n selectedId: scope.organizationId,\n filterIds: [scope.organizationId],\n allowedIds: [scope.organizationId],\n tenantId: scope.tenantId,\n },\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n}\n\nexport function createCursor(uploadId: string, offset: number): string {\n return JSON.stringify({\n uploadId,\n offset,\n })\n}\n\nexport function parseCursor(value: string | null | undefined): SyncExcelCursor | null {\n if (!value) return null\n try {\n const parsed = JSON.parse(value) as Partial<SyncExcelCursor> | null\n if (!parsed || typeof parsed !== 'object') return null\n if (typeof parsed.uploadId !== 'string' || parsed.uploadId.trim().length === 0) return null\n if (typeof parsed.offset !== 'number' || !Number.isFinite(parsed.offset) || parsed.offset < 0) return null\n return {\n uploadId: parsed.uploadId,\n offset: parsed.offset,\n }\n } catch {\n return null\n }\n}\n\nfunction mapRowValues(row: CsvPreviewRow, fields: FieldMapping[]): PersonRowValues {\n const values: PersonFieldValues = {}\n const customFields: Record<string, unknown> = {}\n const addressValues: AddressFieldValues = {}\n\n for (const field of fields) {\n if (field.mappingKind === 'ignore') continue\n const rawValue = row[field.externalField]\n if (rawValue === undefined || rawValue === null) continue\n if (field.mappingKind === 'custom_field' || field.localField.startsWith('cf:')) {\n const customFieldKey = field.localField.startsWith('cf:') ? field.localField.slice(3) : field.localField\n if (customFieldKey.trim().length > 0) {\n customFields[customFieldKey] = rawValue\n }\n continue\n }\n\n if (field.localField === 'person.externalId') {\n values.externalId = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.firstName') {\n values.firstName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.lastName') {\n values.lastName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.displayName') {\n values.displayName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.primaryEmail') {\n values.primaryEmail = normalizeEmail(rawValue)\n continue\n }\n if (field.localField === 'person.primaryPhone') {\n values.primaryPhone = normalizeImportedPhone(rawValue, row)\n continue\n }\n if (field.localField === 'person.jobTitle') {\n values.jobTitle = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.status') {\n values.status = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.source') {\n values.source = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.description') {\n values.description = normalizeOptionalString(rawValue)\n continue\n }\n\n if (field.localField === 'address.name') {\n addressValues.name = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.purpose') {\n addressValues.purpose = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.companyName') {\n addressValues.companyName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.addressLine1') {\n addressValues.addressLine1 = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.addressLine2') {\n addressValues.addressLine2 = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.buildingNumber') {\n addressValues.buildingNumber = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.flatNumber') {\n addressValues.flatNumber = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.city') {\n addressValues.city = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.region') {\n addressValues.region = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.postalCode') {\n addressValues.postalCode = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.country') {\n addressValues.country = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.latitude') {\n addressValues.latitude = normalizeOptionalNumber(rawValue)\n continue\n }\n if (field.localField === 'address.longitude') {\n addressValues.longitude = normalizeOptionalNumber(rawValue)\n }\n }\n\n return {\n values,\n customFields,\n addressValues,\n }\n}\n\nfunction derivePersonNames(values: PersonFieldValues): { firstName: string; lastName: string; displayName: string } | null {\n const firstName = values.firstName ?? null\n const lastName = values.lastName ?? null\n const explicitDisplayName = values.displayName ?? null\n\n if (firstName && lastName) {\n return {\n firstName,\n lastName,\n displayName: explicitDisplayName ?? `${firstName} ${lastName}`.trim(),\n }\n }\n\n if (explicitDisplayName) {\n const parts = explicitDisplayName.split(/\\s+/).filter((part) => part.length > 0)\n if (parts.length >= 2) {\n return {\n firstName: firstName ?? parts.slice(0, -1).join(' '),\n lastName: lastName ?? parts.at(-1) ?? explicitDisplayName,\n displayName: explicitDisplayName,\n }\n }\n return {\n firstName: firstName ?? explicitDisplayName,\n lastName: lastName ?? explicitDisplayName,\n displayName: explicitDisplayName,\n }\n }\n\n return null\n}\n\nexport function buildPersonPayload(row: CsvPreviewRow, mapping: DataMapping, scope: TenantScope): BuiltPersonPayload {\n const { values, customFields, addressValues } = mapRowValues(row, mapping.fields)\n const derivedNames = derivePersonNames(values)\n const sourceIdentifier = values.externalId ?? values.primaryEmail ?? values.displayName ?? null\n\n const updateInput: BuiltPersonPayload['updateInput'] = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }\n\n if (values.primaryEmail) updateInput.primaryEmail = values.primaryEmail\n if (values.primaryPhone) updateInput.primaryPhone = values.primaryPhone\n if (values.jobTitle) updateInput.jobTitle = values.jobTitle\n if (values.status) updateInput.status = values.status\n if (values.source) updateInput.source = values.source\n if (values.description) updateInput.description = values.description\n if (derivedNames?.firstName) updateInput.firstName = derivedNames.firstName\n if (derivedNames?.lastName) updateInput.lastName = derivedNames.lastName\n if (derivedNames?.displayName) updateInput.displayName = derivedNames.displayName\n\n if (!derivedNames) {\n return {\n values,\n customFields,\n addressValues,\n createInput: null,\n updateInput,\n sourceIdentifier,\n }\n }\n\n return {\n values,\n customFields,\n addressValues,\n createInput: {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n firstName: derivedNames.firstName,\n lastName: derivedNames.lastName,\n displayName: derivedNames.displayName,\n ...(values.primaryEmail ? { primaryEmail: values.primaryEmail } : {}),\n ...(values.primaryPhone ? { primaryPhone: values.primaryPhone } : {}),\n ...(values.jobTitle ? { jobTitle: values.jobTitle } : {}),\n ...(values.status ? { status: values.status } : {}),\n ...(values.source ? { source: values.source } : {}),\n ...(values.description ? { description: values.description } : {}),\n },\n updateInput,\n sourceIdentifier,\n }\n}\n\nfunction hasAddressValues(addressValues: AddressFieldValues): boolean {\n return Object.values(addressValues).some((value) => value !== null && value !== undefined)\n}\n\nfunction buildAddressCreateInput(addressValues: AddressFieldValues, entityId: string, scope: TenantScope) {\n if (!addressValues.addressLine1) return null\n\n return {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entityId,\n addressLine1: addressValues.addressLine1,\n isPrimary: true,\n ...(addressValues.name ? { name: addressValues.name } : {}),\n ...(addressValues.purpose ? { purpose: addressValues.purpose } : {}),\n ...(addressValues.companyName ? { companyName: addressValues.companyName } : {}),\n ...(addressValues.addressLine2 ? { addressLine2: addressValues.addressLine2 } : {}),\n ...(addressValues.buildingNumber ? { buildingNumber: addressValues.buildingNumber } : {}),\n ...(addressValues.flatNumber ? { flatNumber: addressValues.flatNumber } : {}),\n ...(addressValues.city ? { city: addressValues.city } : {}),\n ...(addressValues.region ? { region: addressValues.region } : {}),\n ...(addressValues.postalCode ? { postalCode: addressValues.postalCode } : {}),\n ...(addressValues.country ? { country: addressValues.country } : {}),\n ...(addressValues.latitude !== null && addressValues.latitude !== undefined ? { latitude: addressValues.latitude } : {}),\n ...(addressValues.longitude !== null && addressValues.longitude !== undefined ? { longitude: addressValues.longitude } : {}),\n }\n}\n\nasync function upsertPrimaryAddress(params: {\n entityId: string\n addressValues: AddressFieldValues\n scope: TenantScope\n commandBus: CommandBus\n commandContext: CommandRuntimeContext\n em: EntityManager\n}): Promise<void> {\n if (!hasAddressValues(params.addressValues)) return\n if (!params.addressValues.addressLine1) return\n\n const [existingPrimaryAddress] = await findWithDecryption(\n params.em,\n CustomerAddress,\n {\n entity: params.entityId,\n organizationId: params.scope.organizationId,\n tenantId: params.scope.tenantId,\n isPrimary: true,\n },\n {\n orderBy: {\n createdAt: 'asc',\n },\n limit: 1,\n },\n params.scope,\n )\n\n if (existingPrimaryAddress) {\n await params.commandBus.execute('customers.addresses.update', {\n input: {\n id: existingPrimaryAddress.id,\n isPrimary: true,\n ...(params.addressValues.name ? { name: params.addressValues.name } : {}),\n ...(params.addressValues.purpose ? { purpose: params.addressValues.purpose } : {}),\n ...(params.addressValues.companyName ? { companyName: params.addressValues.companyName } : {}),\n ...(params.addressValues.addressLine1 ? { addressLine1: params.addressValues.addressLine1 } : {}),\n ...(params.addressValues.addressLine2 ? { addressLine2: params.addressValues.addressLine2 } : {}),\n ...(params.addressValues.buildingNumber ? { buildingNumber: params.addressValues.buildingNumber } : {}),\n ...(params.addressValues.flatNumber ? { flatNumber: params.addressValues.flatNumber } : {}),\n ...(params.addressValues.city ? { city: params.addressValues.city } : {}),\n ...(params.addressValues.region ? { region: params.addressValues.region } : {}),\n ...(params.addressValues.postalCode ? { postalCode: params.addressValues.postalCode } : {}),\n ...(params.addressValues.country ? { country: params.addressValues.country } : {}),\n ...(params.addressValues.latitude !== null && params.addressValues.latitude !== undefined\n ? { latitude: params.addressValues.latitude }\n : {}),\n ...(params.addressValues.longitude !== null && params.addressValues.longitude !== undefined\n ? { longitude: params.addressValues.longitude }\n : {}),\n },\n ctx: params.commandContext,\n })\n return\n }\n\n const createInput = buildAddressCreateInput(params.addressValues, params.entityId, params.scope)\n if (!createInput) return\n\n await params.commandBus.execute('customers.addresses.create', {\n input: createInput,\n ctx: params.commandContext,\n })\n}\n\nasync function loadStoredMapping(em: EntityManager, entityType: string, scope: TenantScope): Promise<DataMapping> {\n const stored = await findOneWithDecryption(\n em,\n SyncMapping,\n {\n integrationId: 'sync_excel',\n entityType,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (stored?.mapping && typeof stored.mapping === 'object') {\n return stored.mapping as unknown as DataMapping\n }\n\n return {\n entityType,\n fields: [],\n matchStrategy: 'custom',\n }\n}\n\nasync function resolveUpload(em: EntityManager, runId: string | undefined, cursor: SyncExcelCursor | null, scope: TenantScope): Promise<SyncExcelUpload | null> {\n if (runId) {\n const uploadByRun = await findOneWithDecryption(\n em,\n SyncExcelUpload,\n {\n syncRunId: runId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n if (uploadByRun) return uploadByRun\n }\n\n if (cursor?.uploadId) {\n return findOneWithDecryption(\n em,\n SyncExcelUpload,\n {\n id: cursor.uploadId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n }\n\n return null\n}\n\nasync function resolveExistingPersonId(params: {\n externalIdMappingService: ExternalIdMappingService\n externalId: string | null | undefined\n email: string | null | undefined\n emailDedupeIndex: EmailDedupeIndex\n scope: TenantScope\n}): Promise<string | null> {\n if (params.externalId) {\n const mappedLocalId = await params.externalIdMappingService.lookupLocalId(\n 'sync_excel',\n 'customers.person',\n params.externalId,\n params.scope,\n )\n if (mappedLocalId) return mappedLocalId\n }\n\n if (!params.email) return null\n return params.emailDedupeIndex.get(params.email) ?? null\n}\n\nasync function buildEmailDedupeIndex(params: {\n em: EntityManager\n rows: CsvPreviewRow[]\n mapping: DataMapping\n scope: TenantScope\n}): Promise<EmailDedupeIndex> {\n const emails = new Set<string>()\n for (const row of params.rows) {\n const rowValues = mapRowValues(row, params.mapping.fields)\n const email = rowValues.values.primaryEmail\n if (email) emails.add(email)\n }\n\n if (emails.size === 0) return new Map()\n\n const candidates = await findWithDecryption(\n params.em,\n CustomerEntity,\n {\n kind: 'person',\n organizationId: params.scope.organizationId,\n tenantId: params.scope.tenantId,\n deletedAt: null,\n isActive: true,\n },\n {\n orderBy: {\n createdAt: 'asc',\n },\n },\n params.scope,\n )\n\n const index: EmailDedupeIndex = new Map()\n for (const candidate of candidates) {\n const email = normalizeEmail(candidate.primaryEmail)\n if (!email || !emails.has(email) || index.has(email)) continue\n index.set(email, candidate.id)\n }\n return index\n}\n\nfunction isEmptyRow(row: CsvPreviewRow): boolean {\n return !Object.values(row).some((value) => normalizeOptionalString(value))\n}\n\nasync function processRow(params: {\n row: CsvPreviewRow\n rowNumber: number\n mapping: DataMapping\n scope: TenantScope\n commandBus: CommandBus\n commandContext: CommandRuntimeContext\n externalIdMappingService: ExternalIdMappingService\n emailDedupeIndex: EmailDedupeIndex\n customFieldDefinitions: Map<string, ImportCustomFieldDefinition>\n em: EntityManager\n}): Promise<ImportItem> {\n if (isEmptyRow(params.row)) {\n return {\n externalId: `row:${params.rowNumber}`,\n action: 'skip',\n data: {\n rowNumber: params.rowNumber,\n reason: 'empty_row',\n },\n }\n }\n\n const payload = buildPersonPayload(params.row, params.mapping, params.scope)\n const externalId = payload.values.externalId ?? null\n const sourceIdentifier = payload.sourceIdentifier ?? `row:${params.rowNumber}`\n const customFieldResult = coerceCustomFields(payload.customFields, params.customFieldDefinitions)\n if (!customFieldResult.ok) {\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'failed',\n data: {\n rowNumber: params.rowNumber,\n sourceIdentifier,\n errorMessage: customFieldResult.error,\n },\n }\n }\n const existingId = await resolveExistingPersonId({\n externalIdMappingService: params.externalIdMappingService,\n externalId,\n email: payload.values.primaryEmail,\n emailDedupeIndex: params.emailDedupeIndex,\n scope: params.scope,\n })\n\n if (!existingId && !payload.createInput) {\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'failed',\n data: {\n rowNumber: params.rowNumber,\n sourceIdentifier,\n errorMessage: 'Import row is missing a usable person name mapping.',\n },\n }\n }\n\n try {\n if (existingId) {\n const updateInput = {\n id: existingId,\n ...payload.updateInput,\n ...(Object.keys(customFieldResult.values).length > 0 ? { customFields: customFieldResult.values } : {}),\n }\n await params.commandBus.execute('customers.people.update', {\n input: updateInput,\n ctx: params.commandContext,\n })\n\n await upsertPrimaryAddress({\n entityId: existingId,\n addressValues: payload.addressValues,\n scope: params.scope,\n commandBus: params.commandBus,\n commandContext: params.commandContext,\n em: params.em,\n })\n\n if (externalId) {\n await params.externalIdMappingService.storeExternalIdMapping(\n 'sync_excel',\n 'customers.person',\n existingId,\n externalId,\n params.scope,\n )\n }\n if (payload.values.primaryEmail && !params.emailDedupeIndex.has(payload.values.primaryEmail)) {\n params.emailDedupeIndex.set(payload.values.primaryEmail, existingId)\n }\n\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'update',\n data: {\n localId: existingId,\n rowNumber: params.rowNumber,\n sourceIdentifier,\n },\n }\n }\n\n const commandResult = await params.commandBus.execute<\n NonNullable<BuiltPersonPayload['createInput']>,\n { entityId: string; personId: string }\n >('customers.people.create', {\n input: {\n ...payload.createInput!,\n ...(Object.keys(customFieldResult.values).length > 0 ? { customFields: customFieldResult.values } : {}),\n },\n ctx: params.commandContext,\n })\n\n await upsertPrimaryAddress({\n entityId: commandResult.result.entityId,\n addressValues: payload.addressValues,\n scope: params.scope,\n commandBus: params.commandBus,\n commandContext: params.commandContext,\n em: params.em,\n })\n\n if (externalId) {\n await params.externalIdMappingService.storeExternalIdMapping(\n 'sync_excel',\n 'customers.person',\n commandResult.result.entityId,\n externalId,\n params.scope,\n )\n }\n if (payload.values.primaryEmail && !params.emailDedupeIndex.has(payload.values.primaryEmail)) {\n params.emailDedupeIndex.set(payload.values.primaryEmail, commandResult.result.entityId)\n }\n\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'create',\n data: {\n localId: commandResult.result.entityId,\n personId: commandResult.result.personId,\n rowNumber: params.rowNumber,\n sourceIdentifier,\n },\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Import row failed'\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'failed',\n data: {\n rowNumber: params.rowNumber,\n sourceIdentifier,\n errorMessage,\n },\n }\n }\n}\n\nexport const syncExcelCustomersAdapter: DataSyncAdapter = {\n providerKey: 'excel',\n operationalTelemetry: true,\n direction: 'import',\n supportedEntities: ['customers.person'],\n\n async getMapping(input): Promise<DataMapping> {\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n return loadStoredMapping(em, input.entityType, input.scope)\n },\n\n async *streamImport(input): AsyncIterable<ImportBatch> {\n if (input.entityType !== 'customers.person') {\n throw new Error(`Unsupported sync_excel entity type: ${input.entityType}`)\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const commandBus = container.resolve('commandBus') as CommandBus\n const externalIdMappingService = container.resolve('externalIdMappingService') as ExternalIdMappingService\n const cursor = parseCursor(input.cursor)\n const upload = await resolveUpload(em, input.runId, cursor, input.scope)\n\n if (!upload) {\n throw new Error('CSV upload session was not found for this sync run.')\n }\n\n if (input.runId) {\n upload.syncRunId = input.runId\n }\n upload.status = 'importing'\n await em.flush()\n\n try {\n const attachment = await findOneWithDecryption(\n em,\n Attachment,\n {\n id: upload.attachmentId,\n organizationId: input.scope.organizationId,\n tenantId: input.scope.tenantId,\n },\n undefined,\n input.scope,\n )\n\n if (!attachment) {\n throw new Error('CSV upload attachment could not be found.')\n }\n\n const fileBuffer = await readSyncExcelUploadBuffer(attachment)\n const document = parseCsvDocument(fileBuffer)\n const startOffset = cursor?.uploadId === upload.id ? cursor.offset : 0\n const commandContext = buildCommandContext(container, input.scope)\n const customFieldDefinitions = await loadImportCustomFieldDefinitions(em, input.scope)\n\n for (let offset = startOffset, batchIndex = 0; offset < document.rows.length; offset += input.batchSize, batchIndex += 1) {\n const batchRows = document.rows.slice(offset, offset + input.batchSize)\n const emailDedupeIndex = await buildEmailDedupeIndex({\n em,\n rows: batchRows,\n mapping: input.mapping,\n scope: input.scope,\n })\n const items: ImportItem[] = []\n\n for (let index = 0; index < batchRows.length; index += 1) {\n items.push(await processRow({\n row: batchRows[index],\n rowNumber: offset + index + 1,\n mapping: input.mapping,\n scope: input.scope,\n commandBus,\n commandContext,\n externalIdMappingService,\n emailDedupeIndex,\n customFieldDefinitions,\n em,\n }))\n }\n\n const nextOffset = offset + batchRows.length\n yield {\n items,\n cursor: createCursor(upload.id, nextOffset),\n hasMore: nextOffset < document.rows.length,\n totalEstimate: document.totalRows,\n processedCount: batchRows.length,\n refreshCoverageEntityTypes: CUSTOMER_IMPORT_COVERAGE_ENTITY_TYPES,\n batchIndex,\n message: `Processed ${nextOffset} of ${document.totalRows} CSV rows`,\n }\n }\n\n upload.status = 'completed'\n await em.flush()\n } catch (error) {\n upload.status = 'failed'\n await em.flush()\n throw error\n }\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { extractPhoneDigits, validatePhoneNumber } from '@open-mercato/shared/lib/phone'\nimport type {\n DataMapping,\n DataSyncAdapter,\n FieldMapping,\n ImportBatch,\n ImportItem,\n TenantScope,\n} from '../../../data_sync/lib/adapter'\nimport type { ExternalIdMappingService } from '../../../data_sync/lib/id-mapping'\nimport { SyncMapping } from '../../../data_sync/data/entities'\nimport { CustomerAddress, CustomerEntity } from '../../../customers/data/entities'\nimport { Attachment } from '../../../attachments/data/entities'\nimport { CustomFieldDef } from '../../../entities/data/entities'\nimport { SyncExcelUpload } from '../../data/entities'\nimport { parseCsvDocument, type CsvPreviewRow } from '../parser'\nimport { readSyncExcelUploadBuffer } from '../upload-storage'\nimport { E } from '#generated/entities.ids.generated'\n\ntype SyncExcelCursor = {\n uploadId: string\n offset: number\n}\n\ntype Container = Awaited<ReturnType<typeof createRequestContainer>>\n\nconst CUSTOMER_IMPORT_COVERAGE_ENTITY_TYPES = [\n E.customers.customer_entity,\n E.customers.customer_person_profile,\n E.customers.customer_address,\n]\n\ntype PersonFieldValues = {\n externalId?: string | null\n firstName?: string | null\n lastName?: string | null\n displayName?: string | null\n primaryEmail?: string | null\n primaryPhone?: string | null\n jobTitle?: string | null\n status?: string | null\n source?: string | null\n description?: string | null\n}\n\ntype AddressFieldValues = {\n name?: string | null\n purpose?: string | null\n companyName?: string | null\n addressLine1?: string | null\n addressLine2?: string | null\n buildingNumber?: string | null\n flatNumber?: string | null\n city?: string | null\n region?: string | null\n postalCode?: string | null\n country?: string | null\n latitude?: number | null\n longitude?: number | null\n}\n\ntype PersonRowValues = {\n values: PersonFieldValues\n customFields: Record<string, unknown>\n addressValues: AddressFieldValues\n}\n\ntype ImportCustomFieldDefinition = {\n key: string\n kind: string\n entityId: string\n organizationId?: string | null\n tenantId?: string | null\n updatedAt?: Date | string | null\n}\n\ntype EmailDedupeIndex = Map<string, string>\n\ntype BuiltPersonPayload = {\n values: PersonFieldValues\n customFields: Record<string, unknown>\n addressValues: AddressFieldValues\n createInput: {\n organizationId: string\n tenantId: string\n firstName: string\n lastName: string\n displayName: string\n primaryEmail?: string\n primaryPhone?: string\n jobTitle?: string\n status?: string\n source?: string\n description?: string\n customFields?: Record<string, unknown>\n } | null\n updateInput: {\n organizationId: string\n tenantId: string\n primaryEmail?: string\n primaryPhone?: string\n jobTitle?: string\n status?: string\n source?: string\n description?: string\n firstName?: string\n lastName?: string\n displayName?: string\n customFields?: Record<string, unknown>\n }\n sourceIdentifier: string | null\n}\n\nfunction normalizeOptionalString(value: unknown): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction normalizeEmail(value: unknown): string | null {\n const normalized = normalizeOptionalString(value)\n return normalized ? normalized.toLowerCase() : null\n}\n\nconst COUNTRY_DIAL_CODES: Record<string, string> = {\n canada: '1',\n england: '44',\n greatbritain: '44',\n poland: '48',\n scotland: '44',\n uk: '44',\n unitedkingdom: '44',\n unitedstates: '1',\n unitedstatesofamerica: '1',\n usa: '1',\n wales: '44',\n}\n\nfunction normalizeCountryKey(value: unknown): string | null {\n const normalized = normalizeOptionalString(value)\n if (!normalized) return null\n return normalized.toLowerCase().replace(/[^a-z]/g, '')\n}\n\nfunction resolveCountryDialCode(row: CsvPreviewRow): string | null {\n const countryCandidates = [\n row.Country,\n row.country,\n row['Country/Region'],\n row['country/region'],\n ]\n\n for (const candidate of countryCandidates) {\n const countryKey = normalizeCountryKey(candidate)\n if (!countryKey) continue\n const dialCode = COUNTRY_DIAL_CODES[countryKey]\n if (dialCode) return dialCode\n }\n\n return null\n}\n\nfunction stripPhoneExtension(value: string): string {\n return value\n .replace(/\\s*(ext\\.?|extension|x)\\s*\\d+$/i, '')\n .replace(/^\\+\\s+/, '+')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\nfunction normalizeImportedPhone(value: unknown, row: CsvPreviewRow): string | null {\n const normalized = normalizeOptionalString(value)\n if (!normalized) return null\n\n const directValidation = validatePhoneNumber(normalized)\n if (directValidation.valid) {\n return directValidation.normalized\n }\n\n const sanitized = stripPhoneExtension(normalized)\n const sanitizedValidation = validatePhoneNumber(sanitized)\n if (sanitizedValidation.valid) {\n return sanitizedValidation.normalized\n }\n\n const digits = extractPhoneDigits(sanitized)\n if (!digits) return null\n\n if (digits.length >= 9 && digits.length <= 15 && sanitized.startsWith('00')) {\n const internationalCandidate = `+${digits.slice(2)}`\n const internationalValidation = validatePhoneNumber(internationalCandidate)\n if (internationalValidation.valid) {\n return internationalValidation.normalized\n }\n }\n\n const dialCode = resolveCountryDialCode(row)\n if (!dialCode) return null\n\n let nationalDigits = digits\n if (nationalDigits.startsWith(dialCode)) {\n nationalDigits = nationalDigits.slice(dialCode.length)\n } else {\n nationalDigits = nationalDigits.replace(/^0+/, '')\n }\n\n if (!nationalDigits) return null\n\n const localizedCandidate = `+${dialCode}${nationalDigits}`\n const localizedValidation = validatePhoneNumber(localizedCandidate)\n return localizedValidation.valid ? localizedValidation.normalized : null\n}\n\nfunction normalizeOptionalNumber(value: unknown): number | null {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? value : null\n }\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n if (trimmed.length === 0) return null\n const parsed = Number(trimmed)\n return Number.isFinite(parsed) ? parsed : null\n}\n\nfunction normalizeCustomFieldDate(value: string): string | null {\n const parsed = new Date(value)\n if (Number.isNaN(parsed.getTime())) return null\n return parsed.toISOString().slice(0, 10)\n}\n\nfunction normalizeCustomFieldBoolean(value: string): boolean | null {\n const normalized = value.trim().toLowerCase()\n if (['true', '1', 'yes', 'y', 't', 'tak'].includes(normalized)) return true\n if (['false', '0', 'no', 'n', 'f', 'nie'].includes(normalized)) return false\n return null\n}\n\nfunction coerceCustomFieldValue(\n key: string,\n value: unknown,\n definitions: Map<string, ImportCustomFieldDefinition>,\n): { ok: true; value: unknown } | { ok: false; error: string } {\n if (typeof value === 'string' && value.trim().length === 0) {\n return { ok: true, value: null }\n }\n\n const definition = definitions.get(key)\n if (!definition) {\n return { ok: true, value: typeof value === 'string' ? value.trim() : value }\n }\n\n if (value === null || value === undefined) {\n return { ok: true, value: null }\n }\n\n const text = typeof value === 'string' ? value.trim() : String(value)\n if (text.length === 0) {\n return { ok: true, value: null }\n }\n\n const kind = definition.kind.toLowerCase()\n if (kind === 'boolean') {\n const booleanValue = normalizeCustomFieldBoolean(text)\n if (booleanValue === null) {\n return { ok: false, error: `Custom field \"${key}\" expects a boolean value.` }\n }\n return { ok: true, value: booleanValue }\n }\n\n if (kind === 'integer') {\n const numberValue = Number(text)\n if (!Number.isInteger(numberValue)) {\n return { ok: false, error: `Custom field \"${key}\" expects an integer value.` }\n }\n return { ok: true, value: numberValue }\n }\n\n if (kind === 'float' || kind === 'currency' || kind === 'number') {\n const numberValue = Number(text)\n if (!Number.isFinite(numberValue)) {\n return { ok: false, error: `Custom field \"${key}\" expects a number value.` }\n }\n return { ok: true, value: numberValue }\n }\n\n if (kind === 'date' || kind === 'datetime') {\n const dateValue = normalizeCustomFieldDate(text)\n if (!dateValue) {\n return { ok: false, error: `Custom field \"${key}\" expects a date value.` }\n }\n return { ok: true, value: dateValue }\n }\n\n return { ok: true, value: text }\n}\n\nfunction coerceCustomFields(\n values: Record<string, unknown>,\n definitions: Map<string, ImportCustomFieldDefinition>,\n): { ok: true; values: Record<string, unknown> } | { ok: false; error: string } {\n const coerced: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(values)) {\n const result = coerceCustomFieldValue(key, value, definitions)\n if (!result.ok) return result\n coerced[key] = result.value\n }\n return { ok: true, values: coerced }\n}\n\nfunction customFieldDefinitionScopeScore(definition: ImportCustomFieldDefinition): number {\n return (definition.tenantId ? 2 : 0) + (definition.organizationId ? 1 : 0)\n}\n\nfunction customFieldDefinitionUpdatedAt(definition: ImportCustomFieldDefinition): number {\n if (!definition.updatedAt) return 0\n const value = definition.updatedAt instanceof Date\n ? definition.updatedAt.getTime()\n : new Date(definition.updatedAt).getTime()\n return Number.isFinite(value) ? value : 0\n}\n\nfunction preferCustomFieldDefinition(\n current: ImportCustomFieldDefinition | undefined,\n candidate: ImportCustomFieldDefinition,\n): boolean {\n if (!current) return true\n const candidateScore = customFieldDefinitionScopeScore(candidate)\n const currentScore = customFieldDefinitionScopeScore(current)\n if (candidateScore !== currentScore) return candidateScore > currentScore\n return customFieldDefinitionUpdatedAt(candidate) >= customFieldDefinitionUpdatedAt(current)\n}\n\nasync function loadImportCustomFieldDefinitions(\n em: EntityManager,\n scope: TenantScope,\n): Promise<Map<string, ImportCustomFieldDefinition>> {\n const definitions = await findWithDecryption(\n em,\n CustomFieldDef,\n {\n entityId: { $in: [E.customers.customer_entity, E.customers.customer_person_profile] as string[] },\n deletedAt: null,\n isActive: true,\n $and: [\n { $or: [{ tenantId: scope.tenantId }, { tenantId: null }] },\n { $or: [{ organizationId: scope.organizationId }, { organizationId: null }] },\n ],\n },\n undefined,\n scope,\n )\n\n const byKey = new Map<string, ImportCustomFieldDefinition>()\n for (const definition of definitions) {\n const candidate: ImportCustomFieldDefinition = {\n key: definition.key,\n kind: definition.kind,\n entityId: definition.entityId,\n organizationId: definition.organizationId ?? null,\n tenantId: definition.tenantId ?? null,\n updatedAt: definition.updatedAt ?? null,\n }\n if (preferCustomFieldDefinition(byKey.get(candidate.key), candidate)) {\n byKey.set(candidate.key, candidate)\n }\n }\n return byKey\n}\n\nfunction buildCommandContext(container: Container, scope: TenantScope): CommandRuntimeContext {\n return {\n container,\n auth: null,\n organizationScope: {\n selectedId: scope.organizationId,\n filterIds: [scope.organizationId],\n allowedIds: [scope.organizationId],\n tenantId: scope.tenantId,\n },\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n}\n\nexport function createCursor(uploadId: string, offset: number): string {\n return JSON.stringify({\n uploadId,\n offset,\n })\n}\n\nexport function parseCursor(value: string | null | undefined): SyncExcelCursor | null {\n if (!value) return null\n try {\n const parsed = JSON.parse(value) as Partial<SyncExcelCursor> | null\n if (!parsed || typeof parsed !== 'object') return null\n if (typeof parsed.uploadId !== 'string' || parsed.uploadId.trim().length === 0) return null\n if (typeof parsed.offset !== 'number' || !Number.isFinite(parsed.offset) || parsed.offset < 0) return null\n return {\n uploadId: parsed.uploadId,\n offset: parsed.offset,\n }\n } catch {\n return null\n }\n}\n\nfunction mapRowValues(row: CsvPreviewRow, fields: FieldMapping[]): PersonRowValues {\n const values: PersonFieldValues = {}\n const customFields: Record<string, unknown> = {}\n const addressValues: AddressFieldValues = {}\n\n for (const field of fields) {\n if (field.mappingKind === 'ignore') continue\n const rawValue = row[field.externalField]\n if (rawValue === undefined || rawValue === null) continue\n if (field.mappingKind === 'custom_field' || field.localField.startsWith('cf:')) {\n const customFieldKey = field.localField.startsWith('cf:') ? field.localField.slice(3) : field.localField\n if (customFieldKey.trim().length > 0) {\n customFields[customFieldKey] = rawValue\n }\n continue\n }\n\n if (field.localField === 'person.externalId') {\n values.externalId = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.firstName') {\n values.firstName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.lastName') {\n values.lastName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.displayName') {\n values.displayName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.primaryEmail') {\n values.primaryEmail = normalizeEmail(rawValue)\n continue\n }\n if (field.localField === 'person.primaryPhone') {\n values.primaryPhone = normalizeImportedPhone(rawValue, row)\n continue\n }\n if (field.localField === 'person.jobTitle') {\n values.jobTitle = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.status') {\n values.status = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.source') {\n values.source = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'person.description') {\n values.description = normalizeOptionalString(rawValue)\n continue\n }\n\n if (field.localField === 'address.name') {\n addressValues.name = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.purpose') {\n addressValues.purpose = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.companyName') {\n addressValues.companyName = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.addressLine1') {\n addressValues.addressLine1 = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.addressLine2') {\n addressValues.addressLine2 = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.buildingNumber') {\n addressValues.buildingNumber = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.flatNumber') {\n addressValues.flatNumber = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.city') {\n addressValues.city = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.region') {\n addressValues.region = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.postalCode') {\n addressValues.postalCode = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.country') {\n addressValues.country = normalizeOptionalString(rawValue)\n continue\n }\n if (field.localField === 'address.latitude') {\n addressValues.latitude = normalizeOptionalNumber(rawValue)\n continue\n }\n if (field.localField === 'address.longitude') {\n addressValues.longitude = normalizeOptionalNumber(rawValue)\n }\n }\n\n return {\n values,\n customFields,\n addressValues,\n }\n}\n\nfunction derivePersonNames(values: PersonFieldValues): { firstName: string; lastName: string; displayName: string } | null {\n const firstName = values.firstName ?? null\n const lastName = values.lastName ?? null\n const explicitDisplayName = values.displayName ?? null\n\n if (firstName && lastName) {\n return {\n firstName,\n lastName,\n displayName: explicitDisplayName ?? `${firstName} ${lastName}`.trim(),\n }\n }\n\n if (explicitDisplayName) {\n const parts = explicitDisplayName.split(/\\s+/).filter((part) => part.length > 0)\n if (parts.length >= 2) {\n return {\n firstName: firstName ?? parts.slice(0, -1).join(' '),\n lastName: lastName ?? parts.at(-1) ?? explicitDisplayName,\n displayName: explicitDisplayName,\n }\n }\n return {\n firstName: firstName ?? explicitDisplayName,\n lastName: lastName ?? explicitDisplayName,\n displayName: explicitDisplayName,\n }\n }\n\n return null\n}\n\nexport function buildPersonPayload(row: CsvPreviewRow, mapping: DataMapping, scope: TenantScope): BuiltPersonPayload {\n const { values, customFields, addressValues } = mapRowValues(row, mapping.fields)\n const derivedNames = derivePersonNames(values)\n const sourceIdentifier = values.externalId ?? values.primaryEmail ?? values.displayName ?? null\n\n const updateInput: BuiltPersonPayload['updateInput'] = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }\n\n if (values.primaryEmail) updateInput.primaryEmail = values.primaryEmail\n if (values.primaryPhone) updateInput.primaryPhone = values.primaryPhone\n if (values.jobTitle) updateInput.jobTitle = values.jobTitle\n if (values.status) updateInput.status = values.status\n if (values.source) updateInput.source = values.source\n if (values.description) updateInput.description = values.description\n if (derivedNames?.firstName) updateInput.firstName = derivedNames.firstName\n if (derivedNames?.lastName) updateInput.lastName = derivedNames.lastName\n if (derivedNames?.displayName) updateInput.displayName = derivedNames.displayName\n\n if (!derivedNames) {\n return {\n values,\n customFields,\n addressValues,\n createInput: null,\n updateInput,\n sourceIdentifier,\n }\n }\n\n return {\n values,\n customFields,\n addressValues,\n createInput: {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n firstName: derivedNames.firstName,\n lastName: derivedNames.lastName,\n displayName: derivedNames.displayName,\n ...(values.primaryEmail ? { primaryEmail: values.primaryEmail } : {}),\n ...(values.primaryPhone ? { primaryPhone: values.primaryPhone } : {}),\n ...(values.jobTitle ? { jobTitle: values.jobTitle } : {}),\n ...(values.status ? { status: values.status } : {}),\n ...(values.source ? { source: values.source } : {}),\n ...(values.description ? { description: values.description } : {}),\n },\n updateInput,\n sourceIdentifier,\n }\n}\n\nfunction hasAddressValues(addressValues: AddressFieldValues): boolean {\n return Object.values(addressValues).some((value) => value !== null && value !== undefined)\n}\n\nfunction buildAddressCreateInput(addressValues: AddressFieldValues, entityId: string, scope: TenantScope) {\n if (!addressValues.addressLine1) return null\n\n return {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entityId,\n addressLine1: addressValues.addressLine1,\n isPrimary: true,\n ...(addressValues.name ? { name: addressValues.name } : {}),\n ...(addressValues.purpose ? { purpose: addressValues.purpose } : {}),\n ...(addressValues.companyName ? { companyName: addressValues.companyName } : {}),\n ...(addressValues.addressLine2 ? { addressLine2: addressValues.addressLine2 } : {}),\n ...(addressValues.buildingNumber ? { buildingNumber: addressValues.buildingNumber } : {}),\n ...(addressValues.flatNumber ? { flatNumber: addressValues.flatNumber } : {}),\n ...(addressValues.city ? { city: addressValues.city } : {}),\n ...(addressValues.region ? { region: addressValues.region } : {}),\n ...(addressValues.postalCode ? { postalCode: addressValues.postalCode } : {}),\n ...(addressValues.country ? { country: addressValues.country } : {}),\n ...(addressValues.latitude !== null && addressValues.latitude !== undefined ? { latitude: addressValues.latitude } : {}),\n ...(addressValues.longitude !== null && addressValues.longitude !== undefined ? { longitude: addressValues.longitude } : {}),\n }\n}\n\nasync function upsertPrimaryAddress(params: {\n entityId: string\n addressValues: AddressFieldValues\n scope: TenantScope\n commandBus: CommandBus\n commandContext: CommandRuntimeContext\n em: EntityManager\n}): Promise<void> {\n if (!hasAddressValues(params.addressValues)) return\n if (!params.addressValues.addressLine1) return\n\n const [existingPrimaryAddress] = await findWithDecryption(\n params.em,\n CustomerAddress,\n {\n entity: params.entityId,\n organizationId: params.scope.organizationId,\n tenantId: params.scope.tenantId,\n isPrimary: true,\n },\n {\n orderBy: {\n createdAt: 'asc',\n },\n limit: 1,\n },\n params.scope,\n )\n\n if (existingPrimaryAddress) {\n await params.commandBus.execute('customers.addresses.update', {\n input: {\n id: existingPrimaryAddress.id,\n isPrimary: true,\n ...(params.addressValues.name ? { name: params.addressValues.name } : {}),\n ...(params.addressValues.purpose ? { purpose: params.addressValues.purpose } : {}),\n ...(params.addressValues.companyName ? { companyName: params.addressValues.companyName } : {}),\n ...(params.addressValues.addressLine1 ? { addressLine1: params.addressValues.addressLine1 } : {}),\n ...(params.addressValues.addressLine2 ? { addressLine2: params.addressValues.addressLine2 } : {}),\n ...(params.addressValues.buildingNumber ? { buildingNumber: params.addressValues.buildingNumber } : {}),\n ...(params.addressValues.flatNumber ? { flatNumber: params.addressValues.flatNumber } : {}),\n ...(params.addressValues.city ? { city: params.addressValues.city } : {}),\n ...(params.addressValues.region ? { region: params.addressValues.region } : {}),\n ...(params.addressValues.postalCode ? { postalCode: params.addressValues.postalCode } : {}),\n ...(params.addressValues.country ? { country: params.addressValues.country } : {}),\n ...(params.addressValues.latitude !== null && params.addressValues.latitude !== undefined\n ? { latitude: params.addressValues.latitude }\n : {}),\n ...(params.addressValues.longitude !== null && params.addressValues.longitude !== undefined\n ? { longitude: params.addressValues.longitude }\n : {}),\n },\n ctx: params.commandContext,\n })\n return\n }\n\n const createInput = buildAddressCreateInput(params.addressValues, params.entityId, params.scope)\n if (!createInput) return\n\n await params.commandBus.execute('customers.addresses.create', {\n input: createInput,\n ctx: params.commandContext,\n })\n}\n\nasync function loadStoredMapping(em: EntityManager, entityType: string, scope: TenantScope): Promise<DataMapping> {\n const stored = await findOneWithDecryption(\n em,\n SyncMapping,\n {\n integrationId: 'sync_excel',\n entityType,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (stored?.mapping && typeof stored.mapping === 'object') {\n return stored.mapping as unknown as DataMapping\n }\n\n return {\n entityType,\n fields: [],\n matchStrategy: 'custom',\n }\n}\n\nasync function resolveUpload(em: EntityManager, runId: string | undefined, cursor: SyncExcelCursor | null, scope: TenantScope): Promise<SyncExcelUpload | null> {\n if (runId) {\n const uploadByRun = await findOneWithDecryption(\n em,\n SyncExcelUpload,\n {\n syncRunId: runId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n if (uploadByRun) return uploadByRun\n }\n\n if (cursor?.uploadId) {\n return findOneWithDecryption(\n em,\n SyncExcelUpload,\n {\n id: cursor.uploadId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n }\n\n return null\n}\n\nasync function resolveExistingPersonId(params: {\n externalIdMappingService: ExternalIdMappingService\n externalId: string | null | undefined\n email: string | null | undefined\n emailDedupeIndex: EmailDedupeIndex\n scope: TenantScope\n}): Promise<string | null> {\n if (params.externalId) {\n const mappedLocalId = await params.externalIdMappingService.lookupLocalId(\n 'sync_excel',\n 'customers.person',\n params.externalId,\n params.scope,\n )\n if (mappedLocalId) return mappedLocalId\n }\n\n if (!params.email) return null\n return params.emailDedupeIndex.get(params.email) ?? null\n}\n\nasync function buildEmailDedupeIndex(params: {\n em: EntityManager\n rows: CsvPreviewRow[]\n mapping: DataMapping\n scope: TenantScope\n}): Promise<EmailDedupeIndex> {\n const emails = new Set<string>()\n for (const row of params.rows) {\n const rowValues = mapRowValues(row, params.mapping.fields)\n const email = rowValues.values.primaryEmail\n if (email) emails.add(email)\n }\n\n if (emails.size === 0) return new Map()\n\n const candidates = await findWithDecryption(\n params.em,\n CustomerEntity,\n {\n kind: 'person',\n organizationId: params.scope.organizationId,\n tenantId: params.scope.tenantId,\n deletedAt: null,\n isActive: true,\n },\n {\n orderBy: {\n createdAt: 'asc',\n },\n },\n params.scope,\n )\n\n const index: EmailDedupeIndex = new Map()\n for (const candidate of candidates) {\n const email = normalizeEmail(candidate.primaryEmail)\n if (!email || !emails.has(email) || index.has(email)) continue\n index.set(email, candidate.id)\n }\n return index\n}\n\nfunction isEmptyRow(row: CsvPreviewRow): boolean {\n return !Object.values(row).some((value) => normalizeOptionalString(value))\n}\n\nasync function processRow(params: {\n row: CsvPreviewRow\n rowNumber: number\n mapping: DataMapping\n scope: TenantScope\n commandBus: CommandBus\n commandContext: CommandRuntimeContext\n externalIdMappingService: ExternalIdMappingService\n emailDedupeIndex: EmailDedupeIndex\n customFieldDefinitions: Map<string, ImportCustomFieldDefinition>\n em: EntityManager\n}): Promise<ImportItem> {\n if (isEmptyRow(params.row)) {\n return {\n externalId: `row:${params.rowNumber}`,\n action: 'skip',\n data: {\n rowNumber: params.rowNumber,\n reason: 'empty_row',\n },\n }\n }\n\n const payload = buildPersonPayload(params.row, params.mapping, params.scope)\n const externalId = payload.values.externalId ?? null\n const sourceIdentifier = payload.sourceIdentifier ?? `row:${params.rowNumber}`\n const customFieldResult = coerceCustomFields(payload.customFields, params.customFieldDefinitions)\n if (!customFieldResult.ok) {\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'failed',\n data: {\n rowNumber: params.rowNumber,\n sourceIdentifier,\n errorMessage: customFieldResult.error,\n },\n }\n }\n const existingId = await resolveExistingPersonId({\n externalIdMappingService: params.externalIdMappingService,\n externalId,\n email: payload.values.primaryEmail,\n emailDedupeIndex: params.emailDedupeIndex,\n scope: params.scope,\n })\n\n if (!existingId && !payload.createInput) {\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'failed',\n data: {\n rowNumber: params.rowNumber,\n sourceIdentifier,\n errorMessage: 'Import row is missing a usable person name mapping.',\n },\n }\n }\n\n try {\n if (existingId) {\n const updateInput = {\n id: existingId,\n ...payload.updateInput,\n ...(Object.keys(customFieldResult.values).length > 0 ? { customFields: customFieldResult.values } : {}),\n }\n await params.commandBus.execute('customers.people.update', {\n input: updateInput,\n ctx: params.commandContext,\n })\n\n await upsertPrimaryAddress({\n entityId: existingId,\n addressValues: payload.addressValues,\n scope: params.scope,\n commandBus: params.commandBus,\n commandContext: params.commandContext,\n em: params.em,\n })\n\n if (externalId) {\n await params.externalIdMappingService.storeExternalIdMapping(\n 'sync_excel',\n 'customers.person',\n existingId,\n externalId,\n params.scope,\n )\n }\n if (payload.values.primaryEmail && !params.emailDedupeIndex.has(payload.values.primaryEmail)) {\n params.emailDedupeIndex.set(payload.values.primaryEmail, existingId)\n }\n\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'update',\n data: {\n localId: existingId,\n rowNumber: params.rowNumber,\n sourceIdentifier,\n },\n }\n }\n\n const commandResult = await params.commandBus.execute<\n NonNullable<BuiltPersonPayload['createInput']>,\n { entityId: string; personId: string }\n >('customers.people.create', {\n input: {\n ...payload.createInput!,\n ...(Object.keys(customFieldResult.values).length > 0 ? { customFields: customFieldResult.values } : {}),\n },\n ctx: params.commandContext,\n })\n\n await upsertPrimaryAddress({\n entityId: commandResult.result.entityId,\n addressValues: payload.addressValues,\n scope: params.scope,\n commandBus: params.commandBus,\n commandContext: params.commandContext,\n em: params.em,\n })\n\n if (externalId) {\n await params.externalIdMappingService.storeExternalIdMapping(\n 'sync_excel',\n 'customers.person',\n commandResult.result.entityId,\n externalId,\n params.scope,\n )\n }\n if (payload.values.primaryEmail && !params.emailDedupeIndex.has(payload.values.primaryEmail)) {\n params.emailDedupeIndex.set(payload.values.primaryEmail, commandResult.result.entityId)\n }\n\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'create',\n data: {\n localId: commandResult.result.entityId,\n personId: commandResult.result.personId,\n rowNumber: params.rowNumber,\n sourceIdentifier,\n },\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Import row failed'\n return {\n externalId: externalId ?? sourceIdentifier,\n action: 'failed',\n data: {\n rowNumber: params.rowNumber,\n sourceIdentifier,\n errorMessage,\n },\n }\n }\n}\n\nexport const syncExcelCustomersAdapter: DataSyncAdapter = {\n providerKey: 'excel',\n runMode: 'provider',\n operationalTelemetry: true,\n direction: 'import',\n supportedEntities: ['customers.person'],\n\n async getMapping(input): Promise<DataMapping> {\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n return loadStoredMapping(em, input.entityType, input.scope)\n },\n\n async *streamImport(input): AsyncIterable<ImportBatch> {\n if (input.entityType !== 'customers.person') {\n throw new Error(`Unsupported sync_excel entity type: ${input.entityType}`)\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const commandBus = container.resolve('commandBus') as CommandBus\n const externalIdMappingService = container.resolve('externalIdMappingService') as ExternalIdMappingService\n const cursor = parseCursor(input.cursor)\n const upload = await resolveUpload(em, input.runId, cursor, input.scope)\n\n if (!upload) {\n throw new Error('CSV upload session was not found for this sync run.')\n }\n\n if (input.runId) {\n upload.syncRunId = input.runId\n }\n upload.status = 'importing'\n await em.flush()\n\n try {\n const attachment = await findOneWithDecryption(\n em,\n Attachment,\n {\n id: upload.attachmentId,\n organizationId: input.scope.organizationId,\n tenantId: input.scope.tenantId,\n },\n undefined,\n input.scope,\n )\n\n if (!attachment) {\n throw new Error('CSV upload attachment could not be found.')\n }\n\n const fileBuffer = await readSyncExcelUploadBuffer(attachment)\n const document = parseCsvDocument(fileBuffer)\n const startOffset = cursor?.uploadId === upload.id ? cursor.offset : 0\n const commandContext = buildCommandContext(container, input.scope)\n const customFieldDefinitions = await loadImportCustomFieldDefinitions(em, input.scope)\n\n for (let offset = startOffset, batchIndex = 0; offset < document.rows.length; offset += input.batchSize, batchIndex += 1) {\n const batchRows = document.rows.slice(offset, offset + input.batchSize)\n const emailDedupeIndex = await buildEmailDedupeIndex({\n em,\n rows: batchRows,\n mapping: input.mapping,\n scope: input.scope,\n })\n const items: ImportItem[] = []\n\n for (let index = 0; index < batchRows.length; index += 1) {\n items.push(await processRow({\n row: batchRows[index],\n rowNumber: offset + index + 1,\n mapping: input.mapping,\n scope: input.scope,\n commandBus,\n commandContext,\n externalIdMappingService,\n emailDedupeIndex,\n customFieldDefinitions,\n em,\n }))\n }\n\n const nextOffset = offset + batchRows.length\n yield {\n items,\n cursor: createCursor(upload.id, nextOffset),\n hasMore: nextOffset < document.rows.length,\n totalEstimate: document.totalRows,\n processedCount: batchRows.length,\n refreshCoverageEntityTypes: CUSTOMER_IMPORT_COVERAGE_ENTITY_TYPES,\n batchIndex,\n message: `Processed ${nextOffset} of ${document.totalRows} CSV rows`,\n }\n }\n\n upload.status = 'completed'\n await em.flush()\n } catch (error) {\n upload.status = 'failed'\n await em.flush()\n throw error\n }\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }