eggi-ai-db-schema-2 0.1.1

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 +660 -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 +714 -0
  12. package/dist/lib/database-service.d.ts.map +1 -0
  13. package/dist/lib/database-service.js +1394 -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 +160 -0
  89. package/dist/utils/introduction-request-operations.d.ts.map +1 -0
  90. package/dist/utils/introduction-request-operations.js +492 -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 +267 -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 +284 -0
  145. package/dist/utils/organization-operations.d.ts.map +1 -0
  146. package/dist/utils/organization-operations.js +1030 -0
  147. package/dist/utils/organization-operations.js.map +1 -0
  148. package/dist/utils/organization-relationship-operations.d.ts +79 -0
  149. package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
  150. package/dist/utils/organization-relationship-operations.js +294 -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 +163 -0
  165. package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
  166. package/dist/utils/sales-pipeline-operations.js +725 -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,725 @@
1
+ "use strict";
2
+ /**
3
+ * Sales Pipeline Operations
4
+ *
5
+ * Database operations for sales pipelines and user assignments.
6
+ * Organization-scoped pipelines shared by all users in the organization.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createOrGetSalesPipeline = createOrGetSalesPipeline;
10
+ exports.getOrCreateOrganizationRelationshipAssignment = getOrCreateOrganizationRelationshipAssignment;
11
+ exports.createOrUpdateSalesPipelineAssignment = createOrUpdateSalesPipelineAssignment;
12
+ exports.getSalesPipelineAssignmentWithValidation = getSalesPipelineAssignmentWithValidation;
13
+ exports.addToSalesPipeline = addToSalesPipeline;
14
+ exports.addToSalesPipelineByAssignmentId = addToSalesPipelineByAssignmentId;
15
+ exports.getSalesPipelineById = getSalesPipelineById;
16
+ exports.getSalesPipelineForOrganization = getSalesPipelineForOrganization;
17
+ exports.updateSalesPipelineAssignmentStage = updateSalesPipelineAssignmentStage;
18
+ const pg_client_1 = require("../lib/pg-client");
19
+ const db_1 = require("../lib/db");
20
+ /**
21
+ * Create or get a sales pipeline entry for an organization
22
+ * Checks for existing entry via organization_user_relationship_assignment_id
23
+ * If the pipeline entry already exists, returns the existing one
24
+ *
25
+ * @param db - Database instance
26
+ * @param organizationId - Organization ID
27
+ * @param organizationUserRelationshipAssignmentId - Organization relationship assignment ID
28
+ * @param addedByOrganizationMemberId - Organization member who added this to the pipeline
29
+ * @returns Sales pipeline entry
30
+ */
31
+ async function createOrGetSalesPipeline(db, organizationId, organizationUserRelationshipAssignmentId, addedByOrganizationMemberId // Mandatory - must be provided
32
+ ) {
33
+ (0, db_1.debugLogDbOperation)("createOrGetSalesPipeline", "sales_pipelines", {
34
+ organizationId,
35
+ organizationUserRelationshipAssignmentId,
36
+ addedByOrganizationMemberId,
37
+ });
38
+ // Try to get existing pipeline entry via assignment
39
+ const existingSql = `
40
+ SELECT sp.id, sp.organization_id, sp.added_by_organization_member_id, sp.created_at
41
+ FROM public.sales_pipelines sp
42
+ INNER JOIN public.sales_pipeline_assignments spa ON spa.sales_pipeline_id = sp.id
43
+ WHERE sp.organization_id = $1
44
+ AND spa.organization_user_relationship_assignment_id = $2
45
+ LIMIT 1
46
+ `;
47
+ const existing = await (0, pg_client_1.queryOne)(db, existingSql, [
48
+ organizationId,
49
+ organizationUserRelationshipAssignmentId,
50
+ ]);
51
+ if (existing) {
52
+ return {
53
+ id: existing.id,
54
+ organizationId: existing.organization_id,
55
+ addedByOrganizationMemberId: existing.added_by_organization_member_id,
56
+ createdAt: existing.created_at,
57
+ };
58
+ }
59
+ // Create new pipeline entry
60
+ const insertSql = `
61
+ INSERT INTO public.sales_pipelines (organization_id, added_by_organization_member_id)
62
+ VALUES ($1, $2)
63
+ RETURNING id, organization_id, added_by_organization_member_id, created_at
64
+ `;
65
+ const result = await (0, pg_client_1.queryOne)(db, insertSql, [organizationId, addedByOrganizationMemberId]);
66
+ if (!result) {
67
+ throw new Error("Failed to create sales pipeline entry");
68
+ }
69
+ return {
70
+ id: result.id,
71
+ organizationId: result.organization_id,
72
+ addedByOrganizationMemberId: result.added_by_organization_member_id,
73
+ createdAt: result.created_at,
74
+ };
75
+ }
76
+ /**
77
+ * Get or create an organization_user_relationships_assignments entry
78
+ *
79
+ * @param db - Database instance
80
+ * @param organizationId - Organization ID
81
+ * @param linkedinRelationshipId - LinkedIn relationship ID
82
+ * @param organizationMemberId - Organization member ID (the member whose LinkedIn account is part of the relationship)
83
+ * @returns Organization relationship assignment ID
84
+ */
85
+ async function getOrCreateOrganizationRelationshipAssignment(db, organizationId, linkedinRelationshipId, organizationMemberId) {
86
+ // Try to get existing assignment for this specific organization member
87
+ const existingSql = `
88
+ SELECT id
89
+ FROM public.organization_user_relationships_assignments
90
+ WHERE organization_id = $1
91
+ AND linkedin_relationship_id = $2
92
+ AND organization_member_id = $3
93
+ LIMIT 1
94
+ `;
95
+ const existing = await (0, pg_client_1.queryOne)(db, existingSql, [
96
+ organizationId,
97
+ linkedinRelationshipId,
98
+ organizationMemberId,
99
+ ]);
100
+ if (existing) {
101
+ return existing.id;
102
+ }
103
+ // Create new assignment
104
+ const insertSql = `
105
+ INSERT INTO public.organization_user_relationships_assignments (organization_id, linkedin_relationship_id, organization_member_id, created_at)
106
+ VALUES ($1, $2, $3, NOW())
107
+ RETURNING id
108
+ `;
109
+ const result = await (0, pg_client_1.queryOne)(db, insertSql, [
110
+ organizationId,
111
+ linkedinRelationshipId,
112
+ organizationMemberId,
113
+ ]);
114
+ if (!result) {
115
+ throw new Error("Failed to create organization relationship assignment");
116
+ }
117
+ return result.id;
118
+ }
119
+ /**
120
+ * Create or update a sales pipeline assignment
121
+ * If assignment exists, updates the stage; otherwise creates new assignment with default stage 'prospect'
122
+ *
123
+ * @param db - Database instance
124
+ * @param salesPipelineId - Sales pipeline ID
125
+ * @param organizationUserRelationshipAssignmentId - Organization relationship assignment ID
126
+ * @param stage - Sales stage (default: 'prospect')
127
+ * @returns Sales pipeline assignment
128
+ */
129
+ async function createOrUpdateSalesPipelineAssignment(db, salesPipelineId, organizationUserRelationshipAssignmentId, stage = "prospect") {
130
+ (0, db_1.debugLogDbOperation)("createOrUpdateSalesPipelineAssignment", "sales_pipeline_assignments", {
131
+ salesPipelineId,
132
+ organizationUserRelationshipAssignmentId,
133
+ stage,
134
+ });
135
+ // Try to get existing assignment
136
+ const existingSql = `
137
+ SELECT id, sales_pipeline_id, organization_user_relationship_assignment_id, stage, created_at, updated_at
138
+ FROM public.sales_pipeline_assignments
139
+ WHERE sales_pipeline_id = $1 AND organization_user_relationship_assignment_id = $2
140
+ LIMIT 1
141
+ `;
142
+ const existing = await (0, pg_client_1.queryOne)(db, existingSql, [
143
+ salesPipelineId,
144
+ organizationUserRelationshipAssignmentId,
145
+ ]);
146
+ if (existing) {
147
+ // Update existing assignment if stage changed
148
+ if (existing.stage !== stage) {
149
+ const updateSql = `
150
+ UPDATE public.sales_pipeline_assignments
151
+ SET stage = $1, updated_at = now()
152
+ WHERE id = $2
153
+ RETURNING id, sales_pipeline_id, organization_user_relationship_assignment_id, stage, created_at, updated_at
154
+ `;
155
+ const updated = await (0, pg_client_1.queryOne)(db, updateSql, [stage, existing.id]);
156
+ if (!updated) {
157
+ throw new Error("Failed to update sales pipeline assignment");
158
+ }
159
+ return {
160
+ id: updated.id,
161
+ salesPipelineId: updated.sales_pipeline_id,
162
+ organizationUserRelationshipAssignmentId: updated.organization_user_relationship_assignment_id,
163
+ stage: updated.stage,
164
+ createdAt: updated.created_at,
165
+ updatedAt: updated.updated_at,
166
+ };
167
+ }
168
+ // Return existing assignment if stage unchanged
169
+ return {
170
+ id: existing.id,
171
+ salesPipelineId: existing.sales_pipeline_id,
172
+ organizationUserRelationshipAssignmentId: existing.organization_user_relationship_assignment_id,
173
+ stage: existing.stage,
174
+ createdAt: existing.created_at,
175
+ updatedAt: existing.updated_at,
176
+ };
177
+ }
178
+ // Create new assignment
179
+ const insertSql = `
180
+ INSERT INTO public.sales_pipeline_assignments (sales_pipeline_id, organization_user_relationship_assignment_id, stage)
181
+ VALUES ($1, $2, $3)
182
+ RETURNING id, sales_pipeline_id, organization_user_relationship_assignment_id, stage, created_at, updated_at
183
+ `;
184
+ const result = await (0, pg_client_1.queryOne)(db, insertSql, [
185
+ salesPipelineId,
186
+ organizationUserRelationshipAssignmentId,
187
+ stage,
188
+ ]);
189
+ if (!result) {
190
+ throw new Error("Failed to create sales pipeline assignment");
191
+ }
192
+ return {
193
+ id: result.id,
194
+ salesPipelineId: result.sales_pipeline_id,
195
+ organizationUserRelationshipAssignmentId: result.organization_user_relationship_assignment_id,
196
+ stage: result.stage,
197
+ createdAt: result.created_at,
198
+ updatedAt: result.updated_at,
199
+ };
200
+ }
201
+ /**
202
+ * Get a sales pipeline assignment by ID and validate it belongs to an organization
203
+ *
204
+ * @param db - Database instance
205
+ * @param assignmentId - Sales pipeline assignment ID
206
+ * @param organizationId - Organization ID to validate against
207
+ * @returns Sales pipeline assignment with pipeline info, or null if not found or doesn't belong to org
208
+ */
209
+ async function getSalesPipelineAssignmentWithValidation(db, assignmentId, organizationId) {
210
+ (0, db_1.debugLogDbOperation)("getSalesPipelineAssignmentWithValidation", "sales_pipeline_assignments", {
211
+ assignmentId,
212
+ organizationId,
213
+ });
214
+ const sql = `
215
+ SELECT
216
+ spa.id,
217
+ spa.sales_pipeline_id,
218
+ spa.organization_user_relationship_assignment_id,
219
+ spa.stage,
220
+ spa.created_at as assignment_created_at,
221
+ spa.updated_at as assignment_updated_at,
222
+ sp.id as pipeline_id,
223
+ sp.organization_id,
224
+ sp.added_by_organization_member_id,
225
+ sp.created_at as pipeline_created_at
226
+ FROM public.sales_pipeline_assignments spa
227
+ INNER JOIN public.sales_pipelines sp ON sp.id = spa.sales_pipeline_id
228
+ INNER JOIN public.organization_user_relationships_assignments oura ON oura.id = spa.organization_user_relationship_assignment_id
229
+ WHERE spa.id = $1 AND sp.organization_id = $2 AND oura.organization_id = $2
230
+ LIMIT 1
231
+ `;
232
+ const result = await (0, pg_client_1.queryOne)(db, sql, [assignmentId, organizationId]);
233
+ if (!result) {
234
+ return null;
235
+ }
236
+ return {
237
+ assignment: {
238
+ id: result.id,
239
+ salesPipelineId: result.sales_pipeline_id,
240
+ organizationUserRelationshipAssignmentId: result.organization_user_relationship_assignment_id,
241
+ stage: result.stage,
242
+ createdAt: result.assignment_created_at,
243
+ updatedAt: result.assignment_updated_at,
244
+ },
245
+ pipeline: {
246
+ id: result.pipeline_id,
247
+ organizationId: result.organization_id,
248
+ addedByOrganizationMemberId: result.added_by_organization_member_id,
249
+ createdAt: result.pipeline_created_at,
250
+ },
251
+ };
252
+ }
253
+ /**
254
+ * Add a relationship to the sales pipeline
255
+ * Creates or gets the pipeline entry and organization relationship assignment, then creates/updates the pipeline assignment with default stage 'prospect'
256
+ *
257
+ * @param db - Database instance
258
+ * @param organizationId - Organization ID
259
+ * @param linkedinRelationshipId - LinkedIn relationship ID
260
+ * @returns Sales pipeline assignment
261
+ */
262
+ async function addToSalesPipeline(db, organizationId, linkedinRelationshipId, addedByOrganizationMemberId // Mandatory - must be provided
263
+ ) {
264
+ (0, db_1.debugLogDbOperation)("addToSalesPipeline", "sales_pipeline_assignments", {
265
+ organizationId,
266
+ linkedinRelationshipId,
267
+ addedByOrganizationMemberId,
268
+ });
269
+ // Find the organization member whose LinkedIn account is part of this relationship
270
+ // The relationship assignment should belong to the member who owns the relationship
271
+ const findOrgMemberSql = `
272
+ SELECT om.id
273
+ FROM linkedin.relationships r
274
+ INNER JOIN linkedin.accounts la ON (la.id = r.linkedin_account_id_a OR la.id = r.linkedin_account_id_b)
275
+ INNER JOIN public.organization_members om ON om.user_id = la.user_id
276
+ WHERE r.id = $1
277
+ AND om.organization_id = $2
278
+ AND om.id = $3
279
+ LIMIT 1
280
+ `;
281
+ const relationshipOwner = await (0, pg_client_1.queryOne)(db, findOrgMemberSql, [linkedinRelationshipId, organizationId, addedByOrganizationMemberId]);
282
+ // If the person adding to pipeline is not the relationship owner, try to find the actual owner
283
+ let organizationMemberId = addedByOrganizationMemberId;
284
+ if (!relationshipOwner) {
285
+ const findAnyOwnerSql = `
286
+ SELECT om.id
287
+ FROM linkedin.relationships r
288
+ INNER JOIN linkedin.accounts la ON (la.id = r.linkedin_account_id_a OR la.id = r.linkedin_account_id_b)
289
+ INNER JOIN public.organization_members om ON om.user_id = la.user_id
290
+ WHERE r.id = $1
291
+ AND om.organization_id = $2
292
+ LIMIT 1
293
+ `;
294
+ const actualOwner = await (0, pg_client_1.queryOne)(db, findAnyOwnerSql, [
295
+ linkedinRelationshipId,
296
+ organizationId,
297
+ ]);
298
+ if (actualOwner) {
299
+ organizationMemberId = actualOwner.id;
300
+ }
301
+ // If no owner found, fall back to addedByOrganizationMemberId
302
+ }
303
+ // Get or create the organization relationship assignment first
304
+ const orgRelAssignmentId = await getOrCreateOrganizationRelationshipAssignment(db, organizationId, linkedinRelationshipId, organizationMemberId);
305
+ // Create or get the pipeline entry (checking via assignment)
306
+ const pipeline = await createOrGetSalesPipeline(db, organizationId, orgRelAssignmentId, addedByOrganizationMemberId);
307
+ // Create or update the pipeline assignment with default stage 'prospect'
308
+ const assignment = await createOrUpdateSalesPipelineAssignment(db, pipeline.id, orgRelAssignmentId, "prospect");
309
+ return assignment;
310
+ }
311
+ /**
312
+ * Add a relationship to the sales pipeline using organization relationship assignment ID
313
+ * This is more efficient as it already contains the organization and relationship context
314
+ *
315
+ * @param db - Database instance
316
+ * @param organizationUserRelationshipAssignmentId - Organization relationship assignment ID
317
+ * @param addedByOrganizationMemberId - Organization member who added this entry
318
+ * @returns Sales pipeline assignment
319
+ */
320
+ async function addToSalesPipelineByAssignmentId(db, organizationUserRelationshipAssignmentId, addedByOrganizationMemberId) {
321
+ (0, db_1.debugLogDbOperation)("addToSalesPipelineByAssignmentId", "sales_pipeline_assignments", {
322
+ organizationUserRelationshipAssignmentId,
323
+ addedByOrganizationMemberId,
324
+ });
325
+ // First, get the organization relationship assignment to extract org_id
326
+ const getAssignmentSql = `
327
+ SELECT organization_id, linkedin_relationship_id, organization_member_id
328
+ FROM public.organization_user_relationships_assignments
329
+ WHERE id = $1
330
+ LIMIT 1
331
+ `;
332
+ const assignment = await (0, pg_client_1.queryOne)(db, getAssignmentSql, [organizationUserRelationshipAssignmentId]);
333
+ if (!assignment) {
334
+ throw new Error(`Organization relationship assignment not found: ${organizationUserRelationshipAssignmentId}`);
335
+ }
336
+ const organizationId = assignment.organization_id;
337
+ // Create or get the pipeline entry (checking via assignment)
338
+ const pipeline = await createOrGetSalesPipeline(db, organizationId, organizationUserRelationshipAssignmentId, addedByOrganizationMemberId);
339
+ // Create or update the pipeline assignment with default stage 'prospect'
340
+ const pipelineAssignment = await createOrUpdateSalesPipelineAssignment(db, pipeline.id, organizationUserRelationshipAssignmentId, "prospect");
341
+ return pipelineAssignment;
342
+ }
343
+ /**
344
+ * Get a sales pipeline entry by ID
345
+ *
346
+ * @param db - Database instance
347
+ * @param salesPipelineId - Sales pipeline ID
348
+ * @returns Sales pipeline entry or null if not found
349
+ */
350
+ async function getSalesPipelineById(db, salesPipelineId) {
351
+ (0, db_1.debugLogDbOperation)("getSalesPipelineById", "sales_pipelines", {
352
+ salesPipelineId,
353
+ });
354
+ const sql = `
355
+ SELECT id, organization_id, added_by_organization_member_id, created_at
356
+ FROM public.sales_pipelines
357
+ WHERE id = $1
358
+ LIMIT 1
359
+ `;
360
+ const result = await (0, pg_client_1.queryOne)(db, sql, [salesPipelineId]);
361
+ if (!result) {
362
+ return null;
363
+ }
364
+ return {
365
+ id: result.id,
366
+ organizationId: result.organization_id,
367
+ addedByOrganizationMemberId: result.added_by_organization_member_id,
368
+ createdAt: result.created_at,
369
+ };
370
+ }
371
+ /**
372
+ * Get all sales pipeline entries for an organization with profile data
373
+ * Returns all pipeline assignments, with full relationship and profile information
374
+ *
375
+ * @param db - Database instance
376
+ * @param organizationId - Organization ID
377
+ * @param linkedinAccountId - Optional: filter by specific LinkedIn account's relationships
378
+ * @returns Array of sales pipeline entries with profile data
379
+ */
380
+ async function getSalesPipelineForOrganization(db, organizationId, linkedinAccountId) {
381
+ (0, db_1.debugLogDbOperation)("getSalesPipelineForOrganization", "sales_pipeline_assignments", {
382
+ organizationId,
383
+ linkedinAccountId,
384
+ });
385
+ const sql = `
386
+ WITH org_member_accounts AS (
387
+ -- Get all LinkedIn account IDs for organization members
388
+ SELECT DISTINCT la.id as linkedin_account_id
389
+ FROM public.organization_members om
390
+ INNER JOIN linkedin.accounts la ON la.user_id = om.user_id
391
+ WHERE om.organization_id = $1
392
+ ),
393
+ pipeline_assignments AS (
394
+ -- Get all assignments for pipelines in this organization
395
+ SELECT
396
+ spa.id as assignment_id,
397
+ spa.sales_pipeline_id,
398
+ spa.organization_user_relationship_assignment_id,
399
+ spa.stage,
400
+ spa.created_at as assignment_created_at,
401
+ spa.updated_at as assignment_updated_at,
402
+ oura.linkedin_relationship_id,
403
+ sp.added_by_organization_member_id
404
+ FROM public.sales_pipeline_assignments spa
405
+ INNER JOIN public.sales_pipelines sp ON sp.id = spa.sales_pipeline_id
406
+ INNER JOIN public.organization_user_relationships_assignments oura ON oura.id = spa.organization_user_relationship_assignment_id
407
+ INNER JOIN linkedin.relationships r ON r.id = oura.linkedin_relationship_id
408
+ WHERE sp.organization_id = $1 AND oura.organization_id = $1
409
+ ${linkedinAccountId ? "AND (r.linkedin_account_id_a = $2 OR r.linkedin_account_id_b = $2)" : ""}
410
+ )
411
+ SELECT
412
+ pa.assignment_id,
413
+ pa.sales_pipeline_id,
414
+ pa.organization_user_relationship_assignment_id,
415
+ pa.stage,
416
+ pa.assignment_created_at,
417
+ pa.assignment_updated_at,
418
+ pa.linkedin_relationship_id,
419
+ -- Get the contributor/introducer's LinkedIn account (the one whose mapping job created the relationship)
420
+ -- The contributor is the one who can make the intro
421
+ CASE
422
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN r.linkedin_account_id_a
423
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN r.linkedin_account_id_b
424
+ -- Fallback: if mapping job info not available, use org member logic
425
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN r.linkedin_account_id_a
426
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN r.linkedin_account_id_b
427
+ ELSE NULL
428
+ END as introducer_linkedin_account_id,
429
+ -- Get the connection's LinkedIn account (the "other" side - the person we want to reach)
430
+ CASE
431
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN r.linkedin_account_id_b
432
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN r.linkedin_account_id_a
433
+ -- Fallback: if mapping job info not available, use org member logic
434
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN r.linkedin_account_id_b
435
+ ELSE r.linkedin_account_id_a
436
+ END as connection_id,
437
+ -- Connection profile data (the person we want to reach)
438
+ COALESCE(
439
+ CASE
440
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.first_name || ' ' || la_b.last_name
441
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.first_name || ' ' || la_a.last_name
442
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.first_name || ' ' || la_b.last_name
443
+ ELSE la_a.first_name || ' ' || la_a.last_name
444
+ END,
445
+ CASE
446
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.first_name
447
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.first_name
448
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.first_name
449
+ ELSE la_a.first_name
450
+ END
451
+ ) as full_name,
452
+ CASE
453
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.first_name
454
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.first_name
455
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.first_name
456
+ ELSE la_a.first_name
457
+ END as first_name,
458
+ CASE
459
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.last_name
460
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.last_name
461
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.last_name
462
+ ELSE la_a.last_name
463
+ END as last_name,
464
+ CASE
465
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.headline
466
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.headline
467
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.headline
468
+ ELSE la_a.headline
469
+ END as headline,
470
+ CASE
471
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.summary
472
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.summary
473
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.summary
474
+ ELSE la_a.summary
475
+ END as summary,
476
+ CASE
477
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.location
478
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.location
479
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.location
480
+ ELSE la_a.location
481
+ END as location,
482
+ COALESCE(
483
+ CASE
484
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.profile_image_cloudfront_url
485
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.profile_image_cloudfront_url
486
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.profile_image_cloudfront_url
487
+ ELSE la_a.profile_image_cloudfront_url
488
+ END,
489
+ CASE
490
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.profile_picture_url
491
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.profile_picture_url
492
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.profile_picture_url
493
+ ELSE la_a.profile_picture_url
494
+ END
495
+ ) as profile_image_url,
496
+ CASE
497
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.public_identifier
498
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.public_identifier
499
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.public_identifier
500
+ ELSE la_a.public_identifier
501
+ END as linkedin_public_identifier,
502
+ CASE
503
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.linkedin_identifier_acoa
504
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.linkedin_identifier_acoa
505
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.linkedin_identifier_acoa
506
+ ELSE la_a.linkedin_identifier_acoa
507
+ END as linkedin_identifier_acoa,
508
+ -- Connection user data (if the connection is a registered user)
509
+ CASE
510
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_b.user_id
511
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_a.user_id
512
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_b.user_id
513
+ ELSE la_a.user_id
514
+ END as connection_user_id,
515
+ CASE
516
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN u_b.given_name
517
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN u_a.given_name
518
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN u_b.given_name
519
+ ELSE u_a.given_name
520
+ END as connection_user_given_name,
521
+ CASE
522
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN u_b.family_name
523
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN u_a.family_name
524
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN u_b.family_name
525
+ ELSE u_a.family_name
526
+ END as connection_user_family_name,
527
+ -- Introducer/Contributor data (the person who can do the intro - the one whose mapping job created the relationship)
528
+ COALESCE(
529
+ CASE
530
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.first_name || ' ' || la_a.last_name
531
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.first_name || ' ' || la_b.last_name
532
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.first_name || ' ' || la_a.last_name
533
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.first_name || ' ' || la_b.last_name
534
+ ELSE NULL
535
+ END,
536
+ CASE
537
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.first_name
538
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.first_name
539
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.first_name
540
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.first_name
541
+ ELSE NULL
542
+ END
543
+ ) as introducer_full_name,
544
+ CASE
545
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.first_name
546
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.first_name
547
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.first_name
548
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.first_name
549
+ ELSE NULL
550
+ END as introducer_first_name,
551
+ CASE
552
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.last_name
553
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.last_name
554
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.last_name
555
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.last_name
556
+ ELSE NULL
557
+ END as introducer_last_name,
558
+ CASE
559
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.headline
560
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.headline
561
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.headline
562
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.headline
563
+ ELSE NULL
564
+ END as introducer_headline,
565
+ COALESCE(
566
+ CASE
567
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.profile_image_cloudfront_url
568
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.profile_image_cloudfront_url
569
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.profile_image_cloudfront_url
570
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.profile_image_cloudfront_url
571
+ ELSE NULL
572
+ END,
573
+ CASE
574
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.profile_picture_url
575
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.profile_picture_url
576
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.profile_picture_url
577
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.profile_picture_url
578
+ ELSE NULL
579
+ END
580
+ ) as introducer_profile_image_url,
581
+ CASE
582
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.public_identifier
583
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.public_identifier
584
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.public_identifier
585
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.public_identifier
586
+ ELSE NULL
587
+ END as introducer_linkedin_public_identifier,
588
+ CASE
589
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.linkedin_identifier_acoa
590
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.linkedin_identifier_acoa
591
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.linkedin_identifier_acoa
592
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.linkedin_identifier_acoa
593
+ ELSE NULL
594
+ END as introducer_linkedin_identifier_acoa,
595
+ CASE
596
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN la_a.user_id
597
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN la_b.user_id
598
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN la_a.user_id
599
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN la_b.user_id
600
+ ELSE NULL
601
+ END as introducer_user_id,
602
+ CASE
603
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN u_a.given_name
604
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN u_b.given_name
605
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN u_a.given_name
606
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN u_b.given_name
607
+ ELSE NULL
608
+ END as introducer_user_given_name,
609
+ CASE
610
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_a THEN u_a.family_name
611
+ WHEN mj.linkedin_account_id = r.linkedin_account_id_b THEN u_b.family_name
612
+ WHEN oma_a.linkedin_account_id IS NOT NULL THEN u_a.family_name
613
+ WHEN oma_b.linkedin_account_id IS NOT NULL THEN u_b.family_name
614
+ ELSE NULL
615
+ END as introducer_user_family_name,
616
+ -- Added by information (who added this entry to the sales pipeline)
617
+ pa.added_by_organization_member_id,
618
+ added_by_om.user_id as added_by_user_id,
619
+ COALESCE(
620
+ added_by_user.given_name || ' ' || added_by_user.family_name,
621
+ added_by_user.given_name,
622
+ added_by_user.family_name,
623
+ 'Unknown'
624
+ ) as added_by_full_name,
625
+ added_by_user.given_name as added_by_given_name,
626
+ added_by_user.family_name as added_by_family_name,
627
+ COALESCE(
628
+ added_by_la.profile_image_cloudfront_url,
629
+ added_by_la.profile_picture_url
630
+ ) as added_by_profile_image_url
631
+ FROM pipeline_assignments pa
632
+ INNER JOIN linkedin.relationships r ON r.id = pa.linkedin_relationship_id
633
+ -- Get mapping job to determine which account is the contributor (the one whose mapping job created the relationship)
634
+ LEFT JOIN monitoring.mapping_jobs mj ON mj.id = r.mapping_job_id
635
+ -- Check if account A is an org member (fallback if mapping job info not available)
636
+ LEFT JOIN org_member_accounts oma_a ON oma_a.linkedin_account_id = r.linkedin_account_id_a
637
+ -- Check if account B is an org member (fallback if mapping job info not available)
638
+ LEFT JOIN org_member_accounts oma_b ON oma_b.linkedin_account_id = r.linkedin_account_id_b
639
+ -- Get LinkedIn account A data
640
+ INNER JOIN linkedin.accounts la_a ON la_a.id = r.linkedin_account_id_a
641
+ LEFT JOIN public.users u_a ON u_a.id = la_a.user_id
642
+ -- Get LinkedIn account B data
643
+ INNER JOIN linkedin.accounts la_b ON la_b.id = r.linkedin_account_id_b
644
+ LEFT JOIN public.users u_b ON u_b.id = la_b.user_id
645
+ -- Get added_by organization member and user data
646
+ LEFT JOIN public.organization_members added_by_om ON added_by_om.id = pa.added_by_organization_member_id
647
+ LEFT JOIN public.users added_by_user ON added_by_user.id = added_by_om.user_id
648
+ LEFT JOIN linkedin.accounts added_by_la ON added_by_la.user_id = added_by_om.user_id
649
+ ORDER BY pa.assignment_updated_at DESC, pa.assignment_created_at DESC
650
+ `;
651
+ const params = linkedinAccountId ? [organizationId, linkedinAccountId] : [organizationId];
652
+ const results = await (0, pg_client_1.query)(db, sql, params);
653
+ return results.map(r => ({
654
+ assignment_id: r.assignment_id,
655
+ sales_pipeline_id: r.sales_pipeline_id,
656
+ organization_user_relationship_assignment_id: r.organization_user_relationship_assignment_id,
657
+ stage: r.stage,
658
+ assignment_created_at: r.assignment_created_at,
659
+ assignment_updated_at: r.assignment_updated_at,
660
+ linkedin_relationship_id: r.linkedin_relationship_id,
661
+ connection_id: r.connection_id,
662
+ full_name: r.full_name,
663
+ first_name: r.first_name,
664
+ last_name: r.last_name,
665
+ headline: r.headline,
666
+ summary: r.summary,
667
+ location: r.location,
668
+ profile_image_url: r.profile_image_url,
669
+ linkedin_public_identifier: r.linkedin_public_identifier,
670
+ linkedin_identifier_acoa: r.linkedin_identifier_acoa,
671
+ connection_user_id: r.connection_user_id,
672
+ connection_user_given_name: r.connection_user_given_name,
673
+ connection_user_family_name: r.connection_user_family_name,
674
+ introducer_linkedin_account_id: r.introducer_linkedin_account_id,
675
+ introducer_full_name: r.introducer_full_name,
676
+ introducer_first_name: r.introducer_first_name,
677
+ introducer_last_name: r.introducer_last_name,
678
+ introducer_headline: r.introducer_headline,
679
+ introducer_profile_image_url: r.introducer_profile_image_url,
680
+ introducer_linkedin_public_identifier: r.introducer_linkedin_public_identifier,
681
+ introducer_linkedin_identifier_acoa: r.introducer_linkedin_identifier_acoa,
682
+ introducer_user_id: r.introducer_user_id,
683
+ introducer_user_given_name: r.introducer_user_given_name,
684
+ introducer_user_family_name: r.introducer_user_family_name,
685
+ added_by_organization_member_id: r.added_by_organization_member_id,
686
+ added_by_user_id: r.added_by_user_id,
687
+ added_by_full_name: r.added_by_full_name,
688
+ added_by_given_name: r.added_by_given_name,
689
+ added_by_family_name: r.added_by_family_name,
690
+ added_by_profile_image_url: r.added_by_profile_image_url,
691
+ }));
692
+ }
693
+ /**
694
+ * Update the stage of a sales pipeline assignment
695
+ *
696
+ * @param db - Database instance
697
+ * @param assignmentId - Sales pipeline assignment ID
698
+ * @param newStage - New sales stage
699
+ * @returns Updated sales pipeline assignment
700
+ */
701
+ async function updateSalesPipelineAssignmentStage(db, assignmentId, newStage) {
702
+ (0, db_1.debugLogDbOperation)("updateSalesPipelineAssignmentStage", "sales_pipeline_assignments", {
703
+ assignmentId,
704
+ newStage,
705
+ });
706
+ const updateSql = `
707
+ UPDATE public.sales_pipeline_assignments
708
+ SET stage = $1, updated_at = now()
709
+ WHERE id = $2
710
+ RETURNING id, sales_pipeline_id, organization_user_relationship_assignment_id, stage, created_at, updated_at
711
+ `;
712
+ const updated = await (0, pg_client_1.queryOne)(db, updateSql, [newStage, assignmentId]);
713
+ if (!updated) {
714
+ throw new Error("Failed to update sales pipeline assignment stage - assignment not found");
715
+ }
716
+ return {
717
+ id: updated.id,
718
+ salesPipelineId: updated.sales_pipeline_id,
719
+ organizationUserRelationshipAssignmentId: updated.organization_user_relationship_assignment_id,
720
+ stage: updated.stage,
721
+ createdAt: updated.created_at,
722
+ updatedAt: updated.updated_at,
723
+ };
724
+ }
725
+ //# sourceMappingURL=sales-pipeline-operations.js.map