source: src/app/api/invoices/[id]/route.ts@ 057453c

main
Last change on this file since 057453c was 057453c, checked in by Naum Shapkarovski <naumshapkarovski@…>, 5 weeks ago

feat: implement employees

  • Property mode set to 100644
File size: 6.1 KB
Line 
1import { NextRequest, NextResponse } from 'next/server';
2import { invoiceSchema, updateInvoiceSchema } from 'src/schemas';
3import prisma from 'src/lib/prisma';
4import { authenticateRequest } from 'src/lib/auth-middleware';
5import { Prisma } from '@prisma/client';
6
7export async function GET(request: NextRequest, { params }: { params: { id: string } }) {
8 try {
9 // Validate ID format
10 if (!params.id || !/^[0-9a-fA-F-]+$/.test(params.id)) {
11 return NextResponse.json({ error: 'Invalid invoice ID format' }, { status: 400 });
12 }
13
14 // Authenticate request
15 const authResult = await authenticateRequest(request);
16 if (authResult instanceof NextResponse) {
17 return authResult;
18 }
19 const { userId } = authResult;
20
21 // Fetch invoice with user check
22 const invoice = await prisma.invoice.findFirst({
23 where: {
24 id: params.id,
25 // invoiceFromId: userId,
26 },
27 include: {
28 invoiceFrom: true,
29 invoiceTo: true,
30 items: true,
31 },
32 });
33
34 if (!invoice) {
35 return NextResponse.json({ error: 'Invoice not found or access denied' }, { status: 404 });
36 }
37
38 return NextResponse.json(invoice);
39 } catch (error) {
40 console.error('Error fetching invoice:', error);
41
42 if (error instanceof Prisma.PrismaClientKnownRequestError) {
43 return NextResponse.json({ error: 'Database error occurred' }, { status: 500 });
44 }
45
46 return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
47 }
48}
49
50export async function PATCH(request: NextRequest, { params }: { params: { id: string } }) {
51 try {
52 // Validate ID format
53 if (!params.id || !/^[0-9a-fA-F-]+$/.test(params.id)) {
54 return NextResponse.json({ error: 'Invalid invoice ID format' }, { status: 400 });
55 }
56
57 // Authenticate request
58 const authResult = await authenticateRequest(request);
59 if (authResult instanceof NextResponse) {
60 return authResult;
61 }
62 const { userId } = authResult;
63
64 // Parse and validate request body
65 const body = await request.json();
66
67 const validation = updateInvoiceSchema.partial().safeParse(body);
68
69 if (!validation.success) {
70 return NextResponse.json(
71 { error: 'Invalid invoice data', details: validation.error.format() },
72 { status: 400 }
73 );
74 }
75
76 // Verify invoice exists and belongs to user
77 const existingInvoice = await prisma.invoice.findFirst({
78 where: {
79 id: params.id,
80 // invoiceFromId: userId,
81 },
82 });
83
84 if (!existingInvoice) {
85 return NextResponse.json({ error: 'Invoice not found or access denied' }, { status: 404 });
86 }
87
88 // Update invoice and related data
89 const updatedInvoice = await prisma.$transaction(async (tx) => {
90 // Conditionally delete and recreate items only if they are provided
91 if (validation.data.items) {
92 await tx.invoiceItem.deleteMany({
93 where: { invoiceId: params.id },
94 });
95 }
96
97 // Update the invoice and create new items if provided
98 return tx.invoice.update({
99 where: { id: params.id },
100 data: {
101 invoiceNumber: validation.data.invoiceNumber,
102 createDate: validation.data.createDate,
103 dueDate: validation.data.dueDate,
104 status: validation.data.status,
105 currency: validation.data.currency,
106 quantityType: validation.data.quantityType,
107 subTotal: validation.data.subTotal,
108 month: validation.data.month,
109 totalAmount: validation.data.totalAmount,
110 discount: validation.data.discount,
111 taxes: validation.data.taxes,
112 pdfRef: validation.data.pdfRef,
113 invoiceTo: {
114 update: validation.data.invoiceTo,
115 },
116 items: validation.data.items
117 ? {
118 create: validation.data.items.map((item) => ({
119 ...item,
120 service: {
121 connect: { id: item.service.id },
122 },
123 })),
124 }
125 : undefined,
126 },
127 include: {
128 invoiceFrom: true,
129 invoiceTo: true,
130 items: true,
131 },
132 });
133 });
134
135 return NextResponse.json(updatedInvoice);
136 } catch (error) {
137 console.error('Error updating invoice:', error);
138
139 if (error instanceof Prisma.PrismaClientKnownRequestError) {
140 return NextResponse.json({ error: 'Database error occurred' }, { status: 500 });
141 }
142
143 return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
144 }
145}
146
147export async function DELETE(request: NextRequest, { params }: { params: { id: string } }) {
148 try {
149 // Validate ID format
150 if (!params.id || !/^[0-9a-fA-F-]+$/.test(params.id)) {
151 return NextResponse.json({ error: 'Invalid invoice ID format' }, { status: 400 });
152 }
153
154 // Authenticate request
155 const authResult = await authenticateRequest(request);
156 if (authResult instanceof NextResponse) {
157 return authResult;
158 }
159 const { userId } = authResult;
160 console.log('userId', userId);
161
162 // Verify invoice exists and belongs to user
163 const existingInvoice = await prisma.invoice.findFirst({
164 where: {
165 id: params.id,
166 },
167 });
168
169 if (!existingInvoice) {
170 return NextResponse.json({ error: 'Invoice not found or access denied' }, { status: 404 });
171 }
172
173 // Delete invoice and related items in a transaction
174 await prisma.$transaction(async (tx) => {
175 // Delete related items first
176 await tx.invoiceItem.deleteMany({
177 where: { invoiceId: params.id },
178 });
179
180 // Delete the invoice
181 await tx.invoice.delete({
182 where: { id: params.id },
183 });
184 });
185
186 return NextResponse.json({ message: 'Invoice deleted successfully' }, { status: 200 });
187 } catch (error) {
188 console.error('Error deleting invoice:', error);
189
190 if (error instanceof Prisma.PrismaClientKnownRequestError) {
191 if (error.code === 'P2025') {
192 return NextResponse.json({ error: 'Invoice not found' }, { status: 404 });
193 }
194 return NextResponse.json({ error: 'Database error occurred' }, { status: 500 });
195 }
196
197 return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
198 }
199}
Note: See TracBrowser for help on using the repository browser.