// Force this API route to use Node.js runtime for database access export const runtime = "nodejs"; import { getProjectById, getProjectWithContract, updateProject, deleteProject, } from "@/lib/queries/projects"; import { logFieldChange } from "@/lib/queries/fieldHistory"; import { addNoteToProject } from "@/lib/queries/notes"; import initializeDatabase from "@/lib/init-db"; import { NextResponse } from "next/server"; import { withReadAuth, withUserAuth, withTeamLeadAuth } from "@/lib/middleware/auth"; import { logApiActionSafe, AUDIT_ACTIONS, RESOURCE_TYPES, } from "@/lib/auditLogSafe.js"; import { getUserLanguage, serverT } from "@/lib/serverTranslations"; // Make sure the DB is initialized before queries run initializeDatabase(); async function getProjectHandler(req, { params }) { const { id } = await params; const project = getProjectWithContract(parseInt(id)); if (!project) { return NextResponse.json({ error: "Project not found" }, { status: 404 }); } // Log project view await logApiActionSafe( req, AUDIT_ACTIONS.PROJECT_VIEW, RESOURCE_TYPES.PROJECT, id, req.auth, // Use req.auth instead of req.session { project_name: project.project_name } ); return NextResponse.json(project); } async function updateProjectHandler(req, { params }) { try { const { id } = await params; const data = await req.json(); // Get user ID from authenticated request const userId = req.user?.id; // Get original project data for audit log and field tracking const originalProject = getProjectById(parseInt(id)); if (!originalProject) { return NextResponse.json({ error: "Project not found" }, { status: 404 }); } // Track field changes for specific fields we want to monitor const fieldsToTrack = ['finish_date', 'project_status', 'assigned_to', 'contract_id', 'wartosc_zlecenia']; for (const fieldName of fieldsToTrack) { if (data.hasOwnProperty(fieldName)) { const oldValue = originalProject[fieldName]; const newValue = data[fieldName]; if (oldValue !== newValue) { try { logFieldChange('projects', parseInt(id), fieldName, oldValue, newValue, userId); } catch (error) { console.error(`Failed to log field change for ${fieldName}:`, error); } } } } // Special handling for project cancellation if (data.project_status === 'cancelled' && originalProject.project_status !== 'cancelled') { const now = new Date(); const cancellationDate = now.toLocaleDateString('pl-PL', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); const language = getUserLanguage(); const cancellationNote = `${serverT("Project cancelled on", language)} ${cancellationDate}`; try { addNoteToProject(parseInt(id), cancellationNote, userId, true); // true for is_system } catch (error) { console.error('Failed to log project cancellation:', error); } } updateProject(parseInt(id), data, userId); // Get updated project const updatedProject = getProjectById(parseInt(id)); // Log project update await logApiActionSafe( req, AUDIT_ACTIONS.PROJECT_UPDATE, RESOURCE_TYPES.PROJECT, id, req.auth, // Use req.auth instead of req.session { originalData: originalProject, updatedData: data, changedFields: Object.keys(data), } ); return NextResponse.json(updatedProject); } catch (error) { console.error("Error in updateProjectHandler:", error); return NextResponse.json( { error: "Internal server error", details: error.message }, { status: 500 } ); } } async function deleteProjectHandler(req, { params }) { const { id } = await params; // Get project data before deletion for audit log const project = getProjectById(parseInt(id)); deleteProject(parseInt(id)); // Log project deletion await logApiActionSafe( req, AUDIT_ACTIONS.PROJECT_DELETE, RESOURCE_TYPES.PROJECT, id, req.auth, // Use req.auth instead of req.session { deletedProject: { project_name: project?.project_name, project_number: project?.project_number, }, } ); return NextResponse.json({ success: true }); } // Protected routes - require authentication export const GET = withReadAuth(getProjectHandler); export const PUT = withUserAuth(updateProjectHandler); export const DELETE = withTeamLeadAuth(deleteProjectHandler);