"]; //@formatter:off protected array $columns = [ ['key' => 'id', 'text' => 'ID', 'table' => ['visible' => false], 'modal' => false], ['key' => 'invoice_number', 'text' => 'Rechnungsnr.', 'table' => ['sortable' => true, 'filter' => 'search']], ['key' => 'invoice_date', 'text' => 'Datum', 'type' => 'timestamp', 'table' => ['sortable' => true, 'filter' => 'date', 'formatter' => 'formatDate']], ['key' => 'company', 'text' => 'Firma', 'table' => ['sortable' => true, 'filter' => 'search']], ['key' => 'firstname', 'text' => 'Vorname', 'table' => ['visible' => false], 'modal' => false], ['key' => 'lastname', 'text' => 'Nachname', 'table' => ['visible' => false], 'modal' => false], ['key' => 'customer_number', 'text' => 'Kundennr.', 'table' => ['sortable' => true, 'filter' => 'search']], ['key' => 'total', 'text' => 'Netto', 'table' => ['sortable' => true, 'formatter' => 'formatPrice']], ['key' => 'total_gross', 'text' => 'Brutto', 'table' => ['sortable' => true, 'formatter' => 'formatPrice']], ['key' => 'billing_type', 'text' => 'Zahlungsart', 'table' => ['filter' => 'select', 'filterOptions' => [ ['value' => 'invoice', 'text' => 'Rechnung'], ['value' => 'sepa', 'text' => 'SEPA'], ]]], ['key' => 'actions', 'text' => 'Aktionen', 'modal' => false, 'table' => ['filter' => false, 'sortable' => false]], ]; //@formatter:on protected function createPDFAction($returnFilename = false) { // Get data from POST for preview or from database for saved invoice $post = json_decode(file_get_contents('php://input'), true); if (isset($post['preview']) && $post['preview'] === true) { // Create temporary invoice object from POST data for preview $invoice = (object)[]; $invoice->id = 0; $invoice->invoice_number = $post['invoice_number'] ?? null; $invoice->invoice_date = $post['invoice_date'] ?? time(); $invoice->customer_number = $post['customer_number'] ?? 0; $invoice->fibu_account_number = $post['fibu_account_number'] ?? 0; $invoice->company = $post['company'] ?? ''; $invoice->firstname = $post['firstname'] ?? ''; $invoice->lastname = $post['lastname'] ?? ''; $invoice->street = $post['street'] ?? ''; $invoice->zip = $post['zip'] ?? ''; $invoice->city = $post['city'] ?? ''; $invoice->country = $post['country'] ?? 'Österreich'; $invoice->email = $post['email'] ?? ''; $invoice->uid = $post['uid'] ?? ''; $invoice->tax_text = $post['tax_text'] ?? ''; $invoice->billing_type = $post['billing_type'] ?? 'invoice'; $invoice->total = $post['total'] ?? 0; $invoice->total_gross = $post['total_gross'] ?? 0; $positions = []; foreach ($post['positions'] ?? [] as $pos) { $positions[] = (object)$pos; } } else { // Load from database $id = $this->request->id ?? $post['id'] ?? null; if (!$id) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Rechnung wurde nicht gefunden']); return; } $invoice = new ManualInvoice($id); if (!$invoice->id) { http_response_code(500); self::returnJson(['success' => false, 'message' => 'Rechnung wurde nicht gefunden']); return; } $positions = $invoice->getProperty('positions'); } // Calculate VAT totals $vat = []; foreach ($positions as $p) { $vatrate = is_object($p) ? $p->vatrate : $p['vatrate']; $price_gross = is_object($p) ? $p->price_gross : ($p['price_gross'] ?? 0); $price_total = is_object($p) ? $p->price_total : ($p['price_total'] ?? 0); if (!array_key_exists($vatrate, $vat)) { $vat[$vatrate] = 0; } $vat[$vatrate] += $price_gross - $price_total; } // Convert positions array to objects if needed $invoice->positions = $positions; $pdf_vars = [ "invoice" => $invoice, "vat" => $vat, "bank_iban" => TT_INVOICE_BANK_IBAN, "bank_bic" => TT_INVOICE_BANK_BIC, "bank_bank" => TT_INVOICE_BANK_BANK, "bank_owner" => TT_INVOICE_BANK_OWNER ]; // Replace placeholders in header $headerHtml = file_get_contents(BASEDIR . "/Layout/default/ManualInvoice/PDF_HEADER.html"); $headerHtml = str_replace("{{ basedir }}", BASEDIR, $headerHtml); $headerHtml = str_replace("{{ addressLine_1 }}", $invoice->company ? $invoice->company : "", $headerHtml); $headerHtml = str_replace("{{ addressLine_2 }}", trim($invoice->firstname . " " . $invoice->lastname), $headerHtml); $headerHtml = str_replace("{{ addressLine_3 }}", $invoice->street ?? '', $headerHtml); $headerHtml = str_replace("{{ addressLine_4 }}", ($invoice->zip ?? '') . " " . ($invoice->city ?? ''), $headerHtml); $headerHtml = str_replace("{{ addressLine_5 }}", ($invoice->country ?? '') != "Österreich" ? ($invoice->country ?? '') : "", $headerHtml); $headerHtml = str_replace("{{ customerNumber }}", $invoice->customer_number ?? '', $headerHtml); $headerHtml = str_replace("{{ billingAccount }}", $invoice->fibu_account_number ?? '', $headerHtml); $headerHtml = str_replace("{{ invoiceNumber }}", $invoice->invoice_number ?? "VORSCHAU", $headerHtml); $headerHtml = str_replace("{{ invoiceDate }}", date("d.m.Y", $invoice->invoice_date ?? time()), $headerHtml); $headerHtml = str_replace("{{ vatHtml }}", ($invoice->uid ?? '') ? "