beginTransaction(); try { // Bezahlt-Status und Zahlungsdatum setzen $stmt = $pdo->prepare('UPDATE invoices SET paid = TRUE, payment_date = :pd WHERE id = :id'); $stmt->execute([':id' => $id, ':pd' => $payment_date]); // Automatisch Journalbuchung erstellen $existing = get_journal_entry_for_invoice($id); if (!$existing) { $entry_id = create_journal_entry_from_invoice($id); $msg = 'Rechnung als bezahlt markiert. Journalbuchung #' . $entry_id . ' erstellt.'; } else { $msg = 'Rechnung als bezahlt markiert (Journalbuchung existierte bereits).'; } $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); $msg = 'Fehler: ' . $e->getMessage(); } header('Location: ' . url_for('invoices.php?msg=' . urlencode($msg))); exit; } // Nachricht aus Redirect anzeigen if (isset($_GET['msg'])) { $msg = $_GET['msg']; } $filter_number = trim($_GET['number'] ?? ''); $filter_customer = trim($_GET['customer'] ?? ''); $filter_from = trim($_GET['from'] ?? ''); $filter_to = trim($_GET['to'] ?? ''); $where = "WHERE 1=1"; $params = []; if ($filter_number !== '') { $where .= " AND i.invoice_number ILIKE :num"; $params[':num'] = '%' . $filter_number . '%'; } if ($filter_customer !== '') { $where .= " AND c.name ILIKE :cust"; $params[':cust'] = '%' . $filter_customer . '%'; } if ($filter_from !== '') { $where .= " AND i.invoice_date >= :from"; $params[':from'] = $filter_from; } if ($filter_to !== '') { $where .= " AND i.invoice_date <= :to"; $params[':to'] = $filter_to; } try { $sql = "SELECT i.*, c.name AS customer_name, c.customer_number, COALESCE(i.is_storno, FALSE) AS is_storno, i.storno_of, storno_child.invoice_number AS storno_child_number, storno_child.id AS storno_child_id FROM invoices i JOIN customers c ON c.id = i.customer_id LEFT JOIN invoices storno_child ON storno_child.storno_of = i.id $where ORDER BY i.invoice_date DESC, i.id DESC"; $stmt = $pdo->prepare($sql); $stmt->execute($params); } catch (\PDOException $e) { // is_storno/storno_of noch nicht migriert — Fallback $sql = "SELECT i.*, c.name AS customer_name, c.customer_number, FALSE AS is_storno, NULL AS storno_of, NULL AS storno_child_number, NULL AS storno_child_id FROM invoices i JOIN customers c ON c.id = i.customer_id $where ORDER BY i.invoice_date DESC, i.id DESC"; $stmt = $pdo->prepare($sql); $stmt->execute($params); } $invoices = $stmt->fetchAll(PDO::FETCH_ASSOC); // Verknüpfte Journal-Einträge laden (nur wenn Spalte existiert) $journal_linked = []; try { $stmt_jl = $pdo->query("SELECT invoice_id, id FROM journal_entries WHERE invoice_id IS NOT NULL"); foreach ($stmt_jl->fetchAll(PDO::FETCH_ASSOC) as $jl) { $journal_linked[(int)$jl['invoice_id']] = (int)$jl['id']; } } catch (PDOException $e) { // Spalte invoice_id existiert noch nicht - ignorieren } // Mahnungen pro Rechnung laden $mahnungen_count = []; try { $stmt_m = $pdo->query("SELECT invoice_id, COUNT(*) AS cnt, MAX(level) AS max_level FROM mahnungen GROUP BY invoice_id"); foreach ($stmt_m->fetchAll(PDO::FETCH_ASSOC) as $m) { $mahnungen_count[(int)$m['invoice_id']] = ['cnt' => $m['cnt'], 'level' => $m['max_level']]; } } catch (PDOException $e) { // Tabelle noch nicht migriert } ?> Rechnungen

PIRP

Übersicht Neue Rechnung Abo-Rechnungen

Zurücksetzen Export CSV
>
Datum Nr. Kunde Betrag (brutto) Status Aktion
STORNO storniert M PDF | bezahlt | Mahnung | Journal | Storno
Keine Rechnungen gefunden.