feat: Equipment-System, Buchungsbearbeitung, Kundenadresse, LexOffice-Fix
- Vintage Modell hinzugefuegt - Equipment Multi-Select (Neue Buchung + Bearbeitung) - Kundenadresse in Formularen - Bearbeiten-Seite fuer Buchungen - Abbau-Zeiten in Formularen und Uebersicht - Vertrag PDF nur bei Privatkunden - LexOffice Kontakt-Erstellung Fix (BUSINESS) - Zurueck-Pfeil auf Touren-Seite
This commit is contained in:
175
app/api/bookings/[id]/confirm/route.ts
Normal file
175
app/api/bookings/[id]/confirm/route.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getServerSession } from 'next-auth';
|
||||
import { authOptions } from '@/lib/auth';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { lexofficeService } from '@/lib/lexoffice';
|
||||
import { nextcloudCalendar } from '@/lib/nextcloud-calendar';
|
||||
|
||||
export async function POST(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
|
||||
if (!session || session.user.role !== 'ADMIN') {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const bookingId = params.id;
|
||||
|
||||
const booking = await prisma.booking.findUnique({
|
||||
where: { id: bookingId },
|
||||
include: {
|
||||
location: true,
|
||||
photobox: true,
|
||||
bookingEquipment: {
|
||||
include: {
|
||||
equipment: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!booking) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Buchung nicht gefunden' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
if (booking.status === 'CONFIRMED') {
|
||||
return NextResponse.json(
|
||||
{ error: 'Buchung ist bereits bestätigt' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
if (!booking.contractSigned) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Vertrag muss zuerst unterschrieben werden' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`🔄 Bestätige Buchung ${booking.bookingNumber}...`);
|
||||
|
||||
let lexofficeConfirmationId = null;
|
||||
|
||||
if (booking.lexofficeContactId) {
|
||||
try {
|
||||
console.log(' 💼 Erstelle LexOffice Auftragsbestätigung...');
|
||||
|
||||
lexofficeConfirmationId = await lexofficeService.createConfirmationFromBooking(
|
||||
booking,
|
||||
booking.lexofficeContactId
|
||||
);
|
||||
|
||||
console.log(` ✅ Auftragsbestätigung erstellt: ${lexofficeConfirmationId}`);
|
||||
} catch (error: any) {
|
||||
console.error(' ❌ LexOffice Fehler:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
const updatedBooking = await prisma.booking.update({
|
||||
where: { id: bookingId },
|
||||
data: {
|
||||
status: 'CONFIRMED',
|
||||
lexofficeConfirmationId,
|
||||
confirmationSentAt: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
console.log(' 📅 Update Nextcloud Kalender...');
|
||||
await nextcloudCalendar.syncBookingToCalendar(updatedBooking);
|
||||
console.log(' ✅ Kalender aktualisiert');
|
||||
} catch (error: any) {
|
||||
console.error(' ❌ Kalender-Update Fehler:', error.message);
|
||||
}
|
||||
|
||||
await prisma.notification.create({
|
||||
data: {
|
||||
type: 'BOOKING_CONFIRMED',
|
||||
title: 'Buchung bestätigt',
|
||||
message: `Buchung ${booking.bookingNumber} für ${booking.customerName} wurde von Admin bestätigt.`,
|
||||
metadata: {
|
||||
bookingId: booking.id,
|
||||
bookingNumber: booking.bookingNumber,
|
||||
lexofficeConfirmationId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`✅ Buchung bestätigt: ${booking.bookingNumber}`);
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
booking: {
|
||||
id: updatedBooking.id,
|
||||
bookingNumber: updatedBooking.bookingNumber,
|
||||
status: updatedBooking.status,
|
||||
confirmationSentAt: updatedBooking.confirmationSentAt,
|
||||
lexofficeConfirmationId: updatedBooking.lexofficeConfirmationId,
|
||||
},
|
||||
});
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('❌ Bestätigungs-Fehler:', error);
|
||||
return NextResponse.json(
|
||||
{ error: error.message || 'Bestätigung fehlgeschlagen' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
|
||||
if (!session || session.user.role !== 'ADMIN') {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const bookingId = params.id;
|
||||
|
||||
const booking = await prisma.booking.findUnique({
|
||||
where: { id: bookingId },
|
||||
select: {
|
||||
id: true,
|
||||
bookingNumber: true,
|
||||
status: true,
|
||||
contractSigned: true,
|
||||
contractSignedAt: true,
|
||||
confirmationSentAt: true,
|
||||
lexofficeContactId: true,
|
||||
lexofficeOfferId: true,
|
||||
lexofficeConfirmationId: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!booking) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Buchung nicht gefunden' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
const canConfirm = booking.status !== 'CONFIRMED' && booking.contractSigned;
|
||||
|
||||
return NextResponse.json({
|
||||
booking,
|
||||
canConfirm,
|
||||
});
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('❌ Buchungs-Status Fehler:', error);
|
||||
return NextResponse.json(
|
||||
{ error: error.message || 'Fehler beim Abrufen des Status' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user