eggi-ai-db-schema-2 12.54.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 (188) hide show
  1. package/CHANGELOG.md +750 -0
  2. package/README.md +655 -0
  3. package/dist/config/database.d.ts +28 -0
  4. package/dist/config/database.d.ts.map +1 -0
  5. package/dist/config/database.js +72 -0
  6. package/dist/config/database.js.map +1 -0
  7. package/dist/index.d.ts +28 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +199 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/database-service.d.ts +689 -0
  12. package/dist/lib/database-service.d.ts.map +1 -0
  13. package/dist/lib/database-service.js +1362 -0
  14. package/dist/lib/database-service.js.map +1 -0
  15. package/dist/lib/db-types.d.ts +167 -0
  16. package/dist/lib/db-types.d.ts.map +1 -0
  17. package/dist/lib/db-types.js +28 -0
  18. package/dist/lib/db-types.js.map +1 -0
  19. package/dist/lib/db.d.ts +58 -0
  20. package/dist/lib/db.d.ts.map +1 -0
  21. package/dist/lib/db.js +292 -0
  22. package/dist/lib/db.js.map +1 -0
  23. package/dist/lib/index.d.ts +11 -0
  24. package/dist/lib/index.d.ts.map +1 -0
  25. package/dist/lib/index.js +26 -0
  26. package/dist/lib/index.js.map +1 -0
  27. package/dist/lib/pg-client.d.ts +50 -0
  28. package/dist/lib/pg-client.d.ts.map +1 -0
  29. package/dist/lib/pg-client.js +106 -0
  30. package/dist/lib/pg-client.js.map +1 -0
  31. package/dist/lib/schema.d.ts +298 -0
  32. package/dist/lib/schema.d.ts.map +1 -0
  33. package/dist/lib/schema.js +12 -0
  34. package/dist/lib/schema.js.map +1 -0
  35. package/dist/migration-manager.d.ts +49 -0
  36. package/dist/migration-manager.d.ts.map +1 -0
  37. package/dist/migration-manager.js +282 -0
  38. package/dist/migration-manager.js.map +1 -0
  39. package/dist/queries/minimal-connections.d.ts +31 -0
  40. package/dist/queries/minimal-connections.d.ts.map +1 -0
  41. package/dist/queries/minimal-connections.js +143 -0
  42. package/dist/queries/minimal-connections.js.map +1 -0
  43. package/dist/schema.ts +340 -0
  44. package/dist/seed.d.ts +8 -0
  45. package/dist/seed.d.ts.map +1 -0
  46. package/dist/seed.js +40 -0
  47. package/dist/seed.js.map +1 -0
  48. package/dist/types/index.d.ts +7 -0
  49. package/dist/types/index.d.ts.map +1 -0
  50. package/dist/types/index.js +23 -0
  51. package/dist/types/index.js.map +1 -0
  52. package/dist/types/types.d.ts +77 -0
  53. package/dist/types/types.d.ts.map +1 -0
  54. package/dist/types/types.js +3 -0
  55. package/dist/types/types.js.map +1 -0
  56. package/dist/utils/authenticated-user-operations.d.ts +110 -0
  57. package/dist/utils/authenticated-user-operations.d.ts.map +1 -0
  58. package/dist/utils/authenticated-user-operations.js +292 -0
  59. package/dist/utils/authenticated-user-operations.js.map +1 -0
  60. package/dist/utils/authentication-operations.d.ts +48 -0
  61. package/dist/utils/authentication-operations.d.ts.map +1 -0
  62. package/dist/utils/authentication-operations.js +172 -0
  63. package/dist/utils/authentication-operations.js.map +1 -0
  64. package/dist/utils/company-mapping-job-operations.d.ts +103 -0
  65. package/dist/utils/company-mapping-job-operations.d.ts.map +1 -0
  66. package/dist/utils/company-mapping-job-operations.js +413 -0
  67. package/dist/utils/company-mapping-job-operations.js.map +1 -0
  68. package/dist/utils/company-sheet-upload-operations.d.ts +53 -0
  69. package/dist/utils/company-sheet-upload-operations.d.ts.map +1 -0
  70. package/dist/utils/company-sheet-upload-operations.js +135 -0
  71. package/dist/utils/company-sheet-upload-operations.js.map +1 -0
  72. package/dist/utils/contact-operations.d.ts +70 -0
  73. package/dist/utils/contact-operations.d.ts.map +1 -0
  74. package/dist/utils/contact-operations.js +294 -0
  75. package/dist/utils/contact-operations.js.map +1 -0
  76. package/dist/utils/forager-linkedin-operations.d.ts +74 -0
  77. package/dist/utils/forager-linkedin-operations.d.ts.map +1 -0
  78. package/dist/utils/forager-linkedin-operations.js +778 -0
  79. package/dist/utils/forager-linkedin-operations.js.map +1 -0
  80. package/dist/utils/ghost-genius-linkedin-operations.d.ts +23 -0
  81. package/dist/utils/ghost-genius-linkedin-operations.d.ts.map +1 -0
  82. package/dist/utils/ghost-genius-linkedin-operations.js +282 -0
  83. package/dist/utils/ghost-genius-linkedin-operations.js.map +1 -0
  84. package/dist/utils/index.d.ts +29 -0
  85. package/dist/utils/index.d.ts.map +1 -0
  86. package/dist/utils/index.js +77 -0
  87. package/dist/utils/index.js.map +1 -0
  88. package/dist/utils/introduction-request-operations.d.ts +159 -0
  89. package/dist/utils/introduction-request-operations.d.ts.map +1 -0
  90. package/dist/utils/introduction-request-operations.js +481 -0
  91. package/dist/utils/introduction-request-operations.js.map +1 -0
  92. package/dist/utils/invitation-operations.d.ts +141 -0
  93. package/dist/utils/invitation-operations.d.ts.map +1 -0
  94. package/dist/utils/invitation-operations.js +749 -0
  95. package/dist/utils/invitation-operations.js.map +1 -0
  96. package/dist/utils/linkedin-account-operations.d.ts +45 -0
  97. package/dist/utils/linkedin-account-operations.d.ts.map +1 -0
  98. package/dist/utils/linkedin-account-operations.js +279 -0
  99. package/dist/utils/linkedin-account-operations.js.map +1 -0
  100. package/dist/utils/linkedin-account-relationship-operations.d.ts +77 -0
  101. package/dist/utils/linkedin-account-relationship-operations.d.ts.map +1 -0
  102. package/dist/utils/linkedin-account-relationship-operations.js +274 -0
  103. package/dist/utils/linkedin-account-relationship-operations.js.map +1 -0
  104. package/dist/utils/linkedin-data-operations.d.ts +102 -0
  105. package/dist/utils/linkedin-data-operations.d.ts.map +1 -0
  106. package/dist/utils/linkedin-data-operations.js +613 -0
  107. package/dist/utils/linkedin-data-operations.js.map +1 -0
  108. package/dist/utils/linkedin-identifier-utils.d.ts +31 -0
  109. package/dist/utils/linkedin-identifier-utils.d.ts.map +1 -0
  110. package/dist/utils/linkedin-identifier-utils.js +63 -0
  111. package/dist/utils/linkedin-identifier-utils.js.map +1 -0
  112. package/dist/utils/linkedin-profile-cache.d.ts +131 -0
  113. package/dist/utils/linkedin-profile-cache.d.ts.map +1 -0
  114. package/dist/utils/linkedin-profile-cache.js +418 -0
  115. package/dist/utils/linkedin-profile-cache.js.map +1 -0
  116. package/dist/utils/llm-inference-job-operations.d.ts +116 -0
  117. package/dist/utils/llm-inference-job-operations.d.ts.map +1 -0
  118. package/dist/utils/llm-inference-job-operations.js +266 -0
  119. package/dist/utils/llm-inference-job-operations.js.map +1 -0
  120. package/dist/utils/mapping-job-operations.d.ts +272 -0
  121. package/dist/utils/mapping-job-operations.d.ts.map +1 -0
  122. package/dist/utils/mapping-job-operations.js +833 -0
  123. package/dist/utils/mapping-job-operations.js.map +1 -0
  124. package/dist/utils/mapping-operations.d.ts +80 -0
  125. package/dist/utils/mapping-operations.d.ts.map +1 -0
  126. package/dist/utils/mapping-operations.js +318 -0
  127. package/dist/utils/mapping-operations.js.map +1 -0
  128. package/dist/utils/on-demand-mapping-operations.d.ts +199 -0
  129. package/dist/utils/on-demand-mapping-operations.d.ts.map +1 -0
  130. package/dist/utils/on-demand-mapping-operations.js +728 -0
  131. package/dist/utils/on-demand-mapping-operations.js.map +1 -0
  132. package/dist/utils/onboarding-operations.d.ts +53 -0
  133. package/dist/utils/onboarding-operations.d.ts.map +1 -0
  134. package/dist/utils/onboarding-operations.js +223 -0
  135. package/dist/utils/onboarding-operations.js.map +1 -0
  136. package/dist/utils/organization-assignment-job-operations.d.ts +258 -0
  137. package/dist/utils/organization-assignment-job-operations.d.ts.map +1 -0
  138. package/dist/utils/organization-assignment-job-operations.js +881 -0
  139. package/dist/utils/organization-assignment-job-operations.js.map +1 -0
  140. package/dist/utils/organization-assignment-operations.d.ts +59 -0
  141. package/dist/utils/organization-assignment-operations.d.ts.map +1 -0
  142. package/dist/utils/organization-assignment-operations.js +130 -0
  143. package/dist/utils/organization-assignment-operations.js.map +1 -0
  144. package/dist/utils/organization-operations.d.ts +275 -0
  145. package/dist/utils/organization-operations.d.ts.map +1 -0
  146. package/dist/utils/organization-operations.js +993 -0
  147. package/dist/utils/organization-operations.js.map +1 -0
  148. package/dist/utils/organization-relationship-operations.d.ts +59 -0
  149. package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
  150. package/dist/utils/organization-relationship-operations.js +240 -0
  151. package/dist/utils/organization-relationship-operations.js.map +1 -0
  152. package/dist/utils/quota-operations.d.ts +107 -0
  153. package/dist/utils/quota-operations.d.ts.map +1 -0
  154. package/dist/utils/quota-operations.js +692 -0
  155. package/dist/utils/quota-operations.js.map +1 -0
  156. package/dist/utils/recursive-mapping-job-operations.d.ts +42 -0
  157. package/dist/utils/recursive-mapping-job-operations.d.ts.map +1 -0
  158. package/dist/utils/recursive-mapping-job-operations.js +169 -0
  159. package/dist/utils/recursive-mapping-job-operations.js.map +1 -0
  160. package/dist/utils/relationship-operations.d.ts +130 -0
  161. package/dist/utils/relationship-operations.d.ts.map +1 -0
  162. package/dist/utils/relationship-operations.js +329 -0
  163. package/dist/utils/relationship-operations.js.map +1 -0
  164. package/dist/utils/sales-pipeline-operations.d.ts +143 -0
  165. package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
  166. package/dist/utils/sales-pipeline-operations.js +649 -0
  167. package/dist/utils/sales-pipeline-operations.js.map +1 -0
  168. package/dist/utils/skills-operations.d.ts +117 -0
  169. package/dist/utils/skills-operations.d.ts.map +1 -0
  170. package/dist/utils/skills-operations.js +487 -0
  171. package/dist/utils/skills-operations.js.map +1 -0
  172. package/dist/utils/subscription-operations.d.ts +123 -0
  173. package/dist/utils/subscription-operations.d.ts.map +1 -0
  174. package/dist/utils/subscription-operations.js +391 -0
  175. package/dist/utils/subscription-operations.js.map +1 -0
  176. package/dist/utils/unipile-account-operations.d.ts +96 -0
  177. package/dist/utils/unipile-account-operations.d.ts.map +1 -0
  178. package/dist/utils/unipile-account-operations.js +255 -0
  179. package/dist/utils/unipile-account-operations.js.map +1 -0
  180. package/dist/utils/user-industry-operations.d.ts +80 -0
  181. package/dist/utils/user-industry-operations.d.ts.map +1 -0
  182. package/dist/utils/user-industry-operations.js +237 -0
  183. package/dist/utils/user-industry-operations.js.map +1 -0
  184. package/dist/utils/user-operations.d.ts +87 -0
  185. package/dist/utils/user-operations.d.ts.map +1 -0
  186. package/dist/utils/user-operations.js +212 -0
  187. package/dist/utils/user-operations.js.map +1 -0
  188. package/package.json +98 -0
