added CSV file generation for RML Billing

This commit is contained in:
Frank Schubert
2025-03-22 18:23:28 +01:00
parent 5ff67da367
commit 97c7a1dde5
4 changed files with 115 additions and 7 deletions

View File

@@ -118,12 +118,14 @@ $pagination_entity_name = "Rechnungen";
<tr>
<td>
<a href="<?=self::getUrl("PreorderBillingInvoice", "downloadInvoice", ["id" => $invoice->id])?>"><i class="fas fa-download fa-fw"></i> <?=$invoice->invoice_number?></a>
<?php if($invoice->pdf): ?>
<i class="fas fa-fw fa-check" title="PDF generiert"></i>
<?php endif; ?>
<?php if($invoice->date_delivered): ?>
<i class="fas fa-fw fa-mail" title="per Email versendet am <?=date("d.m.Y H:i", $invoice->date_delivered)?>"></i>
<?php endif; ?>
<?php if($invoice->csv): ?>
<a class="ml-2" href="<?=self::getUrl("PreorderBillingInvoice", "downloadCsv", ["id" => $invoice->id])?>">
<i class="fas fa-fw fa-file-csv" title="CSV-Datei herunterladen"></i>
</a>
<?php endif; ?>
</td>
<td><?=($invoice->invoice_date) ? (new DateTime($invoice->invoice_date))->format("d.m.Y") : ""?></td>
<td><?=$invoice->fibu_account_number?></td>

View File

