| import { NextRequest, NextResponse } from 'next/server'; |
| import { db } from '@/lib/db'; |
| import { getCookieToken, getSessionUser } from '@/lib/auth'; |
| import { logActivity } from '@/lib/activity'; |
|
|
| function escapeCsvField(value: unknown): string { |
| const str = value === null || value === undefined ? '' : String(value); |
| if (str.includes(',') || str.includes('"') || str.includes('\n')) { |
| return `"${str.replace(/"/g, '""')}"`; |
| } |
| return str; |
| } |
| |
| export async function GET(request: NextRequest) { |
| try { |
| const token = getCookieToken(request); |
| if (!token) { |
| return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); |
| } |
| const user = await getSessionUser(token); |
| if (!user) { |
| return NextResponse.json({ error: 'Not authenticated' }, { status: 401 }); |
| } |
| |
| const invoices = await db.invoice.findMany({ |
| where: { userId: user.id }, |
| orderBy: { createdAt: 'desc' }, |
| }); |
| |
| const headers = [ |
| 'ID', |
| 'Filename', |
| 'Vendor', |
| 'Invoice Number', |
| 'Invoice Date', |
| 'Due Date', |
| 'Subtotal', |
| 'VAT Amount', |
| 'Total', |
| 'Currency', |
| 'Status', |
| 'Duplicate', |
| 'Confidence', |
| 'Created At', |
| ]; |
| |
| const rows = invoices.map((inv) => |
| [ |
| inv.id, |
| inv.filename ?? '', |
| inv.vendor ?? '', |
| inv.invNumber ?? '', |
| inv.invDate ?? '', |
| inv.dueDate ?? '', |
| inv.amount ?? '', |
| inv.vatAmount ?? '', |
| inv.total ?? '', |
| inv.currency, |
| inv.status, |
| inv.isDuplicate ? 'Yes' : 'No', |
| inv.confidence !== null ? (inv.confidence * 100).toFixed(1) + '%' : '', |
| inv.createdAt.toISOString(), |
| ].map(escapeCsvField).join(',') |
| ); |
| |
| const csvContent = [ |
| headers.map(escapeCsvField).join(','), |
| ...rows, |
| ].join('\n'); |
| |
| const timestamp = new Date().toISOString().split('T')[0]; |
| |
| logActivity(user.id, 'export', 'CSV exported', 'Exported all invoices as CSV'); |
| |
| return new NextResponse(csvContent, { |
| status: 200, |
| headers: { |
| 'Content-Type': 'text/csv; charset=utf-8', |
| 'Content-Disposition': `attachment; filename="invoices-${timestamp}.csv"`, |
| }, |
| }); |
| } catch (error) { |
| console.error('[EXPORT_CSV_ERROR]', error); |
| return NextResponse.json( |
| { error: 'Internal server error' }, |
| { status: 500 } |
| ); |
| } |
| } |