feat: implement project export to Excel with API endpoint and UI button
This commit is contained in:
96
src/app/api/projects/export/route.js
Normal file
96
src/app/api/projects/export/route.js
Normal file
@@ -0,0 +1,96 @@
|
||||
// Force this API route to use Node.js runtime for database access and file operations
|
||||
export const runtime = "nodejs";
|
||||
|
||||
import * as XLSX from 'xlsx';
|
||||
import { getAllProjects } from "@/lib/queries/projects";
|
||||
import initializeDatabase from "@/lib/init-db";
|
||||
import { NextResponse } from "next/server";
|
||||
import { withReadAuth } from "@/lib/middleware/auth";
|
||||
import {
|
||||
logApiActionSafe,
|
||||
AUDIT_ACTIONS,
|
||||
RESOURCE_TYPES,
|
||||
} from "@/lib/auditLogSafe.js";
|
||||
|
||||
// Make sure the DB is initialized before queries run
|
||||
initializeDatabase();
|
||||
|
||||
async function exportProjectsHandler(req) {
|
||||
try {
|
||||
// Get all projects
|
||||
const projects = getAllProjects();
|
||||
|
||||
// Group projects by status
|
||||
const groupedProjects = projects.reduce((acc, project) => {
|
||||
const status = project.project_status || 'unknown';
|
||||
if (!acc[status]) {
|
||||
acc[status] = [];
|
||||
}
|
||||
acc[status].push({
|
||||
'Nazwa projektu': project.project_name,
|
||||
'Adres': project.address || '',
|
||||
'Działka': project.plot || '',
|
||||
'WP': project.wp || '',
|
||||
'Data zakończenia': project.finish_date || ''
|
||||
});
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Polish status translations for sheet names
|
||||
const statusTranslations = {
|
||||
'registered': 'Zarejestrowany',
|
||||
'in_progress_design': 'W realizacji (projektowanie)',
|
||||
'in_progress_construction': 'W realizacji (budowa)',
|
||||
'fulfilled': 'Zakończony',
|
||||
'cancelled': 'Wycofany',
|
||||
'unknown': 'Nieznany'
|
||||
};
|
||||
|
||||
// Create workbook
|
||||
const workbook = XLSX.utils.book_new();
|
||||
|
||||
// Create a sheet for each status
|
||||
Object.keys(groupedProjects).forEach(status => {
|
||||
const sheetName = statusTranslations[status] || status;
|
||||
const worksheet = XLSX.utils.json_to_sheet(groupedProjects[status]);
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
|
||||
});
|
||||
|
||||
// Generate buffer
|
||||
const buffer = XLSX.write(workbook, { type: 'buffer', bookType: 'xlsx' });
|
||||
|
||||
// Generate filename with current date
|
||||
const filename = `projects_export_${new Date().toISOString().split('T')[0]}.xlsx`;
|
||||
|
||||
// Log the export action
|
||||
await logApiActionSafe(
|
||||
req,
|
||||
AUDIT_ACTIONS.DATA_EXPORT,
|
||||
RESOURCE_TYPES.PROJECT,
|
||||
null,
|
||||
req.auth,
|
||||
{
|
||||
exportType: 'excel',
|
||||
totalProjects: projects.length,
|
||||
statuses: Object.keys(groupedProjects)
|
||||
}
|
||||
);
|
||||
|
||||
// Return the Excel file
|
||||
return new NextResponse(buffer, {
|
||||
headers: {
|
||||
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'Content-Disposition': `attachment; filename="${filename}"`,
|
||||
},
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error exporting projects to Excel:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to export projects' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const GET = withReadAuth(exportProjectsHandler);
|
||||
Reference in New Issue
Block a user