@@ -4,6 +4,7 @@ class PreorderBillingInvoice extends mfBaseModel {
protected $forcestr = ["company", "zip", "email", "phone"];
private $positions;
private $pdf;
private $csv;
public static function getNextInvoiceNumber($netowner_id) {
@@ -113,6 +114,17 @@ class PreorderBillingInvoice extends mfBaseModel {
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 == "creator") {
$creator = mfValuecache::singleton()->get("Worker-id-".$this->create_by);
if($creator) {

View File

@@ -133,6 +133,38 @@ class PreorderBillingInvoiceController extends mfBaseController {
exit;
}
protected function downloadCsv() {
$id = $this->request->id;
if (!is_numeric($id) || !$id) {
$this->layout()->setFlash("Rechnung nicht gefunden", "error");
$this->redirect("Invoice");
}
$invoice = new PreorderBillingInvoice($id);
if (!$invoice->id) {
$this->layout()->setFlash("Rechnung nicht gefunden", "error");
$this->redirect("Invoice");
}
$csv = $invoice->csv;
$csv_path = $csv->getFullPath();
$filename = $csv->filename;
if(!file_exists($csv_path)) {
$this->layout()->setFlash("CSV-Datei nicht gefunden");
$this->redirect("Invoice");
}
header('Content-Type: text/csv; charset=utf-8');
header('Content-disposition: attachment; filename="'.$filename.'"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Length: " . filesize($csv_path));
readfile($csv_path);
exit;
}
protected function createAction() {
$netowner_id = $this->me->address_id;
$today = new DateTime();
@@ -145,8 +177,8 @@ class PreorderBillingInvoiceController extends mfBaseController {
$base_rows = PreorderBilling::getInvoiceBaseData(['invoice_id' => null, "netowner_id" => $netowner_id]);
//var_dump($base_rows);exit;
$invoice_count = 0;
$invoice_detail_data = [];
foreach($base_rows as $base) {
$invoice_detail_data = [];
$preorderbillingcustomer_id = $base["preorderbillingcustomer_id"];
$owner_id = $base["owner_id"];
$billingaddress_id = $base["billingaddress_id"];
@@ -205,7 +237,7 @@ class PreorderBillingInvoiceController extends mfBaseController {
$year_month = $start_date->format("Ym");
if ($netoperator_id) {
if (!array_key_exists($netoperator_id, $invoice_detail_data)) $invoice_detail_data[$netoperator_id] = [];
//if (!array_key_exists($netoperator_id, $invoice_detail_data)) $invoice_detail_data[$netoperator_id] = [];
$detail_data = [
"owner_id" => $bill->owner_id,
"company" => ($bill->company) ?: $bill->firstname . " " . $bill->lastname,
@@ -213,6 +245,7 @@ class PreorderBillingInvoiceController extends mfBaseController {
"order_date" => $bill->order_date,
"start_date" => $start_date->format("Y-m-d"),
"end_date" => $end_date->format("Y-m-d"),
"article_number" => $bill->article_number,
"product_name" => $bill->product_name,
"amount" => $bill->amount,
"billing_periodic" => $bill->billing_period,
@@ -220,7 +253,7 @@ class PreorderBillingInvoiceController extends mfBaseController {
"price_gross" => $price_gross,
"vatrate" => $bill->vatrate,
];
$invoice_detail_data[$netoperator_id][] = $detail_data;
$invoice_detail_data[] = $detail_data;
}
$position_data = [];
@@ -409,6 +442,67 @@ class PreorderBillingInvoiceController extends mfBaseController {
// commit transaction
$invoice->commitTransaction();
$invoice_count++;
if(count($invoice_detail_data)) {
// create CSV file
//var_dump($invoice_detail_data);exit;
$csv = "\u{FEFF}Netzbetreiber;Rechungsnummer;Rechnungsdateum;OAID;Bestelldatum;Periode von;Periode bis;Artikelnummer;Produkt;Anzahl;Preis Netto\n";
foreach ($invoice_detail_data as $detail) {
//var_dump($detail);
//exit;
$csv .= '"'.str_replace(["\r","\n"], " ", $detail["company"]).'";';
$csv .= '"'.$invoice->invoice_number.'";';
$csv .= '"'.$invoice->invoice_date.'";';
$csv .= '"'.$detail["oaid"].'";';
$csv .= '"'.$detail["order_date"].'";';
$csv .= '"'.$detail["start_date"].'";';
$csv .= '"'.$detail["end_date"].'";';
$csv .= '"'.$detail["article_number"].'";';
$csv .= '"'.$detail["product_name"].'";';
$csv .= round($detail["amount"], 3).';';
$csv .= round($detail["price"], 2)."\n";
}
$subfolder = TT_PREORDER_BILLING[$invoice->netowner_id]["subfolder"]."/".$today->format("Y");
$invoice_path = MFUPLOAD_FILE_SAVE_PATH."/$subfolder";
if(!file_exists($invoice_path)) {
mkdir($invoice_path, 0777, true);
}
$filename = $invoice->invoice_number.".csv";
$filepath = "$invoice_path/$filename";
file_put_contents($filepath, $csv);
try {
$file = FileModel::create([
"name" => $filename,
"filename" => $filename,
"subfolder" => $subfolder,
"store_filename" => $filename,
"orig_filename" => $filename,
]);
if (!$file->save()) {
$this->log->error(__METHOD__ . ": Error saving PDF file");
return false;
}
} catch(Exception $e) {
$this->log->error(__METHOD__ . ": Error saving PDF file");
die("Fehler beim Erzeugen der Rechnungsdetailliste");
}
$ifile = PreorderBillingInvoiceFile::create([
"invoice_id" => $invoice->id,
"file_id" => $file->id,
"name" => $filename,
"description" => ""
]);
if(!$ifile->save()) {
$this->log->error(__METHOD__.": Error saving PDF Invoice Detail CSV");
die("Fehler beim Erzeugen der Rechnungsdetailliste");
}
}
}
$this->log->debug(__METHOD__.": $billing_row_count billing rows | $positions_count positions count | $bill_id_count bill_id count");

View File

@@ -208,7 +208,7 @@ class PreorderBillingInvoiceFile extends mfBaseModel {
if(array_key_exists("name", $filter)) {
$name = FronkDB::singleton()->escape($filter['name']);
if($name) {
$where .= " AND name='$name'";
$where .= " AND name LIKE '$name'";
}
}