-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathroute.ts
More file actions
129 lines (114 loc) · 4.32 KB
/
route.ts
File metadata and controls
129 lines (114 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { NextRequest, NextResponse } from 'next/server';
import { db, schema } from '@/db';
import { desc, gte, lte, ilike, and } from 'drizzle-orm';
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
// Parse query parameters
const page = parseInt(searchParams.get('page') || '1');
const limit = parseInt(searchParams.get('limit') || '10');
const vendor = searchParams.get('vendor');
const startDate = searchParams.get('startDate');
const endDate = searchParams.get('endDate');
const sortBy = searchParams.get('sortBy') || 'date';
const sortOrder = searchParams.get('sortOrder') || 'desc';
// Validate pagination parameters
const validatedPage = Math.max(1, page);
const validatedLimit = Math.min(100, Math.max(1, limit)); // Max 100 items per page
const offset = (validatedPage - 1) * validatedLimit;
// Build where conditions
const conditions = [];
if (vendor) {
conditions.push(ilike(schema.invoice.vendor, `%${vendor}%`));
}
if (startDate) {
const start = new Date(startDate);
if (!isNaN(start.getTime())) {
conditions.push(gte(schema.invoice.date, start));
}
}
if (endDate) {
const end = new Date(endDate);
if (!isNaN(end.getTime())) {
// Set to end of day
end.setHours(23, 59, 59, 999);
conditions.push(lte(schema.invoice.date, end));
}
}
const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
// Build order clause
let orderClause;
switch (sortBy) {
case 'invoiceNumber':
orderClause = sortOrder === 'asc'
? schema.invoice.invoiceNumber
: desc(schema.invoice.invoiceNumber);
break;
case 'vendor':
orderClause = sortOrder === 'asc'
? schema.invoice.vendor
: desc(schema.invoice.vendor);
break;
case 'totalAmount':
orderClause = sortOrder === 'asc'
? schema.invoice.totalAmount
: desc(schema.invoice.totalAmount);
break;
default: // date
orderClause = sortOrder === 'asc'
? schema.invoice.date
: desc(schema.invoice.date);
}
// Get total count for pagination
const [{ count }] = await db
.select({ count: schema.invoice.id })
.from(schema.invoice)
.where(whereClause);
// Get invoices with pagination
const invoices = await db
.select()
.from(schema.invoice)
.where(whereClause)
.orderBy(orderClause)
.limit(validatedLimit)
.offset(offset);
// Transform the response to include proper numeric values
const transformedInvoices = invoices.map(invoice => ({
id: invoice.id,
invoiceNumber: invoice.invoiceNumber,
date: invoice.date,
vendor: invoice.vendor,
totalAmount: parseFloat(invoice.totalAmount),
createdAt: invoice.createdAt,
updatedAt: invoice.updatedAt
}));
// Calculate pagination metadata
const totalPages = Math.ceil(parseInt(count) / validatedLimit);
const hasNextPage = validatedPage < totalPages;
const hasPrevPage = validatedPage > 1;
return NextResponse.json({
invoices: transformedInvoices,
pagination: {
page: validatedPage,
limit: validatedLimit,
total: parseInt(count),
totalPages,
hasNextPage,
hasPrevPage
},
filters: {
vendor,
startDate,
endDate,
sortBy,
sortOrder
}
});
} catch (error) {
console.error('Error fetching invoices:', error);
return NextResponse.json(
{ error: 'Failed to fetch invoices' },
{ status: 500 }
);
}
}