implemented first version of invoice printing
This commit is contained in:
39
Layout/default/Invoice/PDF_FOOTER.html
Normal file
39
Layout/default/Invoice/PDF_FOOTER.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><title>Xinon Rechnung</title></head>
|
||||||
|
<body style="border:0; margin: 0;font-family: sans-serif, Verdana;font-size: 11px;" onload="subst()">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function subst() {
|
||||||
|
var vars = {};
|
||||||
|
var query_strings_from_url = document.location.search.substring(1).split('&');
|
||||||
|
for (var query_string in query_strings_from_url) {
|
||||||
|
if (query_strings_from_url.hasOwnProperty(query_string)) {
|
||||||
|
var temp_var = query_strings_from_url[query_string].split('=', 2);
|
||||||
|
vars[temp_var[0]] = decodeURI(temp_var[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var css_selector_classes = ['page', 'frompage', 'topage', 'webpage', 'section', 'subsection', 'date', 'isodate', 'time', 'title', 'doctitle', 'sitepage', 'sitepages'];
|
||||||
|
for (var css_class in css_selector_classes) {
|
||||||
|
if (css_selector_classes.hasOwnProperty(css_class)) {
|
||||||
|
var element = document.getElementsByClassName(css_selector_classes[css_class]);
|
||||||
|
for (var j = 0; j < element.length; ++j) {
|
||||||
|
element[j].textContent = vars[css_selector_classes[css_class]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 16px;height: 1px"></div>
|
||||||
|
<div style="color:grey;text-align: center;margin-bottom: 0">
|
||||||
|
<span>XINON GmbH | Fladnitz 150 | 8322 Studenzen</span><br>
|
||||||
|
<span>Tel.: +43 3115 40800 | E-Mail: office@xinon.at</span><br>
|
||||||
|
<span>UID: ATU68711968 | FN: 416556h | LG: Feldbach</span><br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: right">Seite <span class="page"></span> von <span class="topage"></span></div>
|
||||||
|
|
||||||
|
<div style="margin-top: 16px;height: 1px"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
241
Layout/default/Invoice/PDF_MAIN.php
Normal file
241
Layout/default/Invoice/PDF_MAIN.php
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var string $ressourcePathPrefix
|
||||||
|
* @var Invoice $invoice
|
||||||
|
* @var array $vat
|
||||||
|
*/
|
||||||
|
$net_total = $invoice->total + $invoice->total_setup;
|
||||||
|
$gross_total = $invoice->total_gross + $invoice->total_setup_gross;
|
||||||
|
$is_credit = $net_total < 0;
|
||||||
|
|
||||||
|
$this->setReturnValue(['filename' => $invoice->invoice_number . ".pdf"]);
|
||||||
|
|
||||||
|
//die(json_encode($invoice->positions));
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Rechnung</title>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<!-- <link href="-->
|
||||||
|
<?php //= self::getResourcePath() ?><!--assets/css/bootstrap.min.css" rel="stylesheet" type="text/css" />-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin-top: 0;
|
||||||
|
/*padding-top: 20pt;*/
|
||||||
|
font-family: sans-serif, Verdana;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
page-break-inside: avoid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uneven {
|
||||||
|
background-color: #e1e1e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table tr td:last-child {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.additionalRow td:first-child {
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 20pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#invoiceTable tr *:nth-child(5),
|
||||||
|
#invoiceTable tr *:nth-child(4),
|
||||||
|
#invoiceTable tr *:nth-child(3) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#invoiceTable tr *:not(:first-child) {
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#invoiceTable tr td {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#invoiceTable tr td:first-child {
|
||||||
|
max-width: 200pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<h2 style="text-align: center;color: #005384">Ihre Xinon Rechnung vom <?=date("d.m.Y",$invoice->invoice_date)?></h2>
|
||||||
|
|
||||||
|
<table style="border-collapse: collapse; width: 100%;" id="invoiceTable">
|
||||||
|
<tr style="font-weight: bold; border-bottom: 1px solid black;" class="uneven">
|
||||||
|
<th style="text-align: center">Dienstleistung</th>
|
||||||
|
<th style="text-align: center">Zeitraum</th>
|
||||||
|
<th style="text-align: center">Preis</th>
|
||||||
|
<th style="text-align: center;">Menge</th>
|
||||||
|
<th style="text-align: center">Netto €</th>
|
||||||
|
<th style="text-align: center">Ust. %</th>
|
||||||
|
<th style="text-align: center;">Brutto €</th>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
$i = 0;
|
||||||
|
foreach($invoice->positions as $p):
|
||||||
|
$start_date = new DateTime($p->start_date);
|
||||||
|
$end_date = new DateTime($p->end_date);
|
||||||
|
$amount = (float) number_format($p->amount, 3, ",", ".");
|
||||||
|
$price = number_format($p->price, 2, ",",".");
|
||||||
|
$price_total = number_format($p->price_total, 2, ",",".");
|
||||||
|
$price_gross = number_format($p->price_gross, 2, ",",".");
|
||||||
|
$vatrate = number_format($p->vatrate, 2, ",",".");
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<tr class="<?=($i%2 == 0) ? "even" : "uneven" ?>">
|
||||||
|
<td><?=$p->product_name?></td>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
<?= $p->billing_period > 1 ?
|
||||||
|
$start_date->format("m.Y") . " - " . $end_date->format("m.Y") :
|
||||||
|
$start_date->format("d.m.Y") . " - " . $end_date->format("d.m.Y")
|
||||||
|
?>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td><?=$price?> €</td>
|
||||||
|
<td style="text-align: center"><?=$amount?></td>
|
||||||
|
<td><?=$price_total?> €</td>
|
||||||
|
<td style="text-align: right;"><?=$vatrate?>%</td>
|
||||||
|
<td><?=$price_gross?> €</td>
|
||||||
|
</tr>
|
||||||
|
<?php if($p->matchcode): ?>
|
||||||
|
<tr class="additionalRow <?=($i%2 == 0) ? "even" : "uneven" ?>">
|
||||||
|
<td colspan="7"><?=$p->matchcode?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
$i++;
|
||||||
|
endforeach;
|
||||||
|
?>
|
||||||
|
<tr style="font-weight: bold; background-color: #e1e1e1; border-bottom: 1px solid black;border-top: 1px solid black">
|
||||||
|
<td colspan="5">Gesamt Netto:</td>
|
||||||
|
<td colspan="2" style="text-align: right;"><?=number_format($net_total, 2, ",","."). " €"?></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php foreach ($vat as $rate => $vat_total): ?>
|
||||||
|
|
||||||
|
<?php if($vat_total > 0): ?>
|
||||||
|
<tr style="font-size: 11px;border-bottom: 1px solid black;">
|
||||||
|
<td colspan="5">USt. <?=$rate?>%:</td>
|
||||||
|
<td colspan="2" style="text-align: right"><?=number_format($vat_total, 2, ",","."). " €"?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
<!-- double underline border on bottom -->
|
||||||
|
<tr style="font-weight: bold; border-bottom: 3px double black; background-color: #e1e1e1;">
|
||||||
|
<td colspan="5">Gesamt Brutto:</td>
|
||||||
|
<td colspan="2" style="text-align: right"><?=number_format($gross_total, 2, ",","."). " €"?></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- TODO: ADD CALL DETAIL SECTION-->
|
||||||
|
<!--
|
||||||
|
<div style="margin-top: 20pt;">
|
||||||
|
<h3 style="color: #005384;margin-bottom: 0">Zusammenfassung für 0800 / 498748</h3>
|
||||||
|
<div style="margin-bottom: 16px">(01.01.2021 - 31.01.2021)</div>
|
||||||
|
|
||||||
|
<table style="border-collapse: collapse; width: 100%;">
|
||||||
|
<tr style="text-align: left;" class="uneven">
|
||||||
|
<th>Ziel</th>
|
||||||
|
<th>Preis pro Minute</th>
|
||||||
|
<th>Dauer</th>
|
||||||
|
<th style="text-align: right">Netto €</th>
|
||||||
|
<th style="text-align: right">Brutto €</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="uneven">
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="uneven">
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 20pt;">
|
||||||
|
<h3 style="color: #005384;margin-bottom: 0">Zusammenfassung für 0800 / 498748</h3>
|
||||||
|
<div style="margin-bottom: 16px">(01.01.2021 - 31.01.2021)</div>
|
||||||
|
|
||||||
|
<table style="border-collapse: collapse; width: 100%;">
|
||||||
|
<tr style="text-align: left;" class="uneven">
|
||||||
|
<th>Ziel</th>
|
||||||
|
<th>Preis pro Minute</th>
|
||||||
|
<th>Dauer</th>
|
||||||
|
<th style="text-align: right">Netto €</th>
|
||||||
|
<th style="text-align: right">Brutto €</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="uneven">
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="uneven">
|
||||||
|
<td>Österreich Festnetz</td>
|
||||||
|
<td>0,05 €</td>
|
||||||
|
<td>01:40:00</td>
|
||||||
|
<td style="text-align: right">5,00 €</td>
|
||||||
|
<td>6,00 €</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
//use \chillerlan\QRCode;
|
||||||
|
use chillerlan\QRCode\QRCode;
|
||||||
|
use chillerlan\QRCode\QROptions;
|
||||||
|
use chillerlan\QRCode\Output\QROutputInterface;
|
||||||
|
|
||||||
class InvoiceController extends mfBaseController {
|
class InvoiceController extends mfBaseController {
|
||||||
|
|
||||||
protected function init()
|
protected function init() {
|
||||||
{
|
|
||||||
$this->needlogin = true;
|
$this->needlogin = true;
|
||||||
$me = new User();
|
$me = new User();
|
||||||
$me->loadMe();
|
$me->loadMe();
|
||||||
@@ -52,8 +56,7 @@ class InvoiceController extends mfBaseController {
|
|||||||
$this->layout()->set("pagination", $pagination);
|
$this->layout()->set("pagination", $pagination);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getPreparedFilter($filter)
|
private function getPreparedFilter($filter) {
|
||||||
{
|
|
||||||
$new_filter = [];
|
$new_filter = [];
|
||||||
|
|
||||||
if (array_key_exists("customer", $filter)) {
|
if (array_key_exists("customer", $filter)) {
|
||||||
@@ -91,13 +94,11 @@ class InvoiceController extends mfBaseController {
|
|||||||
$invoice = new Invoice($id);
|
$invoice = new Invoice($id);
|
||||||
if (!$invoice->id) {
|
if (!$invoice->id) {
|
||||||
$this->layout()->setFlash("Rechnung nicht gefunden", "error");
|
$this->layout()->setFlash("Rechnung nicht gefunden", "error");
|
||||||
$this->redirect("Rechnung");
|
$this->redirect("Invoice");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$vat = [];
|
$vat = [];
|
||||||
|
|
||||||
foreach ($invoice->positions as $p) {
|
foreach ($invoice->positions as $p) {
|
||||||
if (!array_key_exists($p->vatrate, $vat)) {
|
if (!array_key_exists($p->vatrate, $vat)) {
|
||||||
$vat[$p->vatrate] = 0;
|
$vat[$p->vatrate] = 0;
|
||||||
@@ -105,23 +106,50 @@ class InvoiceController extends mfBaseController {
|
|||||||
$vat[$p->vatrate] += $p->price_gross - $p->price;
|
$vat[$p->vatrate] += $p->price_gross - $p->price;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pdf_vars = [
|
$pdf_vars = ["invoice" => $invoice, "vat" => $vat];
|
||||||
"invoice" => $invoice,
|
|
||||||
"vat" => $vat
|
|
||||||
];
|
|
||||||
|
|
||||||
/*$this->layout()->setTemplate("Invoice/Print.pdf");
|
// Replace placeholders in header
|
||||||
$this->layout()->set("invoice", $invoice);
|
$headerHtml = file_get_contents(BASEDIR . "/Layout/default/Invoice/PDF_HEADER.html");
|
||||||
$this->layout()->set("vat", $vat);
|
$headerHtml = str_replace("{{ basedir }}", BASEDIR, $headerHtml);
|
||||||
$this->layout()->set("ressourcePathPrefix", MFFANCYBASEURL."/");
|
$headerHtml = str_replace("{{ addressLine_1 }}", $invoice->company ? $invoice->company : "", $headerHtml);
|
||||||
return true;*/
|
$headerHtml = str_replace("{{ addressLine_2 }}", $invoice->firstname . " " . $invoice->lastname, $headerHtml);
|
||||||
|
$headerHtml = str_replace("{{ addressLine_3 }}", nl2br($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 }}", "testtest", $headerHtml);
|
||||||
|
$headerHtml = str_replace("{{ invoiceNumber }}", $invoice->invoice_number, $headerHtml);
|
||||||
|
$headerHtml = str_replace("{{ invoiceDate }}", date("d.m.Y", $invoice->invoice_date), $headerHtml);
|
||||||
|
$headerHtml = str_replace("{{ vatHtml }}", $invoice->uid ? "<tr><td>Ihre UID:</td><td>" . $invoice->uid . "</td></tr>" : "", $headerHtml);
|
||||||
|
$headerHtml = str_replace("{{ qrCodeSrc }}", $this->getBankQRCode($invoice->invoice_number, $invoice->total_gross), $headerHtml);
|
||||||
|
|
||||||
$pdf = new PdfForm("Invoice/Print.pdf", $pdf_vars);
|
$headerFile = BASEDIR . "/var/temp/" . date("U") . "-" . rand(1000, 9999) . ".html";
|
||||||
//$pdfpath = $pdf->render();
|
file_put_contents($headerFile, $headerHtml);
|
||||||
$pdf->download($invoice->invoice_number.".pdf");
|
|
||||||
|
|
||||||
|
$pdf = new PdfForm("Invoice/PDF_MAIN", $pdf_vars);
|
||||||
|
$wkhtmltopdfArgs = "--header-html $headerFile --footer-html " . BASEDIR . "/Layout/default/Invoice/PDF_FOOTER.html";
|
||||||
|
$pdf->download($invoice->invoice_number . ".pdf", $wkhtmltopdfArgs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBankQRCode($paymentReference, $amount) {
|
||||||
|
$xinonIBAN = "DE89370400440532013000";
|
||||||
|
$xinonBIC = "COBADEFFXXX";
|
||||||
|
|
||||||
|
$epc = "BCD
|
||||||
|
001
|
||||||
|
1
|
||||||
|
SCT
|
||||||
|
$xinonBIC
|
||||||
|
Xinon GmbH
|
||||||
|
$xinonIBAN
|
||||||
|
EUR$amount
|
||||||
|
XINO
|
||||||
|
$paymentReference
|
||||||
|
|
||||||
|
XINON GmbH";
|
||||||
|
|
||||||
|
return (new QRCode)->render($epc);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function runInvoicingAction() {
|
protected function runInvoicingAction() {
|
||||||
@@ -139,8 +167,7 @@ class InvoiceController extends mfBaseController {
|
|||||||
$bill_positions = [];
|
$bill_positions = [];
|
||||||
$credit_positions = [];
|
$credit_positions = [];
|
||||||
|
|
||||||
$billing_rows = BillingModel::search([
|
$billing_rows = BillingModel::search(["owner_id" => $owner_id,
|
||||||
"owner_id" => $owner_id,
|
|
||||||
"billingaddress_id" => $billingaddress_id,
|
"billingaddress_id" => $billingaddress_id,
|
||||||
"billing_type" => $billing_type,
|
"billing_type" => $billing_type,
|
||||||
"billing_delivery" => $billing_delivery,
|
"billing_delivery" => $billing_delivery,
|
||||||
@@ -239,7 +266,6 @@ class InvoiceController extends mfBaseController {
|
|||||||
$invoice_data["total_vat"] = 0;
|
$invoice_data["total_vat"] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,23 +16,23 @@ class PdfForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function render() {
|
public function render($additionalArgs = false): string {
|
||||||
$this->layout->setTemplate($this->template);
|
$this->layout->setTemplate($this->template);
|
||||||
$this->layout->set("ressourcePathPrefix", BASEDIR."/public/");
|
$this->layout->set("ressourcePathPrefix", BASEDIR."/public/");
|
||||||
foreach($this->variables as $name => $value) {
|
foreach($this->variables as $name => $value) {
|
||||||
$this->layout->set($name, $value);
|
$this->layout->set($name, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
$fullpath = $this->layout->renderPDF();
|
$fullpath = $this->layout->renderPDF(false, $additionalArgs);
|
||||||
$this->fullpath = $fullpath;
|
$this->fullpath = $fullpath;
|
||||||
$this->returnValues = $this->layout->getReturnedValue();
|
$this->returnValues = $this->layout->getReturnedValue();
|
||||||
|
|
||||||
return $fullpath;
|
return $fullpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function download($filename = false) {
|
public function download($filename = false, $additionalArgs = false) {
|
||||||
if(!$this->fullpath) {
|
if(!$this->fullpath) {
|
||||||
$this->render();
|
$this->render($additionalArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
$filepath = $this->fullpath;
|
$filepath = $this->fullpath;
|
||||||
|
|||||||
Reference in New Issue
Block a user