/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/project-service.js (5973B)
const { prisma } = require("../lib/prisma"); const { buildEntitlements, assertWithinLimit } = require("../domain/entitlements"); const { writeAuditEvent } = require("./audit-service"); async function getLatestSubscription(organizationId) { return prisma.subscription.findFirst({ where: { organizationId }, orderBy: { createdAt: "desc" } }); } async function listWorkspaceProjects(workspaceId) { return prisma.project.findMany({ where: { workspaceId }, orderBy: { createdAt: "desc" } }); } async function createProject({ workspace, actor, payload, request }) { const subscription = await getLatestSubscription(workspace.organizationId); const organization = await prisma.organization.findUnique({ where: { id: workspace.organizationId } }); const entitlements = buildEntitlements(subscription, organization); const currentCount = await prisma.project.count({ where: { workspace: { organizationId: workspace.organizationId } } }); assertWithinLimit(entitlements, "projects", currentCount, 1); const project = await prisma.project.create({ data: { workspaceId: workspace.id, name: payload.name, subtitle: payload.subtitle || "COSMIC AI risk measurement workspace", projectType: payload.projectType || "AI-Enabler", currentLifecyclePhase: payload.currentLifecyclePhase || "Needs identification", riskAppetite: Number(payload.riskAppetite || 50), assessmentDate: payload.assessmentDate ? new Date(payload.assessmentDate) : new Date(), status: "Active", ownerDisplayName: payload.ownerDisplayName || actor.displayName, description: payload.description || "", thresholds: payload.thresholds || {}, reviews: payload.reviews || {} } }); await writeAuditEvent({ organizationId: workspace.organizationId, workspaceId: workspace.id, projectId: project.id, actorUserId: actor.id, entityType: "Project", entityId: project.id, action: "create", afterJson: project, request }); return project; } async function getProject(projectId) { const project = await prisma.project.findUnique({ where: { id: projectId }, include: { lifecyclePhases: { orderBy: { sequence: "asc" } }, risks: { include: { mitigations: true, evidence: true } }, indicators: true, experiments: { include: { metrics: true } } } }); if (!project) { const error = new Error(`Project not found: ${projectId}`); error.status = 404; throw error; } return project; } async function updateProject({ projectScope, actor, payload, request }) { const before = await prisma.project.findUnique({ where: { id: projectScope.project.id } }); const project = await prisma.project.update({ where: { id: projectScope.project.id }, data: { name: payload.name ?? before.name, subtitle: payload.subtitle ?? before.subtitle, projectType: payload.projectType ?? before.projectType, currentLifecyclePhase: payload.currentLifecyclePhase ?? before.currentLifecyclePhase, riskAppetite: payload.riskAppetite !== undefined ? Number(payload.riskAppetite) : before.riskAppetite, status: payload.status ?? before.status, ownerDisplayName: payload.ownerDisplayName ?? before.ownerDisplayName, description: payload.description ?? before.description, thresholds: payload.thresholds ?? before.thresholds, reviews: payload.reviews ?? before.reviews } }); await writeAuditEvent({ organizationId: projectScope.organization.id, workspaceId: projectScope.project.workspaceId, projectId: projectScope.project.id, actorUserId: actor.id, entityType: "Project", entityId: project.id, action: "update", beforeJson: before, afterJson: project, request }); return project; } async function deleteProject({ projectScope, projectId, actor, request }) { const before = await prisma.project.findUnique({ where: { id: projectId } }); if (!before) { const error = new Error(`Project not found: ${projectId}`); error.status = 404; throw error; } await writeAuditEvent({ organizationId: projectScope.organization.id, workspaceId: projectScope.project.workspaceId, projectId, actorUserId: actor.id, entityType: "Project", entityId: projectId, action: "delete", beforeJson: before, request }).catch(() => {}); const expIds = (await prisma.experiment.findMany({ where: { projectId }, select: { id: true } })).map(e => e.id); await prisma.modelMetric.deleteMany({ where: { experimentId: { in: expIds } } }); await prisma.auditEvent.deleteMany({ where: { projectId } }); await prisma.reportExport.deleteMany({ where: { projectId } }); await prisma.externalWorkItemMapping.deleteMany({ where: { projectId } }); await prisma.integrationSyncRun.deleteMany({ where: { projectId } }); const gateIds = (await prisma.gateEvaluation.findMany({ where: { projectId }, select: { id: true } })).map(g => g.id); await prisma.gateDecision.deleteMany({ where: { gateId: { in: gateIds } } }); await prisma.gateCriterion.deleteMany({ where: { gateId: { in: gateIds } } }); await prisma.gateEvaluation.deleteMany({ where: { projectId } }); await prisma.evidence.deleteMany({ where: { projectId } }); const riskIds = (await prisma.risk.findMany({ where: { projectId }, select: { id: true } })).map(r => r.id); await prisma.mitigation.deleteMany({ where: { riskId: { in: riskIds } } }); await prisma.risk.deleteMany({ where: { projectId } }); await prisma.experiment.deleteMany({ where: { projectId } }); await prisma.lifecyclePhase.deleteMany({ where: { projectId } }); await prisma.indicator.deleteMany({ where: { projectId } }); await prisma.project.delete({ where: { id: projectId } }); return { deleted: true }; } module.exports = { getLatestSubscription, listWorkspaceProjects, createProject, getProject, updateProject, deleteProject };