0 && $price >= 0) { $line_net = $qty * $price; $total_net += $line_net; $items[] = [ 'position_no' => count($items) + 1, 'description' => $desc, 'quantity' => $qty, 'unit_price' => $price, ]; } } if (empty($items)) { $error = 'Bitte mindestens eine Position ausfüllen.'; } else { if ($vat_mode === 'normal') { $total_vat = round($total_net * $vat_rate / 100, 2); } else { $total_vat = 0.0; } $total_gross = $total_net + $total_vat; $pdo->beginTransaction(); try { $invoice_number = generate_invoice_number(); $stmt = $pdo->prepare("INSERT INTO invoices (invoice_number, customer_id, invoice_date, service_date, vat_mode, vat_rate, payment_terms, notes_internal, total_net, total_vat, total_gross, paid) VALUES (:in, :cid, :idate, :sdate, :vm, :vr, :pt, :ni, :tn, :tv, :tg, FALSE) RETURNING id"); $stmt->execute([ ':in' => $invoice_number, ':cid' => $customer_id, ':idate'=> $invoice_date, ':sdate'=> $service_date, ':vm' => $vat_mode, ':vr' => $vat_rate, ':pt' => $settings['payment_terms'] ?? null, ':ni' => $notes_internal, ':tn' => $total_net, ':tv' => $total_vat, ':tg' => $total_gross, ]); $invoice_id = $stmt->fetchColumn(); $stmtItem = $pdo->prepare("INSERT INTO invoice_items (invoice_id, position_no, description, quantity, unit_price, vat_rate) VALUES (:iid, :pn, :d, :q, :up, :vr)"); foreach ($items as $it) { $stmtItem->execute([ ':iid' => $invoice_id, ':pn' => $it['position_no'], ':d' => $it['description'], ':q' => $it['quantity'], ':up' => $it['unit_price'], ':vr' => $vat_rate, ]); } $pdo->commit(); // PDF sofort archivieren (GoBD-konform) archive_invoice_pdf($invoice_id); header('Location: ' . url_for('invoice_pdf.php?id=' . $invoice_id)); exit; } catch (Exception $e) { $pdo->rollBack(); $error = 'Fehler beim Speichern der Rechnung: ' . $e->getMessage(); } } } } ?> Neue Rechnung

PIRP

Übersicht Neue Rechnung Abo-Rechnungen

Positionen

Pos. Beschreibung Menge Einzelpreis (netto)