import { InvoiceType } from '@prisma/client'; import prisma from '../lib/prisma.js'; import fs from 'fs'; import path from 'path'; export interface CreateInvoiceData { invoiceDate: Date; invoiceType: InvoiceType; documentPath?: string; notes?: string; } export interface UpdateInvoiceData { invoiceDate?: Date; invoiceType?: InvoiceType; documentPath?: string; notes?: string; } /** * Alle Rechnungen für ein EnergyContractDetails abrufen */ export async function getInvoices(energyContractDetailsId: number) { return prisma.invoice.findMany({ where: { energyContractDetailsId }, orderBy: { invoiceDate: 'desc' }, }); } /** * Einzelne Rechnung abrufen */ export async function getInvoice(energyContractDetailsId: number, invoiceId: number) { return prisma.invoice.findFirst({ where: { id: invoiceId, energyContractDetailsId }, }); } /** * Neue Rechnung hinzufügen * * Hinweis: Die Validierung ob ein Dokument vorhanden ist, erfolgt NICHT hier, * da der typische Flow so aussieht: * 1. Invoice erstellen (ohne Dokument) → Invoice-ID zurückbekommen * 2. Dokument hochladen mit der Invoice-ID * * Die Validierung ob alle Rechnungen Dokumente haben, erfolgt im Cockpit. */ export async function addInvoice(energyContractDetailsId: number, data: CreateInvoiceData) { // Prüfen ob EnergyContractDetails existiert const energyDetails = await prisma.energyContractDetails.findUnique({ where: { id: energyContractDetailsId }, }); if (!energyDetails) { throw new Error('Energievertrag nicht gefunden'); } return prisma.invoice.create({ data: { energyContractDetailsId, contractId: energyDetails.contractId, invoiceDate: data.invoiceDate, invoiceType: data.invoiceType, documentPath: data.documentPath, notes: data.notes, }, }); } /** * Rechnung direkt über contractId hinzufügen (für alle Vertragstypen) */ export async function addInvoiceByContract(contractId: number, data: CreateInvoiceData) { return prisma.invoice.create({ data: { contractId, invoiceDate: data.invoiceDate, invoiceType: data.invoiceType, documentPath: data.documentPath, notes: data.notes, }, }); } export async function getInvoicesByContract(contractId: number) { return prisma.invoice.findMany({ where: { contractId }, orderBy: { invoiceDate: 'desc' }, }); } /** * Rechnung aktualisieren */ export async function updateInvoice( energyContractDetailsId: number, invoiceId: number, data: UpdateInvoiceData ) { // Prüfen ob Rechnung existiert und zum EnergyContractDetails gehört const invoice = await prisma.invoice.findFirst({ where: { id: invoiceId, energyContractDetailsId }, }); if (!invoice) { throw new Error('Rechnung nicht gefunden'); } // Validierung bei Typ-Änderung const newType = data.invoiceType ?? invoice.invoiceType; const newPath = data.documentPath !== undefined ? data.documentPath : invoice.documentPath; if (newType !== 'NOT_AVAILABLE' && !newPath) { throw new Error('Dokument ist Pflicht (außer bei Typ "Nicht verfügbar")'); } return prisma.invoice.update({ where: { id: invoiceId }, data: { invoiceDate: data.invoiceDate, invoiceType: data.invoiceType, documentPath: data.documentPath, notes: data.notes, }, }); } /** * Rechnung löschen */ export async function deleteInvoice(energyContractDetailsId: number, invoiceId: number) { const invoice = await prisma.invoice.findFirst({ where: { id: invoiceId, energyContractDetailsId }, }); if (!invoice) { throw new Error('Rechnung nicht gefunden'); } // Datei löschen falls vorhanden if (invoice.documentPath) { const filePath = path.join(process.cwd(), invoice.documentPath); if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } } return prisma.invoice.delete({ where: { id: invoiceId } }); } /** * Rechnung direkt erstellen (für E-Mail-Integration) * Erstellt eine Rechnung mit bereits vorhandenem Dokument */ export async function createInvoiceWithDocument( energyContractDetailsId: number, invoiceDate: Date, invoiceType: InvoiceType, documentPath: string, notes?: string ) { // Prüfen ob EnergyContractDetails existiert const energyDetails = await prisma.energyContractDetails.findUnique({ where: { id: energyContractDetailsId }, }); if (!energyDetails) { throw new Error('Energievertrag nicht gefunden'); } return prisma.invoice.create({ data: { energyContractDetailsId, invoiceDate, invoiceType, documentPath, notes, }, }); }