added place to telecommunication, added contract documents, added invoice to other contracts

This commit is contained in:
2026-03-25 16:55:48 +01:00
parent eaa94e766a
commit 3dd4f7b656
30 changed files with 3424 additions and 90 deletions
@@ -17,15 +17,17 @@ const invoiceTypeLabels: Record<InvoiceType, string> = {
};
interface InvoicesSectionProps {
ecdId: number; // energyContractDetailsId
ecdId?: number; // energyContractDetailsId (optional - für Energie-Verträge)
invoices: Invoice[];
contractId: number;
canEdit: boolean;
showInvoiceWarnings?: boolean; // Warnungen für fehlende Schluss-/Zwischenrechnung (nur Energie)
}
export default function InvoicesSection({
ecdId,
invoices,
showInvoiceWarnings = false,
contractId,
canEdit,
}: InvoicesSectionProps) {
@@ -35,9 +37,9 @@ export default function InvoicesSection({
const queryClient = useQueryClient();
const deleteInvoiceMutation = useMutation({
mutationFn: (invoiceId: number) => invoiceApi.deleteInvoice(ecdId, invoiceId),
mutationFn: (invoiceId: number) => ecdId ? invoiceApi.deleteInvoice(ecdId, invoiceId) : invoiceApi.deleteInvoice(0, invoiceId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['contract', contractId.toString()] });
queryClient.invalidateQueries({ queryKey: ['contract'] });
},
});
@@ -56,18 +58,18 @@ export default function InvoicesSection({
<FileText className="w-4 h-4 text-gray-500" />
<h4 className="text-sm font-medium text-gray-700">Rechnungen</h4>
<Badge variant="default">{invoices.length}</Badge>
{/* Status-Indicator */}
{hasFinalInvoice ? (
{/* Status-Indicator (nur bei Energie-Verträgen) */}
{showInvoiceWarnings && hasFinalInvoice ? (
<span className="flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-green-100 text-green-800">
<Check className="w-3 h-3" />
Schlussrechnung
</span>
) : hasNotAvailable ? (
) : showInvoiceWarnings && hasNotAvailable ? (
<span className="flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-yellow-100 text-yellow-800">
<AlertTriangle className="w-3 h-3" />
Nicht verfügbar
</span>
) : invoices.length > 0 ? (
) : showInvoiceWarnings && invoices.length > 0 ? (
<span className="flex items-center gap-1 px-2 py-0.5 text-xs rounded-full bg-orange-100 text-orange-800">
<AlertTriangle className="w-3 h-3" />
Schlussrechnung fehlt
@@ -198,7 +200,7 @@ function InvoiceModal({
}: {
isOpen: boolean;
onClose: () => void;
ecdId: number;
ecdId?: number;
contractId: number;
invoice?: Invoice | null;
}) {
@@ -216,10 +218,16 @@ function InvoiceModal({
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [error, setError] = useState<string | null>(null);
const addInvoiceFn = async (data: { invoiceDate: string; invoiceType: string; notes?: string }) => {
if (ecdId) {
return invoiceApi.addInvoice(ecdId, data as any);
}
return invoiceApi.addInvoiceByContract(contractId, data as any);
};
const createMutation = useMutation({
mutationFn: async (file: File) => {
// 1. Invoice erstellen
const result = await invoiceApi.addInvoice(ecdId, {
const result = await addInvoiceFn({
invoiceDate: formData.invoiceDate,
invoiceType: formData.invoiceType,
notes: formData.notes || undefined,
@@ -233,7 +241,7 @@ function InvoiceModal({
return result;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['contract', contractId.toString()] });
queryClient.invalidateQueries({ queryKey: ['contract'] });
onClose();
},
onError: (err: Error) => {
@@ -243,15 +251,14 @@ function InvoiceModal({
const createWithoutFileMutation = useMutation({
mutationFn: async () => {
// Für NOT_AVAILABLE Typ - kein Dokument erforderlich
return await invoiceApi.addInvoice(ecdId, {
return addInvoiceFn({
invoiceDate: formData.invoiceDate,
invoiceType: formData.invoiceType,
notes: formData.notes || undefined,
});
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['contract', contractId.toString()] });
queryClient.invalidateQueries({ queryKey: ['contract'] });
onClose();
},
onError: (err: Error) => {
@@ -262,7 +269,7 @@ function InvoiceModal({
const updateMutation = useMutation({
mutationFn: async (file: File | null) => {
// 1. Invoice aktualisieren
const result = await invoiceApi.updateInvoice(ecdId, invoice!.id, {
const result = await invoiceApi.updateInvoice(ecdId || 0, invoice!.id, {
invoiceDate: formData.invoiceDate,
invoiceType: formData.invoiceType,
notes: formData.notes || undefined,
@@ -276,7 +283,7 @@ function InvoiceModal({
return result;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['contract', contractId.toString()] });
queryClient.invalidateQueries({ queryKey: ['contract'] });
onClose();
},
onError: (err: Error) => {