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.
- package/CHANGELOG.md +750 -0
- package/README.md +660 -0
- package/dist/config/database.d.ts +28 -0
- package/dist/config/database.d.ts.map +1 -0
- package/dist/config/database.js +72 -0
- package/dist/config/database.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/database-service.d.ts +714 -0
- package/dist/lib/database-service.d.ts.map +1 -0
- package/dist/lib/database-service.js +1394 -0
- package/dist/lib/database-service.js.map +1 -0
- package/dist/lib/db-types.d.ts +167 -0
- package/dist/lib/db-types.d.ts.map +1 -0
- package/dist/lib/db-types.js +28 -0
- package/dist/lib/db-types.js.map +1 -0
- package/dist/lib/db.d.ts +58 -0
- package/dist/lib/db.d.ts.map +1 -0
- package/dist/lib/db.js +292 -0
- package/dist/lib/db.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +26 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/pg-client.d.ts +50 -0
- package/dist/lib/pg-client.d.ts.map +1 -0
- package/dist/lib/pg-client.js +106 -0
- package/dist/lib/pg-client.js.map +1 -0
- package/dist/lib/schema.d.ts +298 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +12 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/migration-manager.d.ts +49 -0
- package/dist/migration-manager.d.ts.map +1 -0
- package/dist/migration-manager.js +282 -0
- package/dist/migration-manager.js.map +1 -0
- package/dist/queries/minimal-connections.d.ts +31 -0
- package/dist/queries/minimal-connections.d.ts.map +1 -0
- package/dist/queries/minimal-connections.js +143 -0
- package/dist/queries/minimal-connections.js.map +1 -0
- package/dist/schema.ts +340 -0
- package/dist/seed.d.ts +8 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +40 -0
- package/dist/seed.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/types.d.ts +77 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +3 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/authenticated-user-operations.d.ts +110 -0
- package/dist/utils/authenticated-user-operations.d.ts.map +1 -0
- package/dist/utils/authenticated-user-operations.js +292 -0
- package/dist/utils/authenticated-user-operations.js.map +1 -0
- package/dist/utils/authentication-operations.d.ts +48 -0
- package/dist/utils/authentication-operations.d.ts.map +1 -0
- package/dist/utils/authentication-operations.js +172 -0
- package/dist/utils/authentication-operations.js.map +1 -0
- package/dist/utils/company-mapping-job-operations.d.ts +103 -0
- package/dist/utils/company-mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/company-mapping-job-operations.js +413 -0
- package/dist/utils/company-mapping-job-operations.js.map +1 -0
- package/dist/utils/company-sheet-upload-operations.d.ts +53 -0
- package/dist/utils/company-sheet-upload-operations.d.ts.map +1 -0
- package/dist/utils/company-sheet-upload-operations.js +135 -0
- package/dist/utils/company-sheet-upload-operations.js.map +1 -0
- package/dist/utils/contact-operations.d.ts +70 -0
- package/dist/utils/contact-operations.d.ts.map +1 -0
- package/dist/utils/contact-operations.js +294 -0
- package/dist/utils/contact-operations.js.map +1 -0
- package/dist/utils/forager-linkedin-operations.d.ts +74 -0
- package/dist/utils/forager-linkedin-operations.d.ts.map +1 -0
- package/dist/utils/forager-linkedin-operations.js +778 -0
- package/dist/utils/forager-linkedin-operations.js.map +1 -0
- package/dist/utils/ghost-genius-linkedin-operations.d.ts +23 -0
- package/dist/utils/ghost-genius-linkedin-operations.d.ts.map +1 -0
- package/dist/utils/ghost-genius-linkedin-operations.js +282 -0
- package/dist/utils/ghost-genius-linkedin-operations.js.map +1 -0
- package/dist/utils/index.d.ts +29 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +77 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/introduction-request-operations.d.ts +160 -0
- package/dist/utils/introduction-request-operations.d.ts.map +1 -0
- package/dist/utils/introduction-request-operations.js +492 -0
- package/dist/utils/introduction-request-operations.js.map +1 -0
- package/dist/utils/invitation-operations.d.ts +141 -0
- package/dist/utils/invitation-operations.d.ts.map +1 -0
- package/dist/utils/invitation-operations.js +749 -0
- package/dist/utils/invitation-operations.js.map +1 -0
- package/dist/utils/linkedin-account-operations.d.ts +45 -0
- package/dist/utils/linkedin-account-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-account-operations.js +279 -0
- package/dist/utils/linkedin-account-operations.js.map +1 -0
- package/dist/utils/linkedin-account-relationship-operations.d.ts +77 -0
- package/dist/utils/linkedin-account-relationship-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-account-relationship-operations.js +274 -0
- package/dist/utils/linkedin-account-relationship-operations.js.map +1 -0
- package/dist/utils/linkedin-data-operations.d.ts +102 -0
- package/dist/utils/linkedin-data-operations.d.ts.map +1 -0
- package/dist/utils/linkedin-data-operations.js +613 -0
- package/dist/utils/linkedin-data-operations.js.map +1 -0
- package/dist/utils/linkedin-identifier-utils.d.ts +31 -0
- package/dist/utils/linkedin-identifier-utils.d.ts.map +1 -0
- package/dist/utils/linkedin-identifier-utils.js +63 -0
- package/dist/utils/linkedin-identifier-utils.js.map +1 -0
- package/dist/utils/linkedin-profile-cache.d.ts +131 -0
- package/dist/utils/linkedin-profile-cache.d.ts.map +1 -0
- package/dist/utils/linkedin-profile-cache.js +418 -0
- package/dist/utils/linkedin-profile-cache.js.map +1 -0
- package/dist/utils/llm-inference-job-operations.d.ts +116 -0
- package/dist/utils/llm-inference-job-operations.d.ts.map +1 -0
- package/dist/utils/llm-inference-job-operations.js +267 -0
- package/dist/utils/llm-inference-job-operations.js.map +1 -0
- package/dist/utils/mapping-job-operations.d.ts +272 -0
- package/dist/utils/mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/mapping-job-operations.js +833 -0
- package/dist/utils/mapping-job-operations.js.map +1 -0
- package/dist/utils/mapping-operations.d.ts +80 -0
- package/dist/utils/mapping-operations.d.ts.map +1 -0
- package/dist/utils/mapping-operations.js +318 -0
- package/dist/utils/mapping-operations.js.map +1 -0
- package/dist/utils/on-demand-mapping-operations.d.ts +199 -0
- package/dist/utils/on-demand-mapping-operations.d.ts.map +1 -0
- package/dist/utils/on-demand-mapping-operations.js +728 -0
- package/dist/utils/on-demand-mapping-operations.js.map +1 -0
- package/dist/utils/onboarding-operations.d.ts +53 -0
- package/dist/utils/onboarding-operations.d.ts.map +1 -0
- package/dist/utils/onboarding-operations.js +223 -0
- package/dist/utils/onboarding-operations.js.map +1 -0
- package/dist/utils/organization-assignment-job-operations.d.ts +258 -0
- package/dist/utils/organization-assignment-job-operations.d.ts.map +1 -0
- package/dist/utils/organization-assignment-job-operations.js +881 -0
- package/dist/utils/organization-assignment-job-operations.js.map +1 -0
- package/dist/utils/organization-assignment-operations.d.ts +59 -0
- package/dist/utils/organization-assignment-operations.d.ts.map +1 -0
- package/dist/utils/organization-assignment-operations.js +130 -0
- package/dist/utils/organization-assignment-operations.js.map +1 -0
- package/dist/utils/organization-operations.d.ts +284 -0
- package/dist/utils/organization-operations.d.ts.map +1 -0
- package/dist/utils/organization-operations.js +1030 -0
- package/dist/utils/organization-operations.js.map +1 -0
- package/dist/utils/organization-relationship-operations.d.ts +79 -0
- package/dist/utils/organization-relationship-operations.d.ts.map +1 -0
- package/dist/utils/organization-relationship-operations.js +294 -0
- package/dist/utils/organization-relationship-operations.js.map +1 -0
- package/dist/utils/quota-operations.d.ts +107 -0
- package/dist/utils/quota-operations.d.ts.map +1 -0
- package/dist/utils/quota-operations.js +692 -0
- package/dist/utils/quota-operations.js.map +1 -0
- package/dist/utils/recursive-mapping-job-operations.d.ts +42 -0
- package/dist/utils/recursive-mapping-job-operations.d.ts.map +1 -0
- package/dist/utils/recursive-mapping-job-operations.js +169 -0
- package/dist/utils/recursive-mapping-job-operations.js.map +1 -0
- package/dist/utils/relationship-operations.d.ts +130 -0
- package/dist/utils/relationship-operations.d.ts.map +1 -0
- package/dist/utils/relationship-operations.js +329 -0
- package/dist/utils/relationship-operations.js.map +1 -0
- package/dist/utils/sales-pipeline-operations.d.ts +163 -0
- package/dist/utils/sales-pipeline-operations.d.ts.map +1 -0
- package/dist/utils/sales-pipeline-operations.js +725 -0
- package/dist/utils/sales-pipeline-operations.js.map +1 -0
- package/dist/utils/skills-operations.d.ts +117 -0
- package/dist/utils/skills-operations.d.ts.map +1 -0
- package/dist/utils/skills-operations.js +487 -0
- package/dist/utils/skills-operations.js.map +1 -0
- package/dist/utils/subscription-operations.d.ts +123 -0
- package/dist/utils/subscription-operations.d.ts.map +1 -0
- package/dist/utils/subscription-operations.js +391 -0
- package/dist/utils/subscription-operations.js.map +1 -0
- package/dist/utils/unipile-account-operations.d.ts +96 -0
- package/dist/utils/unipile-account-operations.d.ts.map +1 -0
- package/dist/utils/unipile-account-operations.js +255 -0
- package/dist/utils/unipile-account-operations.js.map +1 -0
- package/dist/utils/user-industry-operations.d.ts +80 -0
- package/dist/utils/user-industry-operations.d.ts.map +1 -0
- package/dist/utils/user-industry-operations.js +237 -0
- package/dist/utils/user-industry-operations.js.map +1 -0
- package/dist/utils/user-operations.d.ts +87 -0
- package/dist/utils/user-operations.d.ts.map +1 -0
- package/dist/utils/user-operations.js +212 -0
- package/dist/utils/user-operations.js.map +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,833 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* =============================================================================
|
|
4
|
+
* MAPPING JOB OPERATIONS UTILITIES - CONSOLIDATED SCHEMA
|
|
5
|
+
* =============================================================================
|
|
6
|
+
* Utility functions for creating and managing mapping jobs with direct LinkedIn account references
|
|
7
|
+
*
|
|
8
|
+
* USAGE EXAMPLES:
|
|
9
|
+
*
|
|
10
|
+
* 1. SINGLE LINKEDIN ACCOUNT MAPPING JOB:
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const result = await createMappingJobForLinkedInAccount({
|
|
13
|
+
* linkedinAccountId: 123,
|
|
14
|
+
* jobMetadata: {
|
|
15
|
+
* service: "feed_analyzer",
|
|
16
|
+
* triggered_by: "preparation_handler",
|
|
17
|
+
* linkedin_identifier: "ACoAABCDEFG"
|
|
18
|
+
* }
|
|
19
|
+
* });
|
|
20
|
+
* // Creates: 1 job with direct linkedin_account_id reference
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* 2. BATCH PROCESSING (Multiple Jobs):
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const results = await createMappingJobsForLinkedInAccounts([
|
|
26
|
+
* { linkedinAccountId: 123, metadata: { priority: "high" } },
|
|
27
|
+
* { linkedinAccountId: 456, metadata: { priority: "normal" } },
|
|
28
|
+
* { linkedinAccountId: 789, metadata: { priority: "low" } }
|
|
29
|
+
* ]);
|
|
30
|
+
* // Creates: 3 separate jobs, each with direct linkedin_account_id reference
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* 3. PROCESSING LIFECYCLE:
|
|
34
|
+
* ```typescript
|
|
35
|
+
* // When processing starts
|
|
36
|
+
* await startMappingJob(jobId, {
|
|
37
|
+
* service_version: "v2.1.0",
|
|
38
|
+
* model_version: "gpt-4-turbo",
|
|
39
|
+
* started_by: "mapping_service_lambda"
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // When processing completes
|
|
43
|
+
* await completeMappingJob(jobId, {
|
|
44
|
+
* completion_status: "success",
|
|
45
|
+
* processed_items: 150,
|
|
46
|
+
* completion_reason: "all_items_processed"
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.createMappingJobForLinkedInAccount = createMappingJobForLinkedInAccount;
|
|
52
|
+
exports.createMappingJobsForLinkedInAccounts = createMappingJobsForLinkedInAccounts;
|
|
53
|
+
exports.startMappingJob = startMappingJob;
|
|
54
|
+
exports.completeMappingJob = completeMappingJob;
|
|
55
|
+
exports.validateMappingJobCompletion = validateMappingJobCompletion;
|
|
56
|
+
exports.getMappingJobById = getMappingJobById;
|
|
57
|
+
exports.getMappingJobWithLinkedInAccount = getMappingJobWithLinkedInAccount;
|
|
58
|
+
exports.getMappingJobsForLinkedInAccount = getMappingJobsForLinkedInAccount;
|
|
59
|
+
exports.getPendingMappingJobs = getPendingMappingJobs;
|
|
60
|
+
exports.getRunningMappingJobs = getRunningMappingJobs;
|
|
61
|
+
exports.getCompletedMappingJobs = getCompletedMappingJobs;
|
|
62
|
+
exports.getRelationshipScoresForMappingJob = getRelationshipScoresForMappingJob;
|
|
63
|
+
exports.getEnrichedRelationshipScoresForMappingJob = getEnrichedRelationshipScoresForMappingJob;
|
|
64
|
+
exports.deleteMappingJob = deleteMappingJob;
|
|
65
|
+
exports.createMappingJobWithSingleLinkedInAccount = createMappingJobWithSingleLinkedInAccount;
|
|
66
|
+
exports.createMappingJobWithLinkedInAccounts = createMappingJobWithLinkedInAccounts;
|
|
67
|
+
exports.checkMappingAvailability = checkMappingAvailability;
|
|
68
|
+
const pg_client_1 = require("../lib/pg-client");
|
|
69
|
+
const db_1 = require("../lib/db");
|
|
70
|
+
/**
|
|
71
|
+
* Creates a new mapping job for a single LinkedIn account
|
|
72
|
+
*/
|
|
73
|
+
async function createMappingJobForLinkedInAccount(db, params) {
|
|
74
|
+
const { linkedinAccountId, jobMetadata = {}, companyMappingJobId = null, recursiveMappingJobId = null } = params;
|
|
75
|
+
(0, db_1.debugLogDbOperation)("insert", "monitoring.mapping_jobs", { linkedinAccountId, jobMetadata }, undefined, {
|
|
76
|
+
operation: "createMappingJobForLinkedInAccount",
|
|
77
|
+
linkedinAccountId,
|
|
78
|
+
});
|
|
79
|
+
try {
|
|
80
|
+
// Verify LinkedIn account exists
|
|
81
|
+
const accountCheckSql = `
|
|
82
|
+
SELECT id FROM linkedin.accounts WHERE id = $1 LIMIT 1
|
|
83
|
+
`;
|
|
84
|
+
const linkedinAccount = await (0, pg_client_1.query)(db, accountCheckSql, [
|
|
85
|
+
linkedinAccountId,
|
|
86
|
+
]);
|
|
87
|
+
if (linkedinAccount.length === 0) {
|
|
88
|
+
throw new Error(`LinkedIn account with ID ${linkedinAccountId} not found`);
|
|
89
|
+
}
|
|
90
|
+
// Create the mapping job
|
|
91
|
+
const insertSql = `
|
|
92
|
+
INSERT INTO monitoring.mapping_jobs (linkedin_account_id, company_mapping_job_id, recursive_mapping_job_id, metadata, created_at, queued_at)
|
|
93
|
+
VALUES ($1, $2, $3, $4, NOW(), NOW())
|
|
94
|
+
RETURNING id, linkedin_account_id, company_mapping_job_id, recursive_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
95
|
+
`;
|
|
96
|
+
const mappingJob = await (0, pg_client_1.queryOne)(db, insertSql, [
|
|
97
|
+
linkedinAccountId,
|
|
98
|
+
companyMappingJobId,
|
|
99
|
+
recursiveMappingJobId,
|
|
100
|
+
JSON.stringify(jobMetadata),
|
|
101
|
+
]);
|
|
102
|
+
if (!mappingJob) {
|
|
103
|
+
throw new Error("Failed to create mapping job");
|
|
104
|
+
}
|
|
105
|
+
return { mappingJob };
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
console.error("Error creating mapping job for LinkedIn account:", error);
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Creates mapping jobs for multiple LinkedIn accounts
|
|
114
|
+
*/
|
|
115
|
+
async function createMappingJobsForLinkedInAccounts(db, accountsData) {
|
|
116
|
+
if (accountsData.length === 0) {
|
|
117
|
+
return { mappingJobs: [] };
|
|
118
|
+
}
|
|
119
|
+
(0, db_1.debugLogDbOperation)("insert", "monitoring.mapping_jobs", { count: accountsData.length }, undefined, {
|
|
120
|
+
operation: "createMappingJobsForLinkedInAccounts",
|
|
121
|
+
accountCount: accountsData.length,
|
|
122
|
+
});
|
|
123
|
+
try {
|
|
124
|
+
// Verify all LinkedIn accounts exist
|
|
125
|
+
const linkedinAccountIds = accountsData.map(data => data.linkedinAccountId);
|
|
126
|
+
const placeholders = linkedinAccountIds.map((_, i) => `$${i + 1}`).join(", ");
|
|
127
|
+
const accountCheckSql = `
|
|
128
|
+
SELECT id FROM linkedin.accounts WHERE id IN (${placeholders})
|
|
129
|
+
`;
|
|
130
|
+
const existingAccounts = await (0, pg_client_1.query)(db, accountCheckSql, linkedinAccountIds);
|
|
131
|
+
const existingAccountIds = new Set(existingAccounts.map(acc => acc.id));
|
|
132
|
+
const missingAccountIds = linkedinAccountIds.filter(id => !existingAccountIds.has(id));
|
|
133
|
+
if (missingAccountIds.length > 0) {
|
|
134
|
+
throw new Error(`LinkedIn accounts not found: ${missingAccountIds.join(", ")}`);
|
|
135
|
+
}
|
|
136
|
+
// Create mapping jobs
|
|
137
|
+
const values = [];
|
|
138
|
+
const params = [];
|
|
139
|
+
let paramIndex = 1;
|
|
140
|
+
accountsData.forEach(data => {
|
|
141
|
+
values.push(`($${paramIndex}, NULL, NULL, $${paramIndex + 1}, NOW(), NOW())`);
|
|
142
|
+
params.push(data.linkedinAccountId, JSON.stringify(data.metadata || {}));
|
|
143
|
+
paramIndex += 2;
|
|
144
|
+
});
|
|
145
|
+
const insertSql = `
|
|
146
|
+
INSERT INTO monitoring.mapping_jobs (linkedin_account_id, company_mapping_job_id, recursive_mapping_job_id, metadata, created_at, queued_at)
|
|
147
|
+
VALUES ${values.join(", ")}
|
|
148
|
+
RETURNING id, linkedin_account_id, company_mapping_job_id, recursive_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
149
|
+
`;
|
|
150
|
+
const createdJobs = await (0, pg_client_1.query)(db, insertSql, params);
|
|
151
|
+
return { mappingJobs: createdJobs };
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
console.error("Error creating mapping jobs for LinkedIn accounts:", error);
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Start a mapping job (mark as started)
|
|
160
|
+
*/
|
|
161
|
+
async function startMappingJob(db, mappingJobId, startMetadata) {
|
|
162
|
+
(0, db_1.debugLogDbOperation)("update", "monitoring.mapping_jobs", { id: mappingJobId, startMetadata }, undefined, {
|
|
163
|
+
operation: "startMappingJob",
|
|
164
|
+
mappingJobId,
|
|
165
|
+
});
|
|
166
|
+
try {
|
|
167
|
+
if (startMetadata) {
|
|
168
|
+
// Get existing metadata and merge
|
|
169
|
+
const selectSql = `
|
|
170
|
+
SELECT metadata FROM monitoring.mapping_jobs WHERE id = $1 LIMIT 1
|
|
171
|
+
`;
|
|
172
|
+
const existingJob = await (0, pg_client_1.queryOne)(db, selectSql, [mappingJobId]);
|
|
173
|
+
const mergedMetadata = existingJob
|
|
174
|
+
? { ...(existingJob.metadata || {}), ...startMetadata }
|
|
175
|
+
: startMetadata;
|
|
176
|
+
const updateSql = `
|
|
177
|
+
UPDATE monitoring.mapping_jobs
|
|
178
|
+
SET started_at = NOW(), metadata = $2
|
|
179
|
+
WHERE id = $1
|
|
180
|
+
RETURNING id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
181
|
+
`;
|
|
182
|
+
const updatedJob = await (0, pg_client_1.queryOne)(db, updateSql, [
|
|
183
|
+
mappingJobId,
|
|
184
|
+
JSON.stringify(mergedMetadata),
|
|
185
|
+
]);
|
|
186
|
+
if (!updatedJob) {
|
|
187
|
+
throw new Error(`Mapping job with ID ${mappingJobId} not found`);
|
|
188
|
+
}
|
|
189
|
+
return updatedJob;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const updateSql = `
|
|
193
|
+
UPDATE monitoring.mapping_jobs
|
|
194
|
+
SET started_at = NOW()
|
|
195
|
+
WHERE id = $1
|
|
196
|
+
RETURNING id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
197
|
+
`;
|
|
198
|
+
const updatedJob = await (0, pg_client_1.queryOne)(db, updateSql, [
|
|
199
|
+
mappingJobId,
|
|
200
|
+
]);
|
|
201
|
+
if (!updatedJob) {
|
|
202
|
+
throw new Error(`Mapping job with ID ${mappingJobId} not found`);
|
|
203
|
+
}
|
|
204
|
+
return updatedJob;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
console.error("Error starting mapping job:", error);
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Complete a mapping job (mark as completed)
|
|
214
|
+
*/
|
|
215
|
+
async function completeMappingJob(db, mappingJobId, completionMetadata) {
|
|
216
|
+
(0, db_1.debugLogDbOperation)("update", "monitoring.mapping_jobs", { id: mappingJobId, completionMetadata }, undefined, {
|
|
217
|
+
operation: "completeMappingJob",
|
|
218
|
+
mappingJobId,
|
|
219
|
+
});
|
|
220
|
+
try {
|
|
221
|
+
if (completionMetadata) {
|
|
222
|
+
// Get existing metadata and merge
|
|
223
|
+
const selectSql = `
|
|
224
|
+
SELECT metadata FROM monitoring.mapping_jobs WHERE id = $1 LIMIT 1
|
|
225
|
+
`;
|
|
226
|
+
const existingJob = await (0, pg_client_1.queryOne)(db, selectSql, [mappingJobId]);
|
|
227
|
+
const mergedMetadata = existingJob
|
|
228
|
+
? { ...(existingJob.metadata || {}), ...completionMetadata }
|
|
229
|
+
: completionMetadata;
|
|
230
|
+
const updateSql = `
|
|
231
|
+
UPDATE monitoring.mapping_jobs
|
|
232
|
+
SET completed_at = NOW(), metadata = $2
|
|
233
|
+
WHERE id = $1
|
|
234
|
+
RETURNING id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
235
|
+
`;
|
|
236
|
+
const updatedJob = await (0, pg_client_1.queryOne)(db, updateSql, [
|
|
237
|
+
mappingJobId,
|
|
238
|
+
JSON.stringify(mergedMetadata),
|
|
239
|
+
]);
|
|
240
|
+
if (!updatedJob) {
|
|
241
|
+
throw new Error(`Mapping job with ID ${mappingJobId} not found`);
|
|
242
|
+
}
|
|
243
|
+
return updatedJob;
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
const updateSql = `
|
|
247
|
+
UPDATE monitoring.mapping_jobs
|
|
248
|
+
SET completed_at = NOW()
|
|
249
|
+
WHERE id = $1
|
|
250
|
+
RETURNING id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
251
|
+
`;
|
|
252
|
+
const updatedJob = await (0, pg_client_1.queryOne)(db, updateSql, [
|
|
253
|
+
mappingJobId,
|
|
254
|
+
]);
|
|
255
|
+
if (!updatedJob) {
|
|
256
|
+
throw new Error(`Mapping job with ID ${mappingJobId} not found`);
|
|
257
|
+
}
|
|
258
|
+
return updatedJob;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error("Error completing mapping job:", error);
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Validate that a mapping job exists and has been completed
|
|
268
|
+
*/
|
|
269
|
+
async function validateMappingJobCompletion(db, mappingJobId) {
|
|
270
|
+
(0, db_1.debugLogDbOperation)("select", "monitoring.mapping_jobs", { id: mappingJobId }, undefined, {
|
|
271
|
+
operation: "validateMappingJobCompletion",
|
|
272
|
+
mappingJobId,
|
|
273
|
+
});
|
|
274
|
+
try {
|
|
275
|
+
const sql = `
|
|
276
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, recursive_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
277
|
+
FROM monitoring.mapping_jobs
|
|
278
|
+
WHERE id = $1
|
|
279
|
+
LIMIT 1
|
|
280
|
+
`;
|
|
281
|
+
const row = await (0, pg_client_1.queryOne)(db, sql, [mappingJobId]);
|
|
282
|
+
if (!row) {
|
|
283
|
+
return {
|
|
284
|
+
isValid: false,
|
|
285
|
+
error: `Mapping job with ID ${mappingJobId} not found`,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
// Map snake_case to camelCase
|
|
289
|
+
const mappingJob = {
|
|
290
|
+
id: row.id,
|
|
291
|
+
linkedinAccountId: row.linkedin_account_id,
|
|
292
|
+
companyMappingJobId: row.company_mapping_job_id,
|
|
293
|
+
recursiveMappingJobId: row.recursive_mapping_job_id,
|
|
294
|
+
metadata: row.metadata || {},
|
|
295
|
+
createdAt: row.created_at,
|
|
296
|
+
queuedAt: row.queued_at,
|
|
297
|
+
startedAt: row.started_at,
|
|
298
|
+
completedAt: row.completed_at,
|
|
299
|
+
};
|
|
300
|
+
if (!mappingJob.completedAt) {
|
|
301
|
+
return {
|
|
302
|
+
isValid: false,
|
|
303
|
+
error: `Mapping job ${mappingJobId} has not been completed yet`,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
isValid: true,
|
|
308
|
+
mappingJob: mappingJob,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
catch (error) {
|
|
312
|
+
console.error("Error validating mapping job completion:", error);
|
|
313
|
+
return {
|
|
314
|
+
isValid: false,
|
|
315
|
+
error: `Failed to validate mapping job: ${error instanceof Error ? error.message : String(error)}`,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get mapping job by ID
|
|
321
|
+
* Returns basic mapping job information including completion status
|
|
322
|
+
*
|
|
323
|
+
* @param db - Database instance
|
|
324
|
+
* @param mappingJobId - Mapping job ID
|
|
325
|
+
* @returns Mapping job or null if not found
|
|
326
|
+
*/
|
|
327
|
+
async function getMappingJobById(db, mappingJobId) {
|
|
328
|
+
(0, db_1.debugLogDbOperation)("select", "monitoring.mapping_jobs", { mappingJobId }, undefined, {
|
|
329
|
+
operation: "getMappingJobById",
|
|
330
|
+
mappingJobId,
|
|
331
|
+
});
|
|
332
|
+
try {
|
|
333
|
+
const sql = `
|
|
334
|
+
SELECT id, linkedin_account_id, completed_at
|
|
335
|
+
FROM monitoring.mapping_jobs
|
|
336
|
+
WHERE id = $1
|
|
337
|
+
LIMIT 1
|
|
338
|
+
`;
|
|
339
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [mappingJobId]);
|
|
340
|
+
return result;
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
console.error("Error getting mapping job by ID:", error);
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get mapping job with LinkedIn account details
|
|
349
|
+
*/
|
|
350
|
+
async function getMappingJobWithLinkedInAccount(db, mappingJobId) {
|
|
351
|
+
(0, db_1.debugLogDbOperation)("select", "monitoring.mapping_jobs + linkedin.accounts + users", { mappingJobId }, undefined, {
|
|
352
|
+
operation: "getMappingJobWithLinkedInAccount",
|
|
353
|
+
mappingJobId,
|
|
354
|
+
});
|
|
355
|
+
try {
|
|
356
|
+
const sql = `
|
|
357
|
+
SELECT
|
|
358
|
+
-- Mapping job fields
|
|
359
|
+
mj.id as mj_id,
|
|
360
|
+
mj.linkedin_account_id as mj_linkedin_account_id,
|
|
361
|
+
mj.company_mapping_job_id as mj_company_mapping_job_id,
|
|
362
|
+
mj.recursive_mapping_job_id as mj_recursive_mapping_job_id,
|
|
363
|
+
mj.created_at as mj_created_at,
|
|
364
|
+
mj.queued_at as mj_queued_at,
|
|
365
|
+
mj.started_at as mj_started_at,
|
|
366
|
+
mj.completed_at as mj_completed_at,
|
|
367
|
+
mj.metadata as mj_metadata,
|
|
368
|
+
-- LinkedIn account fields
|
|
369
|
+
la.id as la_id,
|
|
370
|
+
la.user_id as la_user_id,
|
|
371
|
+
la.linkedin_identifier_acoa as la_linkedin_identifier_acoa,
|
|
372
|
+
la.public_identifier as la_public_identifier,
|
|
373
|
+
la.forager_id as la_forager_id,
|
|
374
|
+
la.first_name as la_first_name,
|
|
375
|
+
la.last_name as la_last_name,
|
|
376
|
+
la.headline as la_headline,
|
|
377
|
+
la.summary as la_summary,
|
|
378
|
+
la.location as la_location,
|
|
379
|
+
COALESCE(la.profile_image_cloudfront_url, la.profile_picture_url) as la_profile_picture_url,
|
|
380
|
+
NULL::text as la_profile_image_cloudfront_url,
|
|
381
|
+
la.follower_count as la_follower_count,
|
|
382
|
+
la.connections_count as la_connections_count,
|
|
383
|
+
la.profiles_updated_at as la_profiles_updated_at,
|
|
384
|
+
la.created_at as la_created_at,
|
|
385
|
+
-- User fields (optional)
|
|
386
|
+
u.id as u_id,
|
|
387
|
+
u.given_name as u_given_name,
|
|
388
|
+
u.family_name as u_family_name,
|
|
389
|
+
u.summary as u_summary,
|
|
390
|
+
u.embedding_summary as u_embedding_summary,
|
|
391
|
+
u.embedding as u_embedding,
|
|
392
|
+
u.created_at as u_created_at
|
|
393
|
+
FROM monitoring.mapping_jobs mj
|
|
394
|
+
INNER JOIN linkedin.accounts la ON mj.linkedin_account_id = la.id
|
|
395
|
+
LEFT JOIN public.users u ON la.user_id = u.id
|
|
396
|
+
WHERE mj.id = $1
|
|
397
|
+
LIMIT 1
|
|
398
|
+
`;
|
|
399
|
+
const result = await (0, pg_client_1.queryOne)(db, sql, [mappingJobId]);
|
|
400
|
+
if (!result) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
mappingJob: {
|
|
405
|
+
id: result.mj_id,
|
|
406
|
+
linkedinAccountId: result.mj_linkedin_account_id,
|
|
407
|
+
companyMappingJobId: result.mj_company_mapping_job_id,
|
|
408
|
+
recursiveMappingJobId: result.mj_recursive_mapping_job_id,
|
|
409
|
+
createdAt: result.mj_created_at,
|
|
410
|
+
queuedAt: result.mj_queued_at,
|
|
411
|
+
startedAt: result.mj_started_at,
|
|
412
|
+
completedAt: result.mj_completed_at,
|
|
413
|
+
metadata: result.mj_metadata,
|
|
414
|
+
},
|
|
415
|
+
linkedinAccount: {
|
|
416
|
+
id: result.la_id,
|
|
417
|
+
user_id: result.la_user_id,
|
|
418
|
+
linkedin_identifier_acoa: result.la_linkedin_identifier_acoa,
|
|
419
|
+
public_identifier: result.la_public_identifier,
|
|
420
|
+
forager_id: result.la_forager_id,
|
|
421
|
+
first_name: result.la_first_name,
|
|
422
|
+
last_name: result.la_last_name,
|
|
423
|
+
headline: result.la_headline,
|
|
424
|
+
summary: result.la_summary,
|
|
425
|
+
location: result.la_location,
|
|
426
|
+
profile_picture_url: result.la_profile_picture_url,
|
|
427
|
+
profile_image_cloudfront_url: result.la_profile_image_cloudfront_url,
|
|
428
|
+
follower_count: result.la_follower_count,
|
|
429
|
+
connections_count: result.la_connections_count,
|
|
430
|
+
profiles_updated_at: result.la_profiles_updated_at,
|
|
431
|
+
created_at: result.la_created_at,
|
|
432
|
+
},
|
|
433
|
+
user: result.u_id
|
|
434
|
+
? {
|
|
435
|
+
id: result.u_id,
|
|
436
|
+
given_name: result.u_given_name,
|
|
437
|
+
family_name: result.u_family_name,
|
|
438
|
+
summary: result.u_summary,
|
|
439
|
+
embedding_summary: result.u_embedding_summary,
|
|
440
|
+
embedding: result.u_embedding,
|
|
441
|
+
created_at: result.u_created_at,
|
|
442
|
+
}
|
|
443
|
+
: undefined,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
catch (error) {
|
|
447
|
+
console.error("Error getting mapping job with LinkedIn account:", error);
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Get all mapping jobs for a LinkedIn account
|
|
453
|
+
*/
|
|
454
|
+
async function getMappingJobsForLinkedInAccount(db, linkedinAccountId, options) {
|
|
455
|
+
const { limit = 50, includeCompleted = true } = options || {};
|
|
456
|
+
(0, db_1.debugLogDbOperation)("select", "monitoring.mapping_jobs", { linkedinAccountId, limit, includeCompleted }, undefined, {
|
|
457
|
+
operation: "getMappingJobsForLinkedInAccount",
|
|
458
|
+
linkedinAccountId,
|
|
459
|
+
});
|
|
460
|
+
try {
|
|
461
|
+
const sql = includeCompleted
|
|
462
|
+
? `
|
|
463
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
464
|
+
FROM monitoring.mapping_jobs
|
|
465
|
+
WHERE linkedin_account_id = $1
|
|
466
|
+
ORDER BY created_at DESC
|
|
467
|
+
LIMIT $2
|
|
468
|
+
`
|
|
469
|
+
: `
|
|
470
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
471
|
+
FROM monitoring.mapping_jobs
|
|
472
|
+
WHERE linkedin_account_id = $1 AND completed_at IS NULL
|
|
473
|
+
ORDER BY created_at DESC
|
|
474
|
+
LIMIT $2
|
|
475
|
+
`;
|
|
476
|
+
return await (0, pg_client_1.query)(db, sql, [linkedinAccountId, limit]);
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
console.error("Error getting mapping jobs for LinkedIn account:", error);
|
|
480
|
+
throw error;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Get pending mapping jobs (not started yet)
|
|
485
|
+
*/
|
|
486
|
+
async function getPendingMappingJobs(db, options) {
|
|
487
|
+
const { limit = 100, linkedinAccountId } = options || {};
|
|
488
|
+
(0, db_1.debugLogDbOperation)("select", "monitoring.mapping_jobs", { limit, linkedinAccountId, status: "pending" }, undefined, {
|
|
489
|
+
operation: "getPendingMappingJobs",
|
|
490
|
+
});
|
|
491
|
+
try {
|
|
492
|
+
const sql = linkedinAccountId
|
|
493
|
+
? `
|
|
494
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
495
|
+
FROM monitoring.mapping_jobs
|
|
496
|
+
WHERE started_at IS NULL AND linkedin_account_id = $1
|
|
497
|
+
ORDER BY queued_at ASC
|
|
498
|
+
LIMIT $2
|
|
499
|
+
`
|
|
500
|
+
: `
|
|
501
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
502
|
+
FROM monitoring.mapping_jobs
|
|
503
|
+
WHERE started_at IS NULL
|
|
504
|
+
ORDER BY queued_at ASC
|
|
505
|
+
LIMIT $1
|
|
506
|
+
`;
|
|
507
|
+
const params = linkedinAccountId ? [linkedinAccountId, limit] : [limit];
|
|
508
|
+
return await (0, pg_client_1.query)(db, sql, params);
|
|
509
|
+
}
|
|
510
|
+
catch (error) {
|
|
511
|
+
console.error("Error getting pending mapping jobs:", error);
|
|
512
|
+
throw error;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Get running mapping jobs (started but not completed)
|
|
517
|
+
*/
|
|
518
|
+
async function getRunningMappingJobs(db, options) {
|
|
519
|
+
const { limit = 100, linkedinAccountId } = options || {};
|
|
520
|
+
(0, db_1.debugLogDbOperation)("select", "monitoring.mapping_jobs", { limit, linkedinAccountId, status: "running" }, undefined, {
|
|
521
|
+
operation: "getRunningMappingJobs",
|
|
522
|
+
});
|
|
523
|
+
try {
|
|
524
|
+
const sql = linkedinAccountId
|
|
525
|
+
? `
|
|
526
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
527
|
+
FROM monitoring.mapping_jobs
|
|
528
|
+
WHERE started_at IS NOT NULL AND completed_at IS NULL AND linkedin_account_id = $1
|
|
529
|
+
ORDER BY started_at ASC
|
|
530
|
+
LIMIT $2
|
|
531
|
+
`
|
|
532
|
+
: `
|
|
533
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
534
|
+
FROM monitoring.mapping_jobs
|
|
535
|
+
WHERE started_at IS NOT NULL AND completed_at IS NULL
|
|
536
|
+
ORDER BY started_at ASC
|
|
537
|
+
LIMIT $1
|
|
538
|
+
`;
|
|
539
|
+
const params = linkedinAccountId ? [linkedinAccountId, limit] : [limit];
|
|
540
|
+
return await (0, pg_client_1.query)(db, sql, params);
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
console.error("Error getting running mapping jobs:", error);
|
|
544
|
+
throw error;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Get completed mapping jobs
|
|
549
|
+
*/
|
|
550
|
+
async function getCompletedMappingJobs(db, options) {
|
|
551
|
+
const { limit = 100, linkedinAccountId, since } = options || {};
|
|
552
|
+
(0, db_1.debugLogDbOperation)("select", "monitoring.mapping_jobs", { limit, linkedinAccountId, since, status: "completed" }, undefined, {
|
|
553
|
+
operation: "getCompletedMappingJobs",
|
|
554
|
+
});
|
|
555
|
+
try {
|
|
556
|
+
let sql = `
|
|
557
|
+
SELECT id, linkedin_account_id, company_mapping_job_id, metadata, created_at, queued_at, started_at, completed_at
|
|
558
|
+
FROM monitoring.mapping_jobs
|
|
559
|
+
WHERE completed_at IS NOT NULL
|
|
560
|
+
`;
|
|
561
|
+
const params = [];
|
|
562
|
+
let paramIndex = 1;
|
|
563
|
+
if (linkedinAccountId) {
|
|
564
|
+
sql += ` AND linkedin_account_id = $${paramIndex}`;
|
|
565
|
+
params.push(linkedinAccountId);
|
|
566
|
+
paramIndex++;
|
|
567
|
+
}
|
|
568
|
+
if (since) {
|
|
569
|
+
sql += ` AND completed_at >= $${paramIndex}`;
|
|
570
|
+
params.push(since);
|
|
571
|
+
paramIndex++;
|
|
572
|
+
}
|
|
573
|
+
sql += ` ORDER BY completed_at DESC LIMIT $${paramIndex}`;
|
|
574
|
+
params.push(limit);
|
|
575
|
+
return await (0, pg_client_1.query)(db, sql, params);
|
|
576
|
+
}
|
|
577
|
+
catch (error) {
|
|
578
|
+
console.error("Error getting completed mapping jobs:", error);
|
|
579
|
+
throw error;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Get relationship scores for a mapping job
|
|
584
|
+
*/
|
|
585
|
+
async function getRelationshipScoresForMappingJob(db, mappingJobId, options) {
|
|
586
|
+
const { limit = 50, minScore } = options || {};
|
|
587
|
+
(0, db_1.debugLogDbOperation)("select", "linkedin.relationships", { mappingJobId, limit, minScore }, undefined, {
|
|
588
|
+
operation: "getRelationshipScoresForMappingJob",
|
|
589
|
+
mappingJobId,
|
|
590
|
+
});
|
|
591
|
+
try {
|
|
592
|
+
const sql = minScore !== undefined
|
|
593
|
+
? `
|
|
594
|
+
SELECT id, linkedin_account_id_a, linkedin_account_id_b, score, model_version, analysis_type, mapping_job_id, metadata, created_at
|
|
595
|
+
FROM linkedin.relationships
|
|
596
|
+
WHERE mapping_job_id = $1 AND score >= $2
|
|
597
|
+
ORDER BY score DESC
|
|
598
|
+
LIMIT $3
|
|
599
|
+
`
|
|
600
|
+
: `
|
|
601
|
+
SELECT id, linkedin_account_id_a, linkedin_account_id_b, score, model_version, analysis_type, mapping_job_id, metadata, created_at
|
|
602
|
+
FROM linkedin.relationships
|
|
603
|
+
WHERE mapping_job_id = $1
|
|
604
|
+
ORDER BY score DESC
|
|
605
|
+
LIMIT $2
|
|
606
|
+
`;
|
|
607
|
+
const params = minScore !== undefined ? [mappingJobId, minScore, limit] : [mappingJobId, limit];
|
|
608
|
+
return await (0, pg_client_1.query)(db, sql, params);
|
|
609
|
+
}
|
|
610
|
+
catch (error) {
|
|
611
|
+
console.error("Error getting relationship scores for mapping job:", error);
|
|
612
|
+
throw error;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Gets enriched relationship scores for a specific mapping job with LinkedIn account details
|
|
617
|
+
* This function properly filters by mapping job ID at the database level (avoiding the bug
|
|
618
|
+
* where getRelationshipScoresForAccount followed by client-side filtering would miss records)
|
|
619
|
+
*
|
|
620
|
+
* @param db - Database instance
|
|
621
|
+
* @param mappingJobId - The mapping job ID to filter by
|
|
622
|
+
* @param mainLinkedinAccountId - The main LinkedIn account ID (to determine which is the "other" account)
|
|
623
|
+
* @param options - Query options
|
|
624
|
+
* @returns Promise resolving to array of enriched relationship scores
|
|
625
|
+
*/
|
|
626
|
+
async function getEnrichedRelationshipScoresForMappingJob(db, mappingJobId, mainLinkedinAccountId, options) {
|
|
627
|
+
const { limit = 50, minScore, sortOrder = "desc" } = options || {};
|
|
628
|
+
(0, db_1.debugLogDbOperation)("select", "linkedin.relationships + linkedin.accounts", { mappingJobId, mainLinkedinAccountId, limit, minScore }, undefined, {
|
|
629
|
+
operation: "getEnrichedRelationshipScoresForMappingJob",
|
|
630
|
+
mappingJobId,
|
|
631
|
+
mainLinkedinAccountId,
|
|
632
|
+
});
|
|
633
|
+
try {
|
|
634
|
+
let sql = `
|
|
635
|
+
SELECT
|
|
636
|
+
r.score,
|
|
637
|
+
r.model_version,
|
|
638
|
+
r.analysis_type,
|
|
639
|
+
r.mapping_job_id,
|
|
640
|
+
r.metadata,
|
|
641
|
+
r.created_at,
|
|
642
|
+
CASE
|
|
643
|
+
WHEN r.linkedin_account_id_a = $2
|
|
644
|
+
THEN r.linkedin_account_id_b
|
|
645
|
+
ELSE r.linkedin_account_id_a
|
|
646
|
+
END as other_account_id,
|
|
647
|
+
CASE
|
|
648
|
+
WHEN r.linkedin_account_id_a = $2
|
|
649
|
+
THEN account_b.linkedin_identifier_acoa
|
|
650
|
+
ELSE account_a.linkedin_identifier_acoa
|
|
651
|
+
END as other_account_linkedin_identifier_acoa,
|
|
652
|
+
CASE
|
|
653
|
+
WHEN r.linkedin_account_id_a = $2
|
|
654
|
+
THEN account_b.public_identifier
|
|
655
|
+
ELSE account_a.public_identifier
|
|
656
|
+
END as other_account_public_identifier,
|
|
657
|
+
CASE
|
|
658
|
+
WHEN r.linkedin_account_id_a = $2
|
|
659
|
+
THEN account_b.first_name
|
|
660
|
+
ELSE account_a.first_name
|
|
661
|
+
END as other_account_first_name,
|
|
662
|
+
CASE
|
|
663
|
+
WHEN r.linkedin_account_id_a = $2
|
|
664
|
+
THEN account_b.last_name
|
|
665
|
+
ELSE account_a.last_name
|
|
666
|
+
END as other_account_last_name,
|
|
667
|
+
CASE
|
|
668
|
+
WHEN r.linkedin_account_id_a = $2
|
|
669
|
+
THEN account_b.headline
|
|
670
|
+
ELSE account_a.headline
|
|
671
|
+
END as other_account_headline,
|
|
672
|
+
CASE
|
|
673
|
+
WHEN r.linkedin_account_id_a = $2
|
|
674
|
+
THEN account_b.profile_image_cloudfront_url
|
|
675
|
+
ELSE account_a.profile_image_cloudfront_url
|
|
676
|
+
END as other_account_profile_picture_url
|
|
677
|
+
FROM linkedin.relationships r
|
|
678
|
+
INNER JOIN linkedin.accounts account_a ON r.linkedin_account_id_a = account_a.id
|
|
679
|
+
INNER JOIN linkedin.accounts account_b ON r.linkedin_account_id_b = account_b.id
|
|
680
|
+
WHERE r.mapping_job_id = $1
|
|
681
|
+
`;
|
|
682
|
+
const params = [mappingJobId, mainLinkedinAccountId];
|
|
683
|
+
let paramIndex = 3;
|
|
684
|
+
if (minScore !== undefined) {
|
|
685
|
+
sql += ` AND r.score >= $${paramIndex}`;
|
|
686
|
+
params.push(minScore);
|
|
687
|
+
paramIndex++;
|
|
688
|
+
}
|
|
689
|
+
sql += ` ORDER BY r.score ${sortOrder === "desc" ? "DESC" : "ASC"} LIMIT $${paramIndex}`;
|
|
690
|
+
params.push(limit);
|
|
691
|
+
const results = await (0, pg_client_1.query)(db, sql, params);
|
|
692
|
+
return results.map(result => ({
|
|
693
|
+
score: result.score,
|
|
694
|
+
modelVersion: result.model_version,
|
|
695
|
+
analysisType: result.analysis_type,
|
|
696
|
+
mappingJobId: result.mapping_job_id,
|
|
697
|
+
metadata: result.metadata,
|
|
698
|
+
createdAt: result.created_at,
|
|
699
|
+
otherAccount: {
|
|
700
|
+
id: result.other_account_id,
|
|
701
|
+
linkedinIdentifierAcoa: result.other_account_linkedin_identifier_acoa,
|
|
702
|
+
publicIdentifier: result.other_account_public_identifier,
|
|
703
|
+
firstName: result.other_account_first_name,
|
|
704
|
+
lastName: result.other_account_last_name,
|
|
705
|
+
headline: result.other_account_headline,
|
|
706
|
+
profilePictureUrl: result.other_account_profile_picture_url,
|
|
707
|
+
},
|
|
708
|
+
}));
|
|
709
|
+
}
|
|
710
|
+
catch (error) {
|
|
711
|
+
console.error("Error getting enriched relationship scores for mapping job:", error);
|
|
712
|
+
throw error;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Delete a mapping job and all related data
|
|
717
|
+
*/
|
|
718
|
+
async function deleteMappingJob(db, mappingJobId) {
|
|
719
|
+
(0, db_1.debugLogDbOperation)("delete", "monitoring.mapping_jobs", { mappingJobId }, undefined, {
|
|
720
|
+
operation: "deleteMappingJob",
|
|
721
|
+
mappingJobId,
|
|
722
|
+
});
|
|
723
|
+
try {
|
|
724
|
+
const sql = `
|
|
725
|
+
DELETE FROM monitoring.mapping_jobs
|
|
726
|
+
WHERE id = $1
|
|
727
|
+
RETURNING id
|
|
728
|
+
`;
|
|
729
|
+
const result = await (0, pg_client_1.query)(db, sql, [mappingJobId]);
|
|
730
|
+
return result.length > 0;
|
|
731
|
+
}
|
|
732
|
+
catch (error) {
|
|
733
|
+
console.error("Error deleting mapping job:", error);
|
|
734
|
+
throw error;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
// =============================================================================
|
|
738
|
+
// LEGACY COMPATIBILITY (DEPRECATED)
|
|
739
|
+
// =============================================================================
|
|
740
|
+
/**
|
|
741
|
+
* @deprecated Use createMappingJobForLinkedInAccount instead
|
|
742
|
+
* This function is kept for backward compatibility but will be removed
|
|
743
|
+
*/
|
|
744
|
+
async function createMappingJobWithSingleLinkedInAccount(db, params) {
|
|
745
|
+
console.warn("createMappingJobWithSingleLinkedInAccount is deprecated. Use createMappingJobForLinkedInAccount instead.");
|
|
746
|
+
return await createMappingJobForLinkedInAccount(db, {
|
|
747
|
+
linkedinAccountId: params.linkedinAccountId,
|
|
748
|
+
jobMetadata: {
|
|
749
|
+
...params.jobMetadata,
|
|
750
|
+
...params.linkedinAccountMetadata,
|
|
751
|
+
},
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* @deprecated Use createMappingJobsForLinkedInAccounts instead
|
|
756
|
+
*/
|
|
757
|
+
async function createMappingJobWithLinkedInAccounts(db, params) {
|
|
758
|
+
console.warn("createMappingJobWithLinkedInAccounts is deprecated. Use createMappingJobsForLinkedInAccounts instead.");
|
|
759
|
+
return await createMappingJobsForLinkedInAccounts(db, params.linkedinAccounts.map(acc => ({
|
|
760
|
+
linkedinAccountId: acc.linkedinAccountId,
|
|
761
|
+
metadata: {
|
|
762
|
+
...params.jobMetadata,
|
|
763
|
+
...acc.metadata,
|
|
764
|
+
},
|
|
765
|
+
})));
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Check if a target LinkedIn profile has been mapped before
|
|
769
|
+
* Uses UNION query to check both on-demand and regular mapping jobs
|
|
770
|
+
*
|
|
771
|
+
* @param db - Database connection
|
|
772
|
+
* @param targetLinkedInIdentifier - LinkedIn identifier (ACoA format) to check
|
|
773
|
+
* @returns Promise<MappingAvailabilityResult> - Availability information
|
|
774
|
+
*/
|
|
775
|
+
async function checkMappingAvailability(db, targetLinkedInIdentifier) {
|
|
776
|
+
// First check if the target LinkedIn account exists
|
|
777
|
+
const targetCheckSql = `
|
|
778
|
+
SELECT id, linkedin_identifier_acoa
|
|
779
|
+
FROM linkedin.accounts
|
|
780
|
+
WHERE linkedin_identifier_acoa = $1
|
|
781
|
+
LIMIT 1
|
|
782
|
+
`;
|
|
783
|
+
const targetAccount = await (0, pg_client_1.query)(db, targetCheckSql, [targetLinkedInIdentifier]);
|
|
784
|
+
const targetExists = targetAccount.length > 0;
|
|
785
|
+
// Check for existing mappings using UNION of both tables
|
|
786
|
+
const mappingCheckSql = `
|
|
787
|
+
-- Check on-demand mapping jobs by internal_identifier_acoa
|
|
788
|
+
SELECT
|
|
789
|
+
'on_demand' as source,
|
|
790
|
+
odmj.id as job_id,
|
|
791
|
+
odmj.created_at,
|
|
792
|
+
mj.completed_at
|
|
793
|
+
FROM monitoring.on_demand_mapping_jobs odmj
|
|
794
|
+
LEFT JOIN monitoring.mapping_jobs mj ON odmj.mapping_job_id = mj.id
|
|
795
|
+
WHERE odmj.internal_identifier_acoa = $1
|
|
796
|
+
|
|
797
|
+
UNION ALL
|
|
798
|
+
|
|
799
|
+
-- Check regular mapping jobs by target LinkedIn account
|
|
800
|
+
SELECT
|
|
801
|
+
'regular' as source,
|
|
802
|
+
mj.id as job_id,
|
|
803
|
+
mj.created_at,
|
|
804
|
+
mj.completed_at
|
|
805
|
+
FROM monitoring.mapping_jobs mj
|
|
806
|
+
JOIN linkedin.accounts la ON mj.linkedin_account_id = la.id
|
|
807
|
+
WHERE la.linkedin_identifier_acoa = $1
|
|
808
|
+
|
|
809
|
+
ORDER BY created_at DESC
|
|
810
|
+
LIMIT 1
|
|
811
|
+
`;
|
|
812
|
+
const mappingCheck = await (0, pg_client_1.query)(db, mappingCheckSql, [
|
|
813
|
+
targetLinkedInIdentifier,
|
|
814
|
+
]);
|
|
815
|
+
const hasExistingMapping = mappingCheck.length > 0;
|
|
816
|
+
let mappingDetails = undefined;
|
|
817
|
+
if (hasExistingMapping) {
|
|
818
|
+
const row = mappingCheck[0];
|
|
819
|
+
mappingDetails = {
|
|
820
|
+
source: row.source,
|
|
821
|
+
jobId: Number(row.job_id),
|
|
822
|
+
createdAt: new Date(row.created_at),
|
|
823
|
+
completedAt: row.completed_at ? new Date(row.completed_at) : null,
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
return {
|
|
827
|
+
isAvailable: targetExists && !hasExistingMapping,
|
|
828
|
+
targetExists,
|
|
829
|
+
hasExistingMapping,
|
|
830
|
+
mappingDetails,
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
//# sourceMappingURL=mapping-job-operations.js.map
|