InvoiceFile WIP 2024-07-09

This commit is contained in:
Frank Schubert
2024-07-10 10:06:06 +02:00
parent 43e28847a4
commit 72c89aa97c
12 changed files with 849 additions and 56 deletions

View File

@@ -1,8 +1,103 @@
<?php
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
use chillerlan\QRCode\Output\QROutputInterface;
class Invoice extends mfBaseModel {
private $positions;
private $voicenumbers;
private $pdf;
public function createPdf() {
if($this->id) {
$invoice_number = $this->invoice_number;
$invoice_date = $this->invoice_date;
} else {
$invoice_number = "PROFORMA";
$invoice_date = 1;
}
$filename = "";
$positions = $this->getProperty("positions");
$vat = [];
foreach ($positions as $p) {
if (!array_key_exists($p->vatrate, $vat)) {
$vat[$p->vatrate] = 0;
}
$vat[$p->vatrate] += $p->price_gross - ($p->price * $p->amount);
}
$pdf_vars = [
"invoice" => $this,
"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/Invoice/PDF_HEADER.html");
$headerHtml = str_replace("{{ basedir }}", BASEDIR, $headerHtml);
$headerHtml = str_replace("{{ addressLine_1 }}", $this->company ? $this->company : "", $headerHtml);
$headerHtml = str_replace("{{ addressLine_2 }}", $this->firstname . " " . $this->lastname, $headerHtml);
$headerHtml = str_replace("{{ addressLine_3 }}", nl2br($this->street), $headerHtml);
$headerHtml = str_replace("{{ addressLine_4 }}", $this->zip . " " . $this->city, $headerHtml);
$headerHtml = str_replace("{{ addressLine_5 }}", $this->country != "Österreich" ? $this->country : "", $headerHtml);
$headerHtml = str_replace("{{ customerNumber }}", $this->customer_number, $headerHtml);
$headerHtml = str_replace("{{ billingAccount }}", $this->fibu_account_number, $headerHtml);
$headerHtml = str_replace("{{ invoiceNumber }}", $invoice_number, $headerHtml);
$headerHtml = str_replace("{{ invoiceDate }}", date("d.m.Y", $invoice_date), $headerHtml);
$headerHtml = str_replace("{{ vatHtml }}", $this->uid ? "<tr><td>Ihre UID:</td><td>" . $this->uid . "</td></tr>" : "", $headerHtml);
$headerHtml = str_replace("{{ qrCodeSrc }}", $this->getSepaQRCode($invoice_number, round($this->total_gross, 2)), $headerHtml);
$headerFile = BASEDIR . "/var/temp/invoice_header-" . date("U") . "-" . rand(1000, 9999) . ".html";
file_put_contents($headerFile, $headerHtml);
// Replace placeholders in header
$footerHtml = file_get_contents(BASEDIR . "/Layout/default/Invoice/PDF_FOOTER.html");
$footerHtml = str_replace("{{ bank_iban }}", TT_INVOICE_BANK_IBAN_FORMATTED, $footerHtml);
$footerHtml = str_replace("{{ bank_bic }}", TT_INVOICE_BANK_BIC, $footerHtml);
$footerHtml = str_replace("{{ bank_bank }}", TT_INVOICE_BANK_BANK, $footerHtml);
$footerHtml = str_replace("{{ bank_owner }}", TT_INVOICE_BANK_OWNER, $footerHtml);
$footerFile = BASEDIR . "/var/temp/invoice_footer-" . date("U") . "-" . rand(1000, 9999) . ".html";
file_put_contents($footerFile, $footerHtml);
$pdf = new PdfForm("Invoice/PDF_MAIN", $pdf_vars);
$wkhtmltopdfArgs = "--header-html $headerFile --footer-html $footerFile";
$filename = $pdf->render($wkhtmltopdfArgs);
return $filename;
}
public function getSepaQRCode($paymentReference, $amount) {
$xinonIBAN = TT_INVOICE_BANK_IBAN;
$xinonBIC = TT_INVOICE_BANK_BIC;
$xinonOwner = TT_INVOICE_BANK_OWNER;
$epc = "BCD
001
1
SCT
$xinonBIC
$xinonOwner
$xinonIBAN
EUR$amount
XINO
$paymentReference
XINON GmbH";
return (new QRCode)->render($epc);
}
public function getProperty($name) {
if($this->$name == null) {
@@ -24,6 +119,17 @@ class Invoice extends mfBaseModel {
return $this->voicenumbers;
}
if($name == "pdf") {
$ifile = InvoiceFileModel::getFirst(["invoice_id" => $this->id]);
if(!$ifile) return null;
$file = $ifile->file;
if(!$file) return null;
$this->pdf = $file;
return $this->pdf;
}
if($name == "creator") {
$this->creator = mfValuecache::singleton()->get("Worker-id-".$this->create_by);
if($this->creator === null) {

View File

@@ -1,10 +1,5 @@
<?php
//use \chillerlan\QRCode;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
use chillerlan\QRCode\Output\QROutputInterface;
class InvoiceController extends mfBaseController {
protected function init() {
@@ -97,8 +92,18 @@ class InvoiceController extends mfBaseController {
$this->redirect("Invoice");
}
$filename = $invoice->createPdf();
header('Content-Type: application/octet-stream');
header('Content-disposition: attachment; filename="'.$filename.'"');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: ' . mime_content_type($filename));
header("Content-Length: " . filesize($filename));
$vat = [];
readfile($filename);
exit;
/*$vat = [];
foreach ($invoice->positions as $p) {
if (!array_key_exists($p->vatrate, $vat)) {
$vat[$p->vatrate] = 0;
@@ -148,30 +153,11 @@ class InvoiceController extends mfBaseController {
$pdf = new PdfForm("Invoice/PDF_MAIN", $pdf_vars);
$wkhtmltopdfArgs = "--header-html $headerFile --footer-html $footerFile";
$pdf->download($invoice->invoice_number . ".pdf", $wkhtmltopdfArgs);
$pdf->download($invoice->invoice_number . ".pdf", $wkhtmltopdfArgs);*/
}
public function getBankQRCode($paymentReference, $amount) {
$xinonIBAN = TT_INVOICE_BANK_IBAN;
$xinonBIC = TT_INVOICE_BANK_BIC;
$xinonOwner = TT_INVOICE_BANK_OWNER;
$epc = "BCD
001
1
SCT
$xinonBIC
$xinonOwner
$xinonIBAN
EUR$amount
XINO
$paymentReference
XINON GmbH";
return (new QRCode)->render($epc);
}
protected function runInvoicingAction() {
$i = 0;
@@ -665,7 +651,117 @@ XINON GmbH";
exit;
}
public function createPDFsAction() {
$invoice_path = MFUPLOAD_FILE_SAVE_PATH."/".TT_INVOICE_SAVE_SUBFOLDER."/";
foreach(InvoiceModel::getAll() as $invoice) {
if(InvoiceFileModel::getFirst(["invoice_id" => $invoice->id])) {
continue;
}
// create PDF
$tmp_filename = $invoice->createPdf();
if(!$tmp_filename) {
$this->layout()->setFlash("Error creating PDF file", "error");
$this->redirect("Invoice");
}
$new_filename = $invoice->invoice_number.".pdf";
// move pdf to correct folder
if(!rename($tmp_filename, $invoice_path.$new_filename)) {
$this->layout()->setFlash("Error moving created PDF file", "error");
$this->redirect("Invoice");
}
// create File
$file = FileModel::create([
"name" => $invoice->invoice_number,
"filename" => $new_filename,
"subfolder" => TT_INVOICE_SAVE_SUBFOLDER,
"store_filename" => $new_filename,
"orig_filename" => $new_filename,
]);
if(!$file->save()) {
$this->layout()->setFlash("Error saving PDF file", "error");
$this->redirect("Invoice");
}
// create InvoiceFile
$ifile = InvoiceFileModel::create([
"invoice_id" => $invoice->id,
"file_id" => $file->id,
"name" => $new_filename,
"description" => ""
]);
if(!$ifile->save()) {
$this->layout()->setFlash("Error saving PDF Invoice file", "error");
$this->redirect("Invoice");
}
}
}
public function printInvoicesAction() {
//$start = $r->
$start = $this->request->delivery_start_date;
$end = $this->request->delivery_end_date;
try {
$start_date = DateTime::createFromFormat("d.m.Y", $start, new DateTimeZone("Europe/Vienna"));
$start_date->setTime(0,0,0);
$end_date = DateTime::createFromFormat("d.m.Y", $end, new DateTimeZone("Europe/Vienna"));
$end_date->setTime(23,59,59);
} catch(Exception $e) {
$this->layout()->setFlash("Von- oder Bisdatum ungültig", "error");
$this->redirect("Invoice");
}
if(!InvoiceModel::count(["billing_delivery" => "paper", "invoice_date>=" => $start_date->getTimestamp(), "invoice_date<=" => $end_date->getTimestamp()])) {
$this->layout()->setFlash("Keine Rechnungen im angegebenen Zeitraum gefunden", "error");
$this->redirect("Invoice");
}
$pdf_files = [];
foreach(InvoiceModel::search(["billing_delivery" => "paper", "invoice_date>=" => $start_date->getTimestamp(), "invoice_date<=" => $end_date->getTimestamp()]) as $invoice) {
$filename = $invoice->createPdf();
if(!$filename) {
$this->layout()->setFlash("Fehler beim PDF erstellen (".$invoice->invoice_number.")", "error");
$this->redirect("Invoice");
}
$pdf_files[] = $filename;
}
if(!count($pdf_files)) {
$this->layout()->setFlash("Fehler beim PDF erstellen: Keine PDFs zum zusammenführen", "error");
$this->redirect("Invoice");
}
$output_path = MFUPLOAD_FILE_SAVE_PATH."/".TT_INVOICE_SAVE_SUBFOLDER;
$output_filename = "invoices-print-".date("Y-m-d-H-i-s").".pdf";
$output_filepath = "$output_path/$output_filename";
foreach($pdf_files as $file) {
$pdf_unite_cmd = PDFUNITE_BIN_PATH." '$file' '$output_filepath'";
shell_exec($pdf_unite_cmd);
}
if(!file_exists($output_filepath)) {
$this->layout()->setFlash("Fehler beim PDFs zusammenführen: Ausgabedatei nicht gefunden", "error");
$this->redirect("Invoice");
}
header('Content-Type: application/octet-stream');
header('Content-disposition: attachment; filename="'.$output_filename.'"');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: ' . mime_content_type($output_filepath));
header("Content-Length: " . filesize($output_filepath));
readfile($output_filepath);
exit;
}
}

View File

@@ -33,6 +33,7 @@ class InvoiceModel {
public $total;
public $total_gross;
public $bmd_export_date;
public $date_delivered;
public $total_vat;
public $create_by;
public $edit_by;
@@ -173,7 +174,7 @@ class InvoiceModel {
$sql = "SELECT COUNT(*) as cnt FROM Invoice
WHERE $where";
//mfLoghandler::singleton()->debug($sql);
mfLoghandler::singleton()->debug($sql);
$res = $db->query($sql);
if($db->num_rows($res)) {
@@ -220,7 +221,7 @@ class InvoiceModel {
private static function getSqlFilter($filter) {
$where = "1=1 ";
//var_dump($filter);exit;
$db = FronkDB::singleton();
//var_dump($filter);exit;
@@ -253,6 +254,31 @@ class InvoiceModel {
}
}
if(array_key_exists("invoice_date>", $filter)) {
$invoice_date = $db->escape($filter['invoice_date>']);
if($invoice_date) {
$where .= " AND Invoice.invoice_date > '$invoice_date'";
}
}
if(array_key_exists("invoice_date>=", $filter)) {
$invoice_date = $db->escape($filter['invoice_date>=']);
if($invoice_date) {
$where .= " AND Invoice.invoice_date >= '$invoice_date'";
}
}
if(array_key_exists("invoice_date<", $filter)) {
$invoice_date = $db->escape($filter['invoice_date<']);
if($invoice_date) {
$where .= " AND Invoice.invoice_date < '$invoice_date'";
}
}
if(array_key_exists("invoice_date<=", $filter)) {
$invoice_date = $db->escape($filter['invoice_date<=']);
if($invoice_date) {
$where .= " AND Invoice.invoice_date <= '$invoice_date'";
}
}
if(array_key_exists("bmd_export_date", $filter)) {
$bmd_export_date = $filter['bmd_export_date'];
if(is_numeric($bmd_export_date)) {
@@ -264,6 +290,17 @@ class InvoiceModel {
}
}
if(array_key_exists("date_delivered", $filter)) {
$date_delivered = $filter['date_delivered'];
if(is_numeric($date_delivered)) {
$where .= " AND Invoice.date_delivered=$date_delivered";
} elseif($date_delivered === null || $date_delivered === false) {
$where .= " AND Invoice.date_delivered IS NULL";
} elseif($date_delivered === true) {
$where .= " AND Invoice.date_delivered > 0";
}
}
if(array_key_exists("billingaddress_id", $filter)) {
$Invoiceaddress_id = $filter['billingaddress_id'];
if(is_numeric($Invoiceaddress_id)) {
@@ -353,7 +390,6 @@ class InvoiceModel {
$where .= " AND Invoice.Invoice_period = $Invoice_period";
}
}
//var_dump($filter, $where);exit;
return $where;
}