182 lines
4.6 KiB
TypeScript
182 lines
4.6 KiB
TypeScript
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,
|
|
},
|
|
});
|
|
}
|