true, "netowner_id" => $netowner_id]); if(!$last_invoice || !$last_invoice->invoice_number) { return false; } return $last_invoice->invoice_number; } public function createPdf() { if($this->id) { $invoice_number = $this->invoice_number; $invoice_date = new DateTime($this->invoice_date); } else { $invoice_number = "PROFORMA"; $invoice_date = new DateTime("@1"); } $conf = TT_PREORDER_BILLING[$this->netowner_id]; $netop_conf = null; if($this->owner_id && array_key_exists($this->owner_id, TT_PREORDER_BILLING[$this->netowner_id]["netoperators"])) { $netop_conf = TT_PREORDER_BILLING[$this->netowner_id]["netoperators"][$this->owner_id]; } $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, "qrcode" => $this->getSepaQRCode($this->netowner_id, $invoice_number, round($this->total_gross, 2)), ]; $me = new User(); $me->loadMe(); // Replace placeholders in header $headerHtml = file_get_contents(BASEDIR . "/Layout/default/PreorderBillingInvoice/PDF_HEADER-".$this->netowner_id.".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_4 }}", nl2br($this->street), $headerHtml); $headerHtml = str_replace("{{ addressLine_5 }}", $this->zip . " " . $this->city, $headerHtml); $headerHtml = str_replace("{{ addressLine_6 }}", $this->country != "Österreich" ? $this->country : "", $headerHtml); $headerHtml = str_replace("{{ customerNumber }}", $this->fibu_account_number, $headerHtml); $headerHtml = str_replace("{{ invoiceNumber }}", $invoice_number, $headerHtml); $headerHtml = str_replace("{{ invoiceDate }}", $invoice_date->format("d.m.Y"), $headerHtml); $headerHtml = str_replace("{{ caseWorker }}", $me->name, $headerHtml); $headerHtml = str_replace("{{ caseWorkerPhone }}", $me->mobile, $headerHtml); $headerHtml = str_replace("{{ caseWorkerEmail }}", $me->email, $headerHtml); //$headerHtml = str_replace("{{ orderNumber }}", "WVR / 52", $headerHtml); $headerHtml = str_replace("{{ vatHtml }}", $this->uid ? "Ihre UID:" . $this->uid . "" : "", $headerHtml); if($netop_conf) { if(array_key_exists("order-number", $netop_conf) && $netop_conf["order-number"]) { $headerHtml = str_replace("{{ orderNumberHtml }}", "Auftrag:" . $netop_conf["order-number"] . "", $headerHtml); } else { $headerHtml = str_replace("{{ orderNumberHtml }}", "", $headerHtml); } if(array_key_exists("address-rctp-extra-text", $netop_conf) && $netop_conf["address-rctp-extra-text"]) { $headerHtml = str_replace("{{ addressLine_3 }}", $netop_conf["address-rctp-extra-text"], $headerHtml); } else { $headerHtml = str_replace("{{ addressLine_3 }}", "", $headerHtml); } } else { $headerHtml = str_replace("{{ orderNumberHtml }}", "", $headerHtml); $headerHtml = str_replace("{{ addressLine_3 }}", "", $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/PreorderBillingInvoice/PDF_FOOTER-".$this->netowner_id.".html"); $footerHtml = str_replace("{{ bank_iban }}", $conf["bank-account-iban"], $footerHtml); $footerHtml = str_replace("{{ bank_bic }}", $conf["bank-account-bic"], $footerHtml); $footerFile = BASEDIR . "/var/temp/preorderbillinginvoice_footer-" . date("U") . "-" . rand(1000, 9999) . ".html"; file_put_contents($footerFile, $footerHtml); $pdf = new PdfForm("PreorderBillingInvoice/PDF_MAIN-".$this->netowner_id, $pdf_vars); $wkhtmltopdfArgs = "--margin-top 2mm --header-spacing 90 --header-html '$headerFile' --footer-html '$footerFile'"; $filename = $pdf->render($wkhtmltopdfArgs); if($conf["invoice-pdf-bg-file"]) { // run pdftk with $filename as input and $conf["invoice-pdf-bg-file"] as output // to add background to pdf $bg_file = $conf["invoice-pdf-bg-file"]; $temp_file_name = tempnam(TEMP_DIR, "invoice-pdftk").".pdf"; $pdftk_cmd = PDFTK_BIN_PATH." '$filename' background '$bg_file' output '$temp_file_name'"; $this->log->debug(__METHOD__." $pdftk_cmd"); shell_exec($pdftk_cmd); $filename = $temp_file_name; } return $filename; } public function getSepaQRCode($netowner_id, $invoice_number, $amount) { if(!$netowner_id) return ""; $conf = TT_PREORDER_BILLING[$netowner_id]; $IBAN = str_replace(" ", "", $conf["bank-account-iban"]); $BIC = str_replace(" ", "", $conf["bank-account-bic"]); $Owner = $conf["bank-account-owner"]; $epc = "BCD 001 1 SCT $BIC $Owner $IBAN EUR$amount $invoice_number RML Infrastruktur GmbH"; return (new QRCode)->render($epc); } public function sendByEmail($to_email = false) { if(!$this->id) return false; // get pdf file $ifile = PreorderBillingInvoiceFile::createFromInvoice($this); if(!$ifile) { return false; } $pdf = $ifile->file; $pdf_filename = false; try { $pdf_filename = $pdf->getFullPath(); } catch(\Exception $e) { $this->log->error("PDF-File for Invoice ".$this->id." not found"); } if(!$pdf_filename || !file_exists($pdf_filename)) { return false; } // get detail file $detail_file = null; $netowner = $this->getProperty("netowner"); if(!$netowner || !array_key_exists($netowner->id, TT_PREORDER_BILLING)) { return false; } $netowner_config = TT_PREORDER_BILLING[$netowner->id]; if(array_key_exists($this->owner_id, $netowner_config["netoperators"])) { $anb_config = $netowner_config["netoperators"][$this->owner_id]; $detail_format = $anb_config["invoice-detail-file-format"]; if($detail_format == "csv") { $detail_file = $this->getProperty("csv"); } if($detail_format == "pdf") { $detail_file = $this->getProperty("detailpdf"); } } // get csv file $tpl = new Layout(); $tpl->setTemplate("Emailtemplates/preorder-invoice/rml/invoice-email.html"); if($this->owner_id) { $tpl->setTemplate("Emailtemplates/preorder-invoice/rml/invoice-email-anb.html"); } $pdf_vars = [ "invoice" => $this ]; foreach($pdf_vars as $name => $val) { $tpl->set($name, $val); } $body = $tpl->render(); $values = $tpl->getReturnedValue(); $subject = $values['subject']; $from = $values['from_email']; $from_name = $values['from_email_name']; if($to_email) { $to = $to_email; } else { $to = trim($this->email); } if(!$to) { $this->log->error(__METHOD__.": Invoice ".$this->invoice_number." missing email"); } if(!$subject || !$from || !$from_name || !$to) { $this->log->warn(__METHOD__.": Invoice ".$this->invoice_number." could not be sent. Values missing. (subject: '$subject', from: '$from_name', from_email: '$from', to: '$to')"); return false; } else { $email = new Emailnotification("PreorderBillingInvoice", $this->id); $email->setSubject($subject); $email->setHtmlBody($body); $email->setFrom($from, $from_name); $email->setTo($to); $email->setHeader("X-".MFAPPNAME."-Iid", $this->id); $email->addAttachment($pdf_filename, null, $pdf->filename, "application/pdf"); if($detail_file) { $email->addAttachment($detail_file->getFullPath(), null, $detail_file->filename, $detail_file->mimetype); } $email->send(); $this->log->info(__METHOD__.": Sending Preorder Invoice ".$this->invoice_number." to $to"); } return true; } public function getPdfFromDetailCsv() { $netowner = $this->getProperty("netowner"); if(!$netowner || !array_key_exists($netowner->id, TT_PREORDER_BILLING)) { return false; } $netowner_config = TT_PREORDER_BILLING[$netowner->id]; $csv_file = $this->getProperty("csv"); $input = fopen($csv_file->getFullPath(), "r"); if(!$input) return false; $bom = "\xef\xbb\xbf"; if(fgets($input, 4) !== $bom) { // BOM not found - rewind pointer to start of file. rewind($input); } $headers = []; $positions = []; $c = 0; $i = 0; while($csv = fgetcsv($input, 0, ";")) { $i++; if($i == 1) { foreach($csv as $key => $name) { $headers[$name] = $key; } continue; } if(!trim($csv[1])) { continue; } $data = []; $data["netzbetreiber"] = trim($csv[$headers["Netzbetreiber"]]); $data["rechnum"] = trim($csv[$headers["Rechungsnummer"]]); $data["rechdatum"] = (new DateTime(trim($csv[$headers["Rechnungsdatum"]])))->format("d.m.Y"); $data["netzgebiet"] = trim($csv[$headers["Netzgebiet"]]); $data["oaid"] = trim($csv[$headers["OAID"]]); $data["extref"] = trim($csv[$headers["Extref"]]); $data["bestdatum"] = (new DateTime(trim($csv[$headers["Bestelldatum"]])))->format("d.m.Y"); $data["von"] = trim($csv[$headers["Periode von"]]); $data["bis"] = trim($csv[$headers["Periode bis"]]); $data["artnum"] = trim($csv[$headers["Artikelnummer"]]); $data["produkt"] = trim($csv[$headers["Produkt"]]); $data["anzahl"] = trim($csv[$headers["Anzahl"]]); $data["netto"] = trim($csv[$headers["Preis Netto"]]); $positions[] = $data; } if(!count($positions)) { return false; } $invoice_number = $this->invoice_number; $variables = [ "positions" => $positions, "netzbetreiber" => $this->getProperty("owner")->getCompanyOrName(), "rechnum" => $invoice_number, ]; $pdf = new PdfForm("PreorderBillingInvoice/detail.pdf", $variables); $path = $pdf->render("-O landscape"); if(!$path) return false; $filename = "$invoice_number-detail.pdf"; $subfolder = $netowner_config["subfolder"]; $new_filepath = MFUPLOAD_FILE_SAVE_PATH."/$subfolder/$filename"; if(!rename($path, $new_filepath)) { unlink($path); return false; } $file = FileModel::create([ "name" => $filename, "filename" => $filename, "store_filename" => $filename, "orig_filename" => $filename, "subfolder" => $subfolder, "mimetype" => "application/pdf", ]); if(!$file->save()) { unlink($new_filepath); return false; } $invoice_file = PreorderBillingInvoiceFile::create([ "invoice_id" => $this->id, "file_id" => $file->id, "name" => $filename, ]); if(!$invoice_file->save()) { $file->delete(); //unlink($new_filepath); return false; } return $invoice_file; //$pdf->download(); /* $file = FileModel::create([ "" => "", ]);*/ } public function getProperty($name) { if($this->$name == null) { if($name == "netowner") { $netowner = new Address($this->netowner_id); if(!$netowner->id) { return false; } $this->netowner = $netowner; return $this->netowner; } if($name == "owner") { $owner = new Address($this->owner_id); if(!$owner->id) { return false; } $this->owner = $owner; return $this->owner; } if($name == "billingaddress") { $billingaddress = new Address($this->billingaddress_id); if(!$billingaddress->id) { return false; } $this->billingaddress = $billingaddress; return $this->billingaddress; } if($name == "positions") { $positions = PreorderBillingInvoiceposition::search(["invoice_id" => $this->id]); $this->positions = $positions; return $this->positions; } if($name == "pdf") { $ifile = PreorderBillingInvoiceFile::getFirst(["invoice_id" => $this->id, "name" => "%.pdf"]); if(!$ifile) return null; $file = $ifile->file; if(!$file) return null; $this->pdf = $file; return $this->pdf; } if($name == "csv") { $ifile = PreorderBillingInvoiceFile::getFirst(["invoice_id" => $this->id, "name" => "%.csv"]); if(!$ifile) return null; $file = $ifile->file; if(!$file) return null; $this->csv = $file; return $this->csv; } if($name == "detailpdf") { // same as csv but in pdf format $ifile = PreorderBillingInvoiceFile::getFirst(["invoice_id" => $this->id, "name" => "%-detail.pdf"]); if(!$ifile || !$ifile->file || !$ifile->file->id) { $ifile = $this->getPdfFromDetailCsv(); } if(!$ifile || !$ifile->file || !$ifile->file->id) return null; $this->detailpdf = $ifile->file; return $this->detailpdf; } if($name == "emailLog") { $emaillog = EmailLog::getFirst(["object_type" => "PreorderBillingInvoice", "object_id" => $this->id]); if($emaillog) { $this->emailLog = $emaillog; } return $this->emailLog; } if($name == "creator") { $creator = mfValuecache::singleton()->get("Worker-id-".$this->create_by); if($creator) { $this->creator = $creator; return $this->creator; } $this->creator = new User($this->create_by); if(!$this->creator->id) { return null; } mfValuecache::singleton()->set("Worker-id-".$this->create_by, $this->creator); return $this->creator; } if($name == "editor") { $editor = mfValuecache::singleton()->get("Worker-id-".$this->edit_by); if($editor) { $this->editor = $editor; return $this->editor; } $this->editor = new User($this->edit_by); if(!$this->editor->id) { return null; } mfValuecache::singleton()->set("Worker-id-".$this->edit_by, $this->editor); return $this->editor; } $classname = ucfirst($name); $idfield = $name . "_id"; $this->$name = mfValuecache::singleton()->get("mfObjectmodel-$name-" . $this->$idfield); if(!$this->$name) { $this->$name = new $classname($this->$idfield); } if($this->$name->id) { mfValuecache::singleton()->set("mfObjectmodel-$name-" . $this->$name->id, $this->$name); return $this->$name; } else { return null; } } return $this->$name; } /******************************** * Begin static Model functions */ public static function create(Array $data) { $model = new PreorderBillingInvoice(); $table_fields = [ "netowner_id","invoice_number","invoice_date","preorderbillingcustomer_id","owner_id","billingaddress_id","fibu_account_number","fibu_cost_area", "fibu_cost_account", "fibu_revenue_account","fibu_taxcode","tax_text","head_text","company","firstname","lastname","street","zip","city","country","email", "uid", "billing_type", "billing_delivery","bank_account_bank","bank_account_owner","bank_account_iban","bank_account_bic","total","total_gross","vatgroup_id", "vatrate", "bmd_export_date","date_delivered", "create_by","edit_by","create","edit" ]; foreach($data as $field => $value) { if(in_array($field, $table_fields)) { $model->$field = $value; } } $me = new User(); $me->loadMe(); if($model->create_by === null) { $model->create_by = $me->id; } if($model->edit_by === null) { $model->edit_by = $me->id; } return $model; } public static function getAll() { $items = []; $db = FronkDB::singleton(); $res = $db->select("PreorderBillingInvoice", "*", "1 = 1 ORDER BY id"); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[] = new PreorderBillingInvoice($data); } } return $items; } public static function getFirst($filter) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); $sql = "SELECT PreorderBillingInvoice.* FROM PreorderBillingInvoice WHERE $where ORDER BY id LIMIT 1"; //mfLoghandler::singleton()->debug($sql); $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new PreorderBillingInvoice($data); if($item->id) { return $item; } else { return null; } } return null; } public static function getLast($filter) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); $sql = "SELECT PreorderBillingInvoice.* FROM PreorderBillingInvoice WHERE $where ORDER BY id DESC LIMIT 1"; mfLoghandler::singleton()->debug($sql); $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); $item = new PreorderBillingInvoice($data); if($item->id) { return $item; } else { return null; } } return null; } public static function count($filter) { $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); $sql = "SELECT COUNT(*) as cnt FROM PreorderBillingInvoice WHERE $where"; //mfLoghandler::singleton()->debug($sql); $res = $db->query($sql); if($db->num_rows($res)) { $data = $db->fetch_object($res); return $data->cnt; } return 0; } public static function search($filter, $limit = false, $order = false) { //var_dump($filter);exit; $items = []; if(!$order) { $order = "id ASC"; } $db = FronkDB::singleton(); $where = self::getSqlFilter($filter); $sql = "SELECT PreorderBillingInvoice.* FROM PreorderBillingInvoice WHERE $where ORDER BY $order"; if(is_array($limit) && count($limit)) { if(is_numeric($limit['start']) && is_numeric($limit['count'])) { $sql .= " LIMIT ".$limit['start'].", ".$limit['count']; } elseif(is_numeric($limit['count'])) { $sql .= " LIMIT ".$limit['count']; } } mfLoghandler::singleton()->debug($sql); $res = $db->query($sql); if($db->num_rows($res)) { while($data = $db->fetch_object($res)) { $items[$data->id] = new PreorderBillingInvoice($data); } } return $items; } private static function getSqlFilter($filter) { $where = "1=1 "; if(array_key_exists("invoice_number", $filter)) { $invoice_number = $filter['invoice_number']; if($invoice_number === null || $invoice_number === false) { $where .= " AND (PreorderBillingInvoice.invoice_number IS NULL OR PreorderBillingInvoice.invoice_number=0)"; } elseif($invoice_number === true) { $where .= " AND (PreorderBillingInvoice.invoice_number IS NOT NULL AND PreorderBillingInvoice.invoice_number > 0)"; } elseif(is_numeric($invoice_number)) { $where .= " AND PreorderBillingInvoice.invoice_number=$invoice_number"; } } if(array_key_exists("invoice_date", $filter)) { $invoice_date = FronkDB::singleton()->escape($filter['invoice_date']); if($invoice_date) { $where .= " AND PreorderBillingInvoice.invoice_date='$invoice_date'"; } } if(array_key_exists("preorderbillingcustomer_id", $filter)) { $preorderbillingcustomer_id = $filter['preorderbillingcustomer_id']; if(is_numeric($preorderbillingcustomer_id)) { $where .= " AND PreorderBillingInvoice.preorderbillingcustomer_id=$preorderbillingcustomer_id"; } } if(array_key_exists("netowner_id", $filter)) { $netowner_id = $filter['netowner_id']; if(is_numeric($netowner_id)) { $where .= " AND PreorderBillingInvoice.netowner_id=$netowner_id"; } } if(array_key_exists("owner_id", $filter)) { $owner_id = $filter['owner_id']; if(is_numeric($owner_id)) { $where .= " AND PreorderBillingInvoice.owner_id=$owner_id"; } } if(array_key_exists("billingaddress_id", $filter)) { $billingaddress_id = $filter['billingaddress_id']; if(is_numeric($billingaddress_id)) { $where .= " AND PreorderBillingInvoice.billingaddress_id=$billingaddress_id"; } } if (array_key_exists("company", $filter)) { $company = FronkDB::singleton()->escape($filter["company"]); if ($company) { $where .= " AND company like '%$company%'"; } } if (array_key_exists("firstname", $filter)) { $firstname = FronkDB::singleton()->escape($filter["firstname"]); if ($firstname) { $where .= " AND firstname like '%$firstname%'"; } } if (array_key_exists("lastname", $filter)) { $lastname = FronkDB::singleton()->escape($filter["lastname"]); if ($lastname) { $where .= " AND lastname like '%$lastname%'"; } } if (array_key_exists("mergedName", $filter)) { $name = FronkDB::singleton()->escape($filter["mergedName"]); if ($name) { $where .= " AND (CONCAT(firstname, ' ', lastname) like '%$name%' OR CONCAT(lastname, ' ', firstname) like '%$name%' )"; } } if (array_key_exists("street", $filter)) { $street = FronkDB::singleton()->escape($filter["street"]); if ($street) { $where .= " AND street like '%$street%'"; } } if (array_key_exists("zip", $filter)) { $zip = FronkDB::singleton()->escape($filter["zip"]); if ($zip) { $where .= " AND zip like '%$zip%'"; } } if (array_key_exists("city", $filter)) { $city = FronkDB::singleton()->escape($filter["city"]); if ($city) { $where .= " AND city like '%$city%'"; } } if (array_key_exists("country", $filter)) { $country = FronkDB::singleton()->escape($filter["country"]); if ($country) { $where .= " AND country like '%$country%'"; } } if (array_key_exists("email", $filter)) { $email = FronkDB::singleton()->escape($filter["email"]); if ($email) { $where .= " AND email like '%$email%'"; } } if(array_key_exists("billing_delivery", $filter)) { $billing_delivery = FronkDB::singleton()->escape($filter['billing_delivery']); if($billing_delivery) { $where .= " AND PreorderBillingInvoice.billing_delivery = '$billing_delivery'"; } } if(array_key_exists("date_delivered", $filter)) { $date_delivered = $filter['date_delivered']; if($date_delivered === null || $date_delivered === false) { $where .= " AND (PreorderBillingInvoice.date_delivered IS NULL OR PreorderBillingInvoice.date_delivered=0)"; } elseif($date_delivered === true) { $where .= " AND (PreorderBillingInvoice.date_delivered IS NOT NULL AND PreorderBillingInvoice.date_delivered > 0)"; } elseif(is_numeric($date_delivered)) { $where .= " AND PreorderBillingInvoice.date_delivered=$date_delivered"; } } if(array_key_exists("bmd_export_date", $filter)) { $bmd_export_date = $filter['bmd_export_date']; if($bmd_export_date === null || $bmd_export_date === false) { $where .= " AND (PreorderBillingInvoice.bmd_export_date IS NULL OR PreorderBillingInvoice.bmd_export_date=0)"; } elseif($bmd_export_date === true) { $where .= " AND (PreorderBillingInvoice.bmd_export_date IS NOT NULL AND PreorderBillingInvoice.bmd_export_date > 0)"; } elseif(is_numeric($bmd_export_date)) { $where .= " AND PreorderBillingInvoice.bmd_export_date=$bmd_export_date"; } } if(array_key_exists("add-where", $filter)) { $where .= " ".$filter['add-where']; } //var_dump($filter, $where);exit; return $where; } }