test8 / src /app /api /invoices /export /csv /route.ts
simikkk's picture
Upload 93 files
eaab0a9 verified
Raw
History Blame Contribute Delete
2.63 kB
import { NextRequest, NextResponse } from 'next/server';
import { withDb } from '@/lib/api-handler';
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;
}
async function handler(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');
const response = new NextResponse(csvContent, {
status: 200,
headers: {
'Content-Type': 'text/csv; charset=utf-8',
'Content-Disposition': `attachment; filename="invoices-${timestamp}.csv"`,
},
});
response.headers.set('X-Content-Type-Options', 'nosniff');
response.headers.set('X-Frame-Options', 'DENY');
return response;
} catch (error) {
console.error('[EXPORT_CSV_ERROR]', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
export const GET = withDb(handler);