@@ -0,0 +1,881 @@
1
+ "use strict";
2
+ /**
3
+ * Organization Assignment Job Operations
4
+ *
5
+ * This module provides functions for managing organization assignment job lifecycle.
6
+ * These jobs track when the organization_assignments_handler Lambda processes
7
+ * contributor and relationship assignments to organizations.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.createOrganizationAssignmentJob = createOrganizationAssignmentJob;
11
+ exports.completeOrganizationAssignmentJob = completeOrganizationAssignmentJob;
12
+ exports.updateOrganizationAssignmentJobMetadata = updateOrganizationAssignmentJobMetadata;
13
+ exports.getOrganizationAssignmentJobsForMappingJob = getOrganizationAssignmentJobsForMappingJob;
14
+ exports.getOrganizationAssignmentJobsForOrganization = getOrganizationAssignmentJobsForOrganization;
15
+ exports.getPendingOrganizationAssignmentJobs = getPendingOrganizationAssignmentJobs;
16
+ exports.getOrganizationAssignmentJobById = getOrganizationAssignmentJobById;
17
+ exports.getLatestOrganizationAssignmentJob = getLatestOrganizationAssignmentJob;
18
+ exports.getLatestOrganizationAssignmentJobForUser = getLatestOrganizationAssignmentJobForUser;
19
+ exports.checkExportAvailability = checkExportAvailability;
20
+ exports.checkExportAvailabilityForLinkedInAccount = checkExportAvailabilityForLinkedInAccount;
21
+ exports.getUserExports = getUserExports;
22
+ exports.getExportStatusByLinkedInIdentifier = getExportStatusByLinkedInIdentifier;
23
+ exports.validateOrganizationAssignmentJobCompletion = validateOrganizationAssignmentJobCompletion;
24
+ exports.deleteOrganizationAssignmentJob = deleteOrganizationAssignmentJob;
25
+ const pg_client_1 = require("../lib/pg-client");
26
+ const db_1 = require("../lib/db");
27
+ // =============================================================================
28
+ // CREATE OPERATIONS
29
+ // =============================================================================
30
+ /**
31
+ * Create a new organization assignment job record
32
+ * Called when the organization_assignments_handler Lambda starts processing
33
+ *
34
+ * @param db - Database instance
35
+ * @param params - Job parameters
36
+ * @returns The created job record
37
+ */
38
+ async function createOrganizationAssignmentJob(db, params) {
39
+ const { mappingJobId, organizationId, jobMetadata = {} } = params;
40
+ (0, db_1.debugLogDbOperation)("insert", "organization_assignment_jobs", { mappingJobId, organizationId }, undefined, { operation: "createOrganizationAssignmentJob" });
41
+ const sql = `
42
+ INSERT INTO monitoring.organization_assignment_jobs (mapping_job_id, organization_id, metadata, created_at)
43
+ VALUES ($1, $2, $3, NOW())
44
+ RETURNING id, mapping_job_id, organization_id, metadata, created_at, completed_at
45
+ `;
46
+ const job = await (0, pg_client_1.queryOne)(db, sql, [mappingJobId, organizationId, JSON.stringify(jobMetadata)]);
47
+ if (!job) {
48
+ throw new Error("Failed to create organization assignment job");
49
+ }
50
+ return {
51
+ id: job.id,
52
+ mappingJobId: job.mapping_job_id,
53
+ organizationId: job.organization_id,
54
+ metadata: job.metadata,
55
+ createdAt: job.created_at,
56
+ completedAt: job.completed_at,
57
+ };
58
+ }
59
+ // =============================================================================
60
+ // LIFECYCLE MANAGEMENT
61
+ // =============================================================================
62
+ /**
63
+ * Mark an organization assignment job as completed
64
+ * Updates completed_at timestamp and stores final statistics
65
+ *
66
+ * @param db - Database instance
67
+ * @param organizationAssignmentJobId - Job ID
68
+ * @param completionMetadata - Final job statistics
69
+ * @returns Updated job record
70
+ */
71
+ async function completeOrganizationAssignmentJob(db, organizationAssignmentJobId, completionMetadata) {
72
+ (0, db_1.debugLogDbOperation)("update", "organization_assignment_jobs", { organizationAssignmentJobId }, undefined, { operation: "completeOrganizationAssignmentJob" });
73
+ const updates = ["completed_at = NOW()"];
74
+ const params = [organizationAssignmentJobId];
75
+ if (completionMetadata) {
76
+ updates.push("metadata = $2");
77
+ params.push(JSON.stringify(completionMetadata));
78
+ }
79
+ const sql = `
80
+ UPDATE monitoring.organization_assignment_jobs
81
+ SET ${updates.join(", ")}
82
+ WHERE id = $1
83
+ RETURNING id, mapping_job_id, organization_id, metadata, created_at, completed_at
84
+ `;
85
+ const job = await (0, pg_client_1.queryOne)(db, sql, params);
86
+ if (!job) {
87
+ throw new Error(`Organization assignment job ${organizationAssignmentJobId} not found`);
88
+ }
89
+ return {
90
+ id: job.id,
91
+ mappingJobId: job.mapping_job_id,
92
+ organizationId: job.organization_id,
93
+ metadata: job.metadata,
94
+ createdAt: job.created_at,
95
+ completedAt: job.completed_at,
96
+ };
97
+ }
98
+ /**
99
+ * Update job metadata (for incremental statistics during processing)
100
+ *
101
+ * @param db - Database instance
102
+ * @param organizationAssignmentJobId - Job ID
103
+ * @param metadata - Updated metadata
104
+ * @returns Updated job record
105
+ */
106
+ async function updateOrganizationAssignmentJobMetadata(db, organizationAssignmentJobId, metadata) {
107
+ (0, db_1.debugLogDbOperation)("update", "organization_assignment_jobs", { organizationAssignmentJobId }, undefined, { operation: "updateOrganizationAssignmentJobMetadata" });
108
+ const sql = `
109
+ UPDATE monitoring.organization_assignment_jobs
110
+ SET metadata = $1
111
+ WHERE id = $2
112
+ RETURNING id, mapping_job_id, organization_id, metadata, created_at, completed_at
113
+ `;
114
+ const job = await (0, pg_client_1.queryOne)(db, sql, [JSON.stringify(metadata), organizationAssignmentJobId]);
115
+ if (!job) {
116
+ throw new Error(`Organization assignment job ${organizationAssignmentJobId} not found`);
117
+ }
118
+ return {
119
+ id: job.id,
120
+ mappingJobId: job.mapping_job_id,
121
+ organizationId: job.organization_id,
122
+ metadata: job.metadata,
123
+ createdAt: job.created_at,
124
+ completedAt: job.completed_at,
125
+ };
126
+ }
127
+ // =============================================================================
128
+ // QUERY OPERATIONS
129
+ // =============================================================================
130
+ /**
131
+ * Get all organization assignment jobs for a specific mapping job
132
+ *
133
+ * @param db - Database instance
134
+ * @param mappingJobId - Mapping job ID
135
+ * @param options - Query options
136
+ * @returns Array of organization assignment jobs
137
+ */
138
+ async function getOrganizationAssignmentJobsForMappingJob(db, mappingJobId, options = {}) {
139
+ const { limit = 100, onlyCompleted = false } = options;
140
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { mappingJobId, limit, onlyCompleted }, undefined, { operation: "getOrganizationAssignmentJobsForMappingJob" });
141
+ const whereClause = onlyCompleted
142
+ ? "WHERE mapping_job_id = $1 AND completed_at IS NOT NULL"
143
+ : "WHERE mapping_job_id = $1";
144
+ const sql = `
145
+ SELECT id, mapping_job_id, organization_id, metadata, created_at, completed_at
146
+ FROM monitoring.organization_assignment_jobs
147
+ ${whereClause}
148
+ ORDER BY created_at DESC
149
+ LIMIT $2
150
+ `;
151
+ const results = await (0, pg_client_1.query)(db, sql, [mappingJobId, limit]);
152
+ return results.map(r => ({
153
+ id: r.id,
154
+ mappingJobId: r.mapping_job_id,
155
+ organizationId: r.organization_id,
156
+ metadata: r.metadata,
157
+ createdAt: r.created_at,
158
+ completedAt: r.completed_at,
159
+ }));
160
+ }
161
+ /**
162
+ * Get all organization assignment jobs for a specific organization
163
+ *
164
+ * @param db - Database instance
165
+ * @param organizationId - Organization ID
166
+ * @param options - Query options
167
+ * @returns Array of organization assignment jobs
168
+ */
169
+ async function getOrganizationAssignmentJobsForOrganization(db, organizationId, options = {}) {
170
+ const { limit = 100, onlyCompleted = false } = options;
171
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { organizationId, limit, onlyCompleted }, undefined, { operation: "getOrganizationAssignmentJobsForOrganization" });
172
+ const whereClause = onlyCompleted
173
+ ? "WHERE organization_id = $1 AND completed_at IS NOT NULL"
174
+ : "WHERE organization_id = $1";
175
+ const sql = `
176
+ SELECT id, mapping_job_id, organization_id, metadata, created_at, completed_at
177
+ FROM monitoring.organization_assignment_jobs
178
+ ${whereClause}
179
+ ORDER BY created_at DESC
180
+ LIMIT $2
181
+ `;
182
+ const results = await (0, pg_client_1.query)(db, sql, [organizationId, limit]);
183
+ return results.map(r => ({
184
+ id: r.id,
185
+ mappingJobId: r.mapping_job_id,
186
+ organizationId: r.organization_id,
187
+ metadata: r.metadata,
188
+ createdAt: r.created_at,
189
+ completedAt: r.completed_at,
190
+ }));
191
+ }
192
+ /**
193
+ * Get pending organization assignment jobs (not completed)
194
+ *
195
+ * @param db - Database instance
196
+ * @param options - Query options
197
+ * @returns Array of pending jobs
198
+ */
199
+ async function getPendingOrganizationAssignmentJobs(db, options = {}) {
200
+ const { limit = 100 } = options;
201
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { limit }, undefined, {
202
+ operation: "getPendingOrganizationAssignmentJobs",
203
+ });
204
+ const sql = `
205
+ SELECT id, mapping_job_id, organization_id, metadata, created_at, completed_at
206
+ FROM monitoring.organization_assignment_jobs
207
+ WHERE completed_at IS NULL
208
+ ORDER BY created_at DESC
209
+ LIMIT $1
210
+ `;
211
+ const results = await (0, pg_client_1.query)(db, sql, [limit]);
212
+ return results.map(r => ({
213
+ id: r.id,
214
+ mappingJobId: r.mapping_job_id,
215
+ organizationId: r.organization_id,
216
+ metadata: r.metadata,
217
+ createdAt: r.created_at,
218
+ completedAt: r.completed_at,
219
+ }));
220
+ }
221
+ /**
222
+ * Get a specific organization assignment job by ID
223
+ *
224
+ * @param db - Database instance
225
+ * @param organizationAssignmentJobId - Job ID
226
+ * @returns Job record or null if not found
227
+ */
228
+ async function getOrganizationAssignmentJobById(db, organizationAssignmentJobId) {
229
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { organizationAssignmentJobId }, undefined, { operation: "getOrganizationAssignmentJobById" });
230
+ const sql = `
231
+ SELECT id, mapping_job_id, organization_id, metadata, created_at, completed_at
232
+ FROM monitoring.organization_assignment_jobs
233
+ WHERE id = $1
234
+ LIMIT 1
235
+ `;
236
+ const job = await (0, pg_client_1.queryOne)(db, sql, [organizationAssignmentJobId]);
237
+ if (!job)
238
+ return null;
239
+ return {
240
+ id: job.id,
241
+ mappingJobId: job.mapping_job_id,
242
+ organizationId: job.organization_id,
243
+ metadata: job.metadata,
244
+ createdAt: job.created_at,
245
+ completedAt: job.completed_at,
246
+ };
247
+ }
248
+ /**
249
+ * Get the latest organization assignment job for a specific organization and mapping job
250
+ *
251
+ * @param db - Database instance
252
+ * @param mappingJobId - Mapping job ID
253
+ * @param organizationId - Organization ID
254
+ * @returns Latest job record or null if not found
255
+ */
256
+ async function getLatestOrganizationAssignmentJob(db, mappingJobId, organizationId) {
257
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { mappingJobId, organizationId }, undefined, { operation: "getLatestOrganizationAssignmentJob" });
258
+ const sql = `
259
+ SELECT id, mapping_job_id, organization_id, metadata, created_at, started_at, completed_at
260
+ FROM monitoring.organization_assignment_jobs
261
+ WHERE mapping_job_id = $1 AND organization_id = $2
262
+ ORDER BY created_at DESC
263
+ LIMIT 1
264
+ `;
265
+ const job = await (0, pg_client_1.queryOne)(db, sql, [mappingJobId, organizationId]);
266
+ if (!job)
267
+ return null;
268
+ return {
269
+ id: job.id,
270
+ mappingJobId: job.mapping_job_id,
271
+ organizationId: job.organization_id,
272
+ metadata: job.metadata,
273
+ createdAt: job.created_at,
274
+ completedAt: job.completed_at,
275
+ };
276
+ }
277
+ /**
278
+ * Get the latest organization assignment job for a user in an organization
279
+ *
280
+ * Finds the most recent organization assignment job for a user by joining
281
+ * through mapping_jobs and linkedin_accounts to find the user's mapping job.
282
+ *
283
+ * @param db - Database instance
284
+ * @param userId - User ID
285
+ * @param organizationId - Organization ID
286
+ * @returns Latest organization assignment job or null if not found
287
+ */
288
+ async function getLatestOrganizationAssignmentJobForUser(db, userId, organizationId) {
289
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { userId, organizationId }, undefined, { operation: "getLatestOrganizationAssignmentJobForUser" });
290
+ const sql = `
291
+ SELECT
292
+ oaj.id,
293
+ oaj.mapping_job_id,
294
+ oaj.organization_id,
295
+ oaj.metadata,
296
+ oaj.created_at,
297
+ oaj.completed_at
298
+ FROM monitoring.organization_assignment_jobs oaj
299
+ INNER JOIN monitoring.mapping_jobs mj ON mj.id = oaj.mapping_job_id
300
+ INNER JOIN linkedin.accounts la ON la.id = mj.linkedin_account_id
301
+ WHERE la.user_id = $1 AND oaj.organization_id = $2
302
+ ORDER BY oaj.created_at DESC
303
+ LIMIT 1
304
+ `;
305
+ const job = await (0, pg_client_1.queryOne)(db, sql, [userId, organizationId]);
306
+ if (!job)
307
+ return null;
308
+ return {
309
+ id: job.id,
310
+ mappingJobId: job.mapping_job_id,
311
+ organizationId: job.organization_id,
312
+ metadata: job.metadata,
313
+ createdAt: job.created_at,
314
+ completedAt: job.completed_at,
315
+ };
316
+ }
317
+ async function checkExportAvailability(db, mappingJobId, organizationId) {
318
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { mappingJobId, organizationId }, undefined, { operation: "checkExportAvailability" });
319
+ // If mapping job is not completed, export is not available
320
+ if (!mappingJobId) {
321
+ // Get organization name
322
+ const orgSql = `
323
+ SELECT name
324
+ FROM public.organizations
325
+ WHERE id = $1
326
+ `;
327
+ const org = await (0, pg_client_1.queryOne)(db, orgSql, [
328
+ organizationId,
329
+ ]).catch(() => null);
330
+ return {
331
+ can_export: false,
332
+ is_exported: false,
333
+ export_status: "not_available",
334
+ organization_id: organizationId,
335
+ organization_name: org?.name || null,
336
+ on_demand_mapping_job_id: null,
337
+ };
338
+ }
339
+ try {
340
+ // Get organization name
341
+ const orgSql = `
342
+ SELECT name
343
+ FROM public.organizations
344
+ WHERE id = $1
345
+ `;
346
+ const org = await (0, pg_client_1.queryOne)(db, orgSql, [
347
+ organizationId,
348
+ ]).catch(() => null);
349
+ const organizationName = org?.name || null;
350
+ const sql = `
351
+ SELECT
352
+ oaj.id,
353
+ oaj.created_at,
354
+ oaj.started_at,
355
+ oaj.completed_at
356
+ FROM monitoring.organization_assignment_jobs oaj
357
+ WHERE oaj.mapping_job_id = $1
358
+ AND oaj.organization_id = $2
359
+ ORDER BY oaj.created_at DESC
360
+ LIMIT 1
361
+ `;
362
+ const exportJob = await (0, pg_client_1.queryOne)(db, sql, [mappingJobId, organizationId]);
363
+ if (exportJob) {
364
+ // Already exported or in progress
365
+ const orgAssignmentJobDetails = {
366
+ id: exportJob.id,
367
+ created_at: exportJob.created_at,
368
+ started_at: exportJob.started_at,
369
+ completed_at: exportJob.completed_at,
370
+ };
371
+ // Find the on-demand mapping job for this mapping job
372
+ const onDemandJobSql = `
373
+ SELECT odmj.id
374
+ FROM monitoring.on_demand_mapping_jobs odmj
375
+ WHERE odmj.mapping_job_id = $1
376
+ ORDER BY odmj.created_at DESC
377
+ LIMIT 1
378
+ `;
379
+ const onDemandJob = await (0, pg_client_1.queryOne)(db, onDemandJobSql, [
380
+ mappingJobId,
381
+ ]).catch(() => null);
382
+ if (exportJob.completed_at) {
383
+ return {
384
+ can_export: false,
385
+ is_exported: true,
386
+ export_status: "exported",
387
+ organization_id: organizationId,
388
+ organization_name: organizationName,
389
+ on_demand_mapping_job_id: onDemandJob?.id || null,
390
+ org_assignment_job: orgAssignmentJobDetails,
391
+ };
392
+ }
393
+ else {
394
+ // In progress (started or queued)
395
+ return {
396
+ can_export: false,
397
+ is_exported: false,
398
+ export_status: "exporting",
399
+ organization_id: organizationId,
400
+ organization_name: organizationName,
401
+ on_demand_mapping_job_id: onDemandJob?.id || null,
402
+ org_assignment_job: orgAssignmentJobDetails,
403
+ };
404
+ }
405
+ }
406
+ else {
407
+ // Not exported yet, can export
408
+ // Find the on-demand mapping job for this mapping job
409
+ const onDemandJobSql = `
410
+ SELECT odmj.id
411
+ FROM monitoring.on_demand_mapping_jobs odmj
412
+ WHERE odmj.mapping_job_id = $1
413
+ ORDER BY odmj.created_at DESC
414
+ LIMIT 1
415
+ `;
416
+ const onDemandJob = await (0, pg_client_1.queryOne)(db, onDemandJobSql, [
417
+ mappingJobId,
418
+ ]).catch(() => null);
419
+ // Get LinkedIn identifier (ACoA) for direct export if no on-demand job exists
420
+ let linkedinIdentifierAcoa = null;
421
+ if (!onDemandJob) {
422
+ const linkedinAccountSql = `
423
+ SELECT la.linkedin_identifier_acoa
424
+ FROM linkedin.accounts la
425
+ INNER JOIN monitoring.mapping_jobs mj ON la.id = mj.linkedin_account_id
426
+ WHERE mj.id = $1
427
+ LIMIT 1
428
+ `;
429
+ const linkedinAccount = await (0, pg_client_1.queryOne)(db, linkedinAccountSql, [mappingJobId]).catch(() => null);
430
+ linkedinIdentifierAcoa = linkedinAccount?.linkedin_identifier_acoa || null;
431
+ }
432
+ return {
433
+ can_export: true,
434
+ is_exported: false,
435
+ export_status: "not_exported",
436
+ organization_id: organizationId,
437
+ organization_name: organizationName,
438
+ on_demand_mapping_job_id: onDemandJob?.id || null,
439
+ mapping_job_id: mappingJobId, // Always include mapping job ID
440
+ linkedin_identifier_acoa: linkedinIdentifierAcoa, // Include ACoA for direct export
441
+ org_assignment_job: null,
442
+ };
443
+ }
444
+ }
445
+ catch (error) {
446
+ console.error("Error checking export availability:", error);
447
+ // On error, assume not available
448
+ return {
449
+ can_export: false,
450
+ is_exported: false,
451
+ export_status: "not_available",
452
+ organization_id: organizationId,
453
+ organization_name: null,
454
+ org_assignment_job: null,
455
+ };
456
+ }
457
+ }
458
+ /**
459
+ * Check export availability for a LinkedIn account to a specific organization
460
+ * This checks ALL mapping jobs for the account, not just the latest one
461
+ *
462
+ * @param db - Database instance
463
+ * @param linkedinAccountId - LinkedIn account ID
464
+ * @param organizationId - Organization ID to check
465
+ * @returns Export availability information
466
+ */
467
+ async function checkExportAvailabilityForLinkedInAccount(db, linkedinAccountId, organizationId) {
468
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs + mapping_jobs", { linkedinAccountId, organizationId }, undefined, { operation: "checkExportAvailabilityForLinkedInAccount" });
469
+ try {
470
+ // First, get the organization name
471
+ const orgSql = `
472
+ SELECT name
473
+ FROM public.organizations
474
+ WHERE id = $1
475
+ `;
476
+ const org = await (0, pg_client_1.queryOne)(db, orgSql, [organizationId]);
477
+ const organizationName = org?.name || null;
478
+ // Check if there's an organization assignment job for ANY mapping job
479
+ // of this LinkedIn account for this organization
480
+ const sql = `
481
+ SELECT
482
+ oaj.id,
483
+ oaj.created_at,
484
+ oaj.started_at,
485
+ oaj.completed_at,
486
+ oaj.mapping_job_id
487
+ FROM monitoring.organization_assignment_jobs oaj
488
+ INNER JOIN monitoring.mapping_jobs mj ON oaj.mapping_job_id = mj.id
489
+ WHERE mj.linkedin_account_id = $1
490
+ AND oaj.organization_id = $2
491
+ ORDER BY oaj.created_at DESC
492
+ LIMIT 1
493
+ `;
494
+ const exportJob = await (0, pg_client_1.queryOne)(db, sql, [linkedinAccountId, organizationId]);
495
+ if (exportJob) {
496
+ // Already exported or in progress
497
+ const orgAssignmentJobDetails = {
498
+ id: exportJob.id,
499
+ created_at: exportJob.created_at,
500
+ started_at: exportJob.started_at,
501
+ completed_at: exportJob.completed_at,
502
+ };
503
+ if (exportJob.completed_at) {
504
+ return {
505
+ can_export: false,
506
+ is_exported: true,
507
+ export_status: "exported",
508
+ organization_id: organizationId,
509
+ organization_name: organizationName,
510
+ org_assignment_job: orgAssignmentJobDetails,
511
+ };
512
+ }
513
+ else {
514
+ // In progress (started or queued)
515
+ return {
516
+ can_export: false,
517
+ is_exported: false,
518
+ export_status: "exporting",
519
+ organization_id: organizationId,
520
+ organization_name: organizationName,
521
+ org_assignment_job: orgAssignmentJobDetails,
522
+ };
523
+ }
524
+ }
525
+ else {
526
+ // Check if there's a completed mapping job for this account
527
+ // If yes, export is available. If no, export is not available.
528
+ const completedJobSql = `
529
+ SELECT id
530
+ FROM monitoring.mapping_jobs
531
+ WHERE linkedin_account_id = $1
532
+ AND completed_at IS NOT NULL
533
+ ORDER BY completed_at DESC
534
+ LIMIT 1
535
+ `;
536
+ const completedJob = await (0, pg_client_1.queryOne)(db, completedJobSql, [linkedinAccountId]);
537
+ if (completedJob) {
538
+ // Not exported yet, but mapping is complete - can export
539
+ // Find the on-demand mapping job for this completed mapping job
540
+ const onDemandJobSql = `
541
+ SELECT odmj.id
542
+ FROM monitoring.on_demand_mapping_jobs odmj
543
+ WHERE odmj.mapping_job_id = $1
544
+ ORDER BY odmj.created_at DESC
545
+ LIMIT 1
546
+ `;
547
+ const onDemandJob = await (0, pg_client_1.queryOne)(db, onDemandJobSql, [completedJob.id]).catch(() => null);
548
+ // Get LinkedIn identifier (ACoA) for direct export if no on-demand job exists
549
+ let linkedinIdentifierAcoa = null;
550
+ if (!onDemandJob) {
551
+ const linkedinAccountSql = `
552
+ SELECT la.linkedin_identifier_acoa
553
+ FROM linkedin.accounts la
554
+ WHERE la.id = $1
555
+ LIMIT 1
556
+ `;
557
+ const linkedinAccount = await (0, pg_client_1.queryOne)(db, linkedinAccountSql, [linkedinAccountId]).catch(() => null);
558
+ linkedinIdentifierAcoa = linkedinAccount?.linkedin_identifier_acoa || null;
559
+ }
560
+ return {
561
+ can_export: true,
562
+ is_exported: false,
563
+ export_status: "not_exported",
564
+ organization_id: organizationId,
565
+ organization_name: organizationName,
566
+ on_demand_mapping_job_id: onDemandJob?.id || null,
567
+ mapping_job_id: completedJob.id, // Always include mapping job ID
568
+ linkedin_identifier_acoa: linkedinIdentifierAcoa, // Include ACoA for direct export
569
+ org_assignment_job: null,
570
+ };
571
+ }
572
+ else {
573
+ // No completed mapping job - export not available
574
+ return {
575
+ can_export: false,
576
+ is_exported: false,
577
+ export_status: "not_available",
578
+ organization_id: organizationId,
579
+ organization_name: organizationName,
580
+ on_demand_mapping_job_id: null,
581
+ org_assignment_job: null,
582
+ };
583
+ }
584
+ }
585
+ }
586
+ catch (error) {
587
+ console.error("Error checking export availability for LinkedIn account:", error);
588
+ // On error, assume not available
589
+ return {
590
+ can_export: false,
591
+ is_exported: false,
592
+ export_status: "not_available",
593
+ organization_id: organizationId,
594
+ organization_name: null,
595
+ org_assignment_job: null,
596
+ };
597
+ }
598
+ }
599
+ async function getUserExports(db, requesterLinkedinAccountId, options = {}) {
600
+ const { page = 1, pageSize = 10, sort = "desc", organizationId, status = "all" } = options;
601
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs + mapping_jobs + on_demand_mapping_jobs", {
602
+ requesterLinkedinAccountId,
603
+ page,
604
+ pageSize,
605
+ sort,
606
+ organizationId,
607
+ status,
608
+ }, undefined, { operation: "getUserExports" });
609
+ // Validate pagination
610
+ const limit = Math.min(Math.max(1, pageSize), 50); // Max 50 per page
611
+ const offset = (Math.max(1, page) - 1) * limit;
612
+ const orderBy = sort === "asc" ? "ASC" : "DESC";
613
+ // Build WHERE clause for status filter
614
+ let statusFilter = "";
615
+ if (status === "completed") {
616
+ statusFilter = "AND oaj.completed_at IS NOT NULL";
617
+ }
618
+ else if (status === "pending") {
619
+ statusFilter = "AND oaj.completed_at IS NULL AND oaj.started_at IS NOT NULL";
620
+ }
621
+ else if (status === "failed") {
622
+ // Failed status would need to be tracked in metadata or a separate field
623
+ // For now, we'll treat it as pending if not completed
624
+ statusFilter = "AND oaj.completed_at IS NULL";
625
+ }
626
+ // Build WHERE clause for organization filter
627
+ // If organizationId is provided, return all exports for that organization
628
+ // Otherwise, return only exports where the user is the requester
629
+ let orgFilter = "";
630
+ let requesterFilter = "";
631
+ let paramIndex = 1;
632
+ const countParams = [];
633
+ if (organizationId) {
634
+ // When organizationId is provided, return all exports for that organization
635
+ // (all members should see all exports to their organization)
636
+ orgFilter = `oaj.organization_id = $${paramIndex}`;
637
+ countParams.push(organizationId);
638
+ paramIndex++;
639
+ }
640
+ else {
641
+ // When organizationId is NOT provided, filter by requester (backward compatibility)
642
+ requesterFilter = `odmj.requester_linkedin_account_id = $${paramIndex}`;
643
+ countParams.push(requesterLinkedinAccountId);
644
+ paramIndex++;
645
+ }
646
+ const whereClause = [orgFilter, requesterFilter].filter(Boolean).join(" AND ");
647
+ const countSql = `
648
+ SELECT COUNT(DISTINCT oaj.id) as total
649
+ FROM monitoring.organization_assignment_jobs oaj
650
+ INNER JOIN monitoring.mapping_jobs mj ON oaj.mapping_job_id = mj.id
651
+ LEFT JOIN monitoring.on_demand_mapping_jobs odmj ON mj.id = odmj.mapping_job_id
652
+ WHERE ${whereClause}
653
+ ${statusFilter}
654
+ `;
655
+ const totalResult = await (0, pg_client_1.queryOne)(db, countSql, countParams);
656
+ const totalItems = totalResult?.total || 0;
657
+ const totalPages = Math.ceil(totalItems / limit);
658
+ // Get paginated exports with full details
659
+ // Note: current_company comes from work_experience table (most recent current position)
660
+ const sql = `
661
+ SELECT
662
+ oaj.id,
663
+ oaj.created_at,
664
+ oaj.started_at,
665
+ oaj.completed_at,
666
+ oaj.mapping_job_id,
667
+ oaj.organization_id,
668
+ o.name as organization_name,
669
+ o.workspace_type,
670
+ CONCAT(COALESCE(la.first_name, ''), ' ', COALESCE(la.last_name, '')) as profile_name,
671
+ la.headline as profile_position,
672
+ we.company as current_company,
673
+ COALESCE(la.profile_image_cloudfront_url, la.profile_picture_url) as profile_image_url,
674
+ la.linkedin_identifier_acoa as linkedin_identifier,
675
+ CASE
676
+ WHEN la.public_identifier IS NOT NULL
677
+ THEN CONCAT('https://www.linkedin.com/in/', la.public_identifier)
678
+ ELSE NULL
679
+ END as linkedin_url
680
+ FROM monitoring.organization_assignment_jobs oaj
681
+ INNER JOIN monitoring.mapping_jobs mj ON oaj.mapping_job_id = mj.id
682
+ LEFT JOIN monitoring.on_demand_mapping_jobs odmj ON mj.id = odmj.mapping_job_id
683
+ INNER JOIN linkedin.accounts la ON mj.linkedin_account_id = la.id
684
+ INNER JOIN public.organizations o ON oaj.organization_id = o.id
685
+ LEFT JOIN LATERAL (
686
+ SELECT company
687
+ FROM linkedin.work_experience we
688
+ WHERE we.linkedin_account_id = la.id
689
+ AND we.is_current = true
690
+ ORDER BY we.start_date DESC NULLS LAST
691
+ LIMIT 1
692
+ ) we ON true
693
+ WHERE ${whereClause}
694
+ ${statusFilter}
695
+ ORDER BY oaj.created_at ${orderBy}
696
+ LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
697
+ `;
698
+ const queryParams = [...countParams, limit, offset];
699
+ const results = await (0, pg_client_1.query)(db, sql, queryParams);
700
+ const exports = results.map(r => {
701
+ // Determine status based on completion
702
+ let exportStatus = "pending";
703
+ if (r.completed_at) {
704
+ exportStatus = "completed";
705
+ }
706
+ else if (r.started_at) {
707
+ exportStatus = "pending";
708
+ }
709
+ return {
710
+ id: r.id,
711
+ status: exportStatus,
712
+ created_at: r.created_at,
713
+ started_at: r.started_at,
714
+ completed_at: r.completed_at,
715
+ mapping_job_id: r.mapping_job_id,
716
+ organization: {
717
+ id: r.organization_id,
718
+ name: r.organization_name,
719
+ workspace_type: r.workspace_type,
720
+ },
721
+ profile: {
722
+ name: r.profile_name,
723
+ position: r.profile_position,
724
+ current_company: r.current_company,
725
+ profile_image_url: r.profile_image_url,
726
+ linkedin_identifier: r.linkedin_identifier,
727
+ linkedin_url: r.linkedin_url,
728
+ },
729
+ };
730
+ });
731
+ return {
732
+ exports,
733
+ pagination: {
734
+ page,
735
+ pageSize: limit,
736
+ totalItems,
737
+ totalPages,
738
+ },
739
+ };
740
+ }
741
+ /**
742
+ * Get export status for a specific LinkedIn identifier (ACoA) in an organization
743
+ * Returns full export details including profile and organization information
744
+ *
745
+ * @param db - Database instance
746
+ * @param linkedinIdentifierAcoa - LinkedIn ACoA identifier
747
+ * @param organizationId - Organization ID
748
+ * @returns Export status result
749
+ */
750
+ async function getExportStatusByLinkedInIdentifier(db, linkedinIdentifierAcoa, organizationId) {
751
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs + mapping_jobs + linkedin.accounts", { linkedinIdentifierAcoa, organizationId }, undefined, { operation: "getExportStatusByLinkedInIdentifier" });
752
+ try {
753
+ // Single query to get all export details
754
+ const sql = `
755
+ SELECT
756
+ oaj.id,
757
+ oaj.created_at,
758
+ oaj.started_at,
759
+ oaj.completed_at,
760
+ oaj.mapping_job_id,
761
+ oaj.organization_id,
762
+ o.name as organization_name,
763
+ o.workspace_type,
764
+ CONCAT(COALESCE(la.first_name, ''), ' ', COALESCE(la.last_name, '')) as profile_name,
765
+ la.headline as profile_position,
766
+ we.company as current_company,
767
+ COALESCE(la.profile_image_cloudfront_url, la.profile_picture_url) as profile_image_url,
768
+ la.linkedin_identifier_acoa as linkedin_identifier,
769
+ CASE
770
+ WHEN la.public_identifier IS NOT NULL
771
+ THEN CONCAT('https://www.linkedin.com/in/', la.public_identifier)
772
+ ELSE NULL
773
+ END as linkedin_url
774
+ FROM monitoring.organization_assignment_jobs oaj
775
+ INNER JOIN monitoring.mapping_jobs mj ON oaj.mapping_job_id = mj.id
776
+ INNER JOIN linkedin.accounts la ON mj.linkedin_account_id = la.id
777
+ INNER JOIN public.organizations o ON oaj.organization_id = o.id
778
+ LEFT JOIN LATERAL (
779
+ SELECT company
780
+ FROM linkedin.work_experience we
781
+ WHERE we.linkedin_account_id = la.id
782
+ AND we.is_current = true
783
+ ORDER BY we.start_date DESC NULLS LAST
784
+ LIMIT 1
785
+ ) we ON true
786
+ WHERE la.linkedin_identifier_acoa = $1
787
+ AND oaj.organization_id = $2
788
+ ORDER BY oaj.created_at DESC
789
+ LIMIT 1
790
+ `;
791
+ const result = await (0, pg_client_1.queryOne)(db, sql, [linkedinIdentifierAcoa, organizationId]);
792
+ if (!result) {
793
+ return {
794
+ found: false,
795
+ };
796
+ }
797
+ // Determine status
798
+ let exportStatus = "pending";
799
+ if (result.completed_at) {
800
+ exportStatus = "completed";
801
+ }
802
+ else if (result.started_at) {
803
+ exportStatus = "pending";
804
+ }
805
+ return {
806
+ found: true,
807
+ export: {
808
+ id: result.id,
809
+ status: exportStatus,
810
+ created_at: result.created_at,
811
+ started_at: result.started_at,
812
+ completed_at: result.completed_at,
813
+ mapping_job_id: result.mapping_job_id,
814
+ organization: {
815
+ id: result.organization_id,
816
+ name: result.organization_name,
817
+ workspace_type: result.workspace_type,
818
+ },
819
+ profile: {
820
+ name: result.profile_name || "Unknown",
821
+ position: result.profile_position || null,
822
+ current_company: result.current_company || null,
823
+ profile_image_url: result.profile_image_url || null,
824
+ linkedin_identifier: result.linkedin_identifier,
825
+ linkedin_url: result.linkedin_url || null,
826
+ },
827
+ },
828
+ };
829
+ }
830
+ catch (error) {
831
+ console.error("Error getting export status by LinkedIn identifier:", error);
832
+ throw error;
833
+ }
834
+ }
835
+ // =============================================================================
836
+ // VALIDATION & MANAGEMENT
837
+ // =============================================================================
838
+ /**
839
+ * Validate that an organization assignment job exists and is completed
840
+ *
841
+ * @param db - Database instance
842
+ * @param organizationAssignmentJobId - Job ID
843
+ * @returns True if valid and completed, false otherwise
844
+ */
845
+ async function validateOrganizationAssignmentJobCompletion(db, organizationAssignmentJobId) {
846
+ (0, db_1.debugLogDbOperation)("select", "organization_assignment_jobs", { organizationAssignmentJobId }, undefined, { operation: "validateOrganizationAssignmentJobCompletion" });
847
+ const job = await getOrganizationAssignmentJobById(db, organizationAssignmentJobId);
848
+ if (!job) {
849
+ return false;
850
+ }
851
+ return job.completedAt !== null;
852
+ }
853
+ /**
854
+ * Delete an organization assignment job
855
+ * Use with caution - this will cascade delete related records
856
+ *
857
+ * @param db - Database instance
858
+ * @param organizationAssignmentJobId - Job ID
859
+ * @returns Deleted job record
860
+ */
861
+ async function deleteOrganizationAssignmentJob(db, organizationAssignmentJobId) {
862
+ (0, db_1.debugLogDbOperation)("delete", "organization_assignment_jobs", { organizationAssignmentJobId }, undefined, { operation: "deleteOrganizationAssignmentJob" });
863
+ const sql = `
864
+ DELETE FROM monitoring.organization_assignment_jobs
865
+ WHERE id = $1
866
+ RETURNING id, mapping_job_id, organization_id, metadata, created_at, completed_at
867
+ `;
868
+ const deleted = await (0, pg_client_1.queryOne)(db, sql, [organizationAssignmentJobId]);
869
+ if (!deleted) {
870
+ throw new Error(`Organization assignment job ${organizationAssignmentJobId} not found`);
871
+ }
872
+ return {
873
+ id: deleted.id,
874
+ mappingJobId: deleted.mapping_job_id,
875
+ organizationId: deleted.organization_id,
876
+ metadata: deleted.metadata,
877
+ createdAt: deleted.created_at,
878
+ completedAt: deleted.completed_at,
879
+ };
880
+ }
881
+ //# sourceMappingURL=organization-assignment-job-operations.js.map