/home/techb158/cosmic-risk.abdallabala.com/src/services
NameSizeModeActions
audit-service.js6590644editdlrm
auth-service.js47790644editdlrm
dashboard-service.js11100644editdlrm
gate-service.js45120644editdlrm
import-service.js61950644editdlrm
integration-service.js166530644editdlrm
project-service.js59730644editdlrm
reporting-service.js86440644editdlrm
risk-service.js125050644editdlrm
sso-service.js31670644editdlrm
Edit: /home/techb158/cosmic-risk.abdallabala.com/src/services/import-service.js (6195B)
const { prisma } = require("../lib/prisma"); const { loadIntegrationCredentials } = require("./integration-service"); const { createPmClient, fetchIntegrationWorkItems } = require("../integrations/pm-clients"); const { externalStatusToLocalStatus, parseDimensionFromLabels, parsePhaseFromLabels } = require("../domain/integrations"); const { writeAuditEvent } = require("./audit-service"); async function getImportPreview(integrationId) { const integration = await prisma.integration.findUnique({ where: { id: integrationId }, include: { workspace: { include: { projects: { take: 1 } } } } }); if (!integration) { const error = new Error(`Integration not found: ${integrationId}`); error.status = 404; throw error; } const credentials = await loadIntegrationCredentials(integration); const items = await fetchIntegrationWorkItems(integration.provider, credentials, { [integration.provider === "TRELLO" ? "listId" : integration.provider === "JIRA" ? "projectKey" : integration.provider === "ASANA" ? "projectGid" : "planId"]: integration.externalProjectKey }); const existingMappings = await prisma.externalWorkItemMapping.findMany({ where: { integrationId }, select: { externalItemId: true } }); const existingIds = new Set(existingMappings.map(m => m.externalItemId)); const newItems = items.filter(item => !existingIds.has(item.id)); const existingItems = items.filter(item => existingIds.has(item.id)); return { provider: integration.provider, totalItems: items.length, newItems: newItems.length, existingItems: existingItems.length, preview: newItems.map(item => ({ externalId: item.id, title: item.title, description: (item.description || "").slice(0, 200), status: item.status || item.completed ? "Completed" : "Open", dueDate: item.dueDate || null, willCreate: true })) }; } async function pullFromProvider(integrationId, actor, request) { const integration = await prisma.integration.findUnique({ where: { id: integrationId }, include: { workspace: { include: { projects: { take: 1 } } } } }); if (!integration) { const error = new Error(`Integration not found: ${integrationId}`); error.status = 404; throw error; } const project = integration.workspace.projects[0]; if (!project) { const error = new Error("Workspace has no projects. Create a project before importing."); error.status = 400; throw error; } const credentials = await loadIntegrationCredentials(integration); const items = await fetchIntegrationWorkItems(integration.provider, credentials, { [integration.provider === "TRELLO" ? "listId" : integration.provider === "JIRA" ? "projectKey" : integration.provider === "ASANA" ? "projectGid" : "planId"]: integration.externalProjectKey }); const existingMappings = await prisma.externalWorkItemMapping.findMany({ where: { integrationId }, select: { externalItemId: true } }); const existingIds = new Set(existingMappings.map(m => m.externalItemId)); const startedAt = new Date(); let createdCount = 0; let skippedCount = 0; let failedCount = 0; const failureLog = []; for (const item of items) { if (existingIds.has(item.id)) { skippedCount++; continue; } const labels = item.labels || []; const dimension = parseDimensionFromLabels(labels); const lifecyclePhase = parsePhaseFromLabels(labels); const externalStatus = item.status || (item.completed ? "Completed" : "Open"); const localStatus = externalStatusToLocalStatus(integration.provider, externalStatus); try { const risk = await prisma.risk.create({ data: { projectId: project.id, title: item.title || "Imported item", description: item.description || "", dimension, domain: "Technical risks", lifecyclePhase, probability: 3, impact: 3, detectability: 3, status: localStatus, ownerDisplayName: item.assignee?.displayName || item.assignee?.name || null, dueDate: item.dueDate ? new Date(item.dueDate) : null } }); await prisma.externalWorkItemMapping.create({ data: { integrationId, projectId: project.id, localEntityType: "Risk", localEntityId: risk.id, localTitle: risk.title, externalItemType: integration.provider === "TRELLO" ? "Card" : integration.provider === "JIRA" ? "Issue" : "Task", externalItemId: item.id, externalItemKey: item.key || item.id, externalUrl: item.externalUrl || null, externalStatus, syncStatus: "Imported", lastSyncedAt: new Date(), fieldMapping: { source: "pull-import", externalItem: { id: item.id, title: item.title } } } }); createdCount++; } catch (err) { failedCount++; failureLog.push({ itemId: item.id, title: item.title, error: err.message }); } } const finishedAt = new Date(); const syncRun = await prisma.integrationSyncRun.create({ data: { integrationId, projectId: project.id, provider: integration.provider, status: failedCount > 0 ? "Partial" : "Completed", startedAt, finishedAt, createdCount, updatedCount: 0, failedCount, summary: `Pull import: ${createdCount} created, ${skippedCount} skipped, ${failedCount} failed.`, failureLog } }); await prisma.integration.update({ where: { id: integrationId }, data: { connectionStatus: "CONNECTED", lastSyncAt: new Date() } }); await writeAuditEvent({ organizationId: integration.workspace.organizationId, workspaceId: integration.workspaceId, actorUserId: actor?.id || null, entityType: "IntegrationSyncRun", entityId: syncRun.id, action: "pull-import", afterJson: { status: syncRun.status, createdCount, skippedCount, failedCount }, request }); return { syncRun, createdCount, skippedCount, failedCount }; } module.exports = { getImportPreview, pullFromProvider };