import { NextRequest, NextResponse } from 'next/server'; import { nocodbClient } from '@/api/nocodbClient'; import type { OrderFilters } from '@/api/nocodbClient'; import * as XLSX from 'xlsx'; import Papa from 'papaparse'; /** * GET /api/admin/orders/export * Export orders to CSV or Excel * Query params: * - format: 'csv' | 'xlsx' (default: csv) * - status: Filter by status * - dateFrom, dateTo: Date range filter */ export async function GET(request: NextRequest) { try { const searchParams = request.nextUrl.searchParams; const format = searchParams.get('format') || 'csv'; // Build filters (same as orders list) const filters: OrderFilters = {}; if (searchParams.get('status')) filters.status = searchParams.get('status')!; if (searchParams.get('dateFrom')) filters.dateFrom = searchParams.get('dateFrom')!; if (searchParams.get('dateTo')) filters.dateTo = searchParams.get('dateTo')!; // Get all matching orders (no pagination for export) const response = await nocodbClient.getOrders(filters, { limit: 10000 }); const orders = response.list; // Transform data for export const exportData = orders.map((order) => ({ 'Order ID': order.orderId, 'Status': order.status, 'Created Date': order.CreatedAt ? new Date(order.CreatedAt).toLocaleDateString() : '', 'Vessel Name': order.vesselName, 'IMO Number': order.imoNumber || '', 'Distance (NM)': order.distance || '', 'Avg Speed (kn)': order.avgSpeed || '', 'CO2 Tons': order.co2Tons || '', 'Total Amount': order.totalAmount || '', 'Currency': order.currency || '', 'Customer Name': order.customerName || '', 'Customer Email': order.customerEmail || '', 'Customer Company': order.customerCompany || '', 'Departure Port': order.departurePort || '', 'Arrival Port': order.arrivalPort || '', 'Payment Method': order.paymentMethod || '', 'Payment Reference': order.paymentReference || '', 'Wren Order ID': order.wrenOrderId || '', 'Certificate URL': order.certificateUrl || '', 'Fulfilled At': order.fulfilledAt ? new Date(order.fulfilledAt).toLocaleDateString() : '', 'Notes': order.notes || '', })); if (format === 'xlsx') { // Generate Excel file const worksheet = XLSX.utils.json_to_sheet(exportData); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Orders'); // Style headers (make them bold) const range = XLSX.utils.decode_range(worksheet['!ref'] || 'A1'); for (let col = range.s.c; col <= range.e.c; col++) { const cellAddress = XLSX.utils.encode_cell({ r: 0, c: col }); if (!worksheet[cellAddress]) continue; worksheet[cellAddress].s = { font: { bold: true }, fill: { fgColor: { rgb: 'D3D3D3' } }, }; } // Set column widths worksheet['!cols'] = [ { wch: 20 }, // Order ID { wch: 12 }, // Status { wch: 15 }, // Created Date { wch: 25 }, // Vessel Name { wch: 12 }, // IMO Number { wch: 12 }, // Distance { wch: 12 }, // Avg Speed { wch: 10 }, // CO2 Tons { wch: 12 }, // Total Amount { wch: 10 }, // Currency { wch: 20 }, // Customer Name { wch: 25 }, // Customer Email { wch: 25 }, // Customer Company { wch: 20 }, // Departure Port { wch: 20 }, // Arrival Port { wch: 15 }, // Payment Method { wch: 20 }, // Payment Reference { wch: 20 }, // Wren Order ID { wch: 30 }, // Certificate URL { wch: 15 }, // Fulfilled At { wch: 40 }, // Notes ]; // Generate buffer const buffer = XLSX.write(workbook, { type: 'buffer', bookType: 'xlsx' }); // Return Excel file return new NextResponse(buffer, { status: 200, headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Content-Disposition': `attachment; filename="puffin-orders-${Date.now()}.xlsx"`, }, }); } else { // Generate CSV const csv = Papa.unparse(exportData); // Return CSV file return new NextResponse(csv, { status: 200, headers: { 'Content-Type': 'text/csv', 'Content-Disposition': `attachment; filename="puffin-orders-${Date.now()}.csv"`, }, }); } } catch (error) { console.error('Error exporting orders:', error); return NextResponse.json( { success: false, error: error instanceof Error ? error.message : 'Failed to export orders', }, { status: 500 } ); } }