From cc4f2e3bdbafac1ddcc228501f0aeff469e99424 Mon Sep 17 00:00:00 2001 From: Frank Schubert Date: Tue, 9 Jul 2024 18:50:08 +0200 Subject: [PATCH] Invoice BMD export --- Layout/default/Invoice/Index.php | 8 +- application/Billing/BillingController.php | 4 +- application/Invoice/InvoiceController.php | 123 +++++++++++++++++- application/Invoice/InvoiceModel.php | 11 ++ application/IvtBill/IvtBillModel.php | 26 ++++ .../20240709105957_invoice_add_bmd_export.php | 31 +++++ scripts/import-sepa-date-from-ivt.php | 65 ++++++--- 7 files changed, 241 insertions(+), 27 deletions(-) create mode 100644 db/migrations/20240709105957_invoice_add_bmd_export.php diff --git a/Layout/default/Invoice/Index.php b/Layout/default/Invoice/Index.php index f81634be5..809f776d5 100644 --- a/Layout/default/Invoice/Index.php +++ b/Layout/default/Invoice/Index.php @@ -1,7 +1,7 @@ getUrl($Mod, "Index"); $pagination_baseurl_params = ["filter" => $filter]; -$pagination_entity_name = "Billingrecords"; +$pagination_entity_name = "Rechnungen"; ?> @@ -62,7 +62,9 @@ $pagination_entity_name = "Billingrecords";
@@ -99,7 +101,7 @@ $pagination_entity_name = "Billingrecords"; country?> ">€ - ">€ total_vat,2,",",".")?> + € ">€ billing_type == "sepa") ? "SEPA" : "Überweisung"?> billing_delivery == "email") ? "Email" : "Papier"?> diff --git a/application/Billing/BillingController.php b/application/Billing/BillingController.php index 06a5f18fa..3e37c96f1 100644 --- a/application/Billing/BillingController.php +++ b/application/Billing/BillingController.php @@ -113,6 +113,8 @@ class BillingController extends mfBaseController { return $new_filter; } + + protected function importContractsAction() { $r = $this->request; @@ -417,7 +419,7 @@ class BillingController extends mfBaseController { $data["billing_delivery"] = $billing_delivery; $data["bank_account_bank"] = $billingaddress->bank_account_bank; $data["bank_account_owner"] = $billingaddress->bank_account_owner; - $data["bank_account_iban"] = $billingaddress->bank_account_iban; + $data["bank_account_iban"] = str_replace(" ", "", $billingaddress->bank_account_iban); $data["bank_account_bic"] = $billingaddress->bank_account_bic; $data["product_id"] = $contract->product_id; $data["product_name"] = $contract->product_name; diff --git a/application/Invoice/InvoiceController.php b/application/Invoice/InvoiceController.php index 05086abba..c62d93191 100644 --- a/application/Invoice/InvoiceController.php +++ b/application/Invoice/InvoiceController.php @@ -203,6 +203,7 @@ XINON GmbH"; $invoice_data = []; $invoice_vatrate = 20; + $price_total_sum = 0; foreach($billing_rows as $bill) { $vatarea = $bill->vatarea; @@ -218,6 +219,8 @@ XINON GmbH"; $add_setup_position = ($price > 0 && $price_setup > 0); $is_setup_only = ($price < 0.00001 && $price_setup > 0); + $price_total_sum += $price_gross + $price_setup_gross; + $position_data = []; $position_data["billing_id"] = $bill->id; $position_data["contract_id"] = $bill->contract_id; @@ -347,12 +350,16 @@ XINON GmbH"; $voicenumber_zone = InvoiceVoicenumberZoneModel::create($zone_data); //var_dump($voicenumber_zone); $invoice_voicenumber->data->voicenumberzones[] = $voicenumber_zone; + + } } //var_dump($invoice_voicenumber);exit; $invoice_voicenumbers[] = $invoice_voicenumber; } - //var_dump($invoice_voicenumbers);exit; + + $price_total_sum += $total_voice_price; + //var_dump($invoice_voicenumbers);exit; $this->log->debug("Adding Voice Invoiceposition for Contract ID " . $bill->contract_id); @@ -363,7 +370,6 @@ XINON GmbH"; $voice_data["price"] = $total_voice_price; $voice_data["price_total"] = $total_voice_price; $voice_data["price_gross"] = $total_voice_price + (($total_voice_price / 100) * 20); - $voice_data["vatrate"] = $invoice_vatrate; $voice_data["start_date"] = $voice_start_date; $voice_data["end_date"] = $voice_end_date; $voice_position = InvoicepositionModel::create($voice_data); @@ -416,6 +422,13 @@ XINON GmbH"; } + /* + // to not generate zero total invoices + if($price_total_sum == 0.0000) { + continue; + }*/ + + /* * ******************************* * Save invoice and add positions @@ -512,6 +525,13 @@ XINON GmbH"; $invoice->rollbackTransaction(); die("Error saving Invoice number and date"); } + + /* + $address = new Address($invoice->billingaddress_id); + if($address) { + $address->last_invoice_date = date("U"); + $address->save(); + }*/ } catch (Exception $e) { if ($invoice) { $invoice->rollbackTransaction(); @@ -539,4 +559,103 @@ XINON GmbH"; $this->redirect("Invoice"); } + + protected function exportBmdAction() { + /* + * satzart;konto;gkonto;belegnr;belegdatum;buchsymbol;buchcode;prozent;steuercode;betrag;steuer;text;kost;bank-iban-nr;bank-swiftcode;bank-mandatsid;bank-mandatsdatum;bank-mandatskz;bank-letztereinzug;zvsperre;bankeinzug + * 0;234941;40010;TEST-1;23.01.2024;AR;1;20;1;1,2;-0,2;RNTEST-01;;AT293828200003027919;RZSTAT2G282;KJ2813;13.01.2023;0;;0;1 + * 0;234325;40010;TEST-2;23.01.2024;GU;1;20;1;-1,2;0,2;GSTEST-01;;;;;;;;10;0 + */ + + $csv_header = "satzart;konto;gkonto;belegnr;belegdatum;buchsymbol;buchcode;prozent;steuercode;betrag;steuer;text;kost;bank-iban-nr;bank-swiftcode;bank-mandatsid;bank-mandatsdatum;bank-mandatskz;bank-letztereinzug;zvsperre;bankeinzug"; + $csv_out = ""; + + if(!InvoiceModel::search(["bmd_export_date" => null])) { + $this->layout()->setFlash("Keine neuen Rechnungen seit letztem BMD-Export vorhanden."); + $this->redirect("Invoice"); + } + foreach(InvoiceModel::search(["bmd_export_date" => null]) as $invoice) { + if($invoice->bmd_export_date) { + die("wtf"); + } + + $vatrate = (($invoice->total == $invoice->total_gross) ? "0" : "20"); + $vat = $invoice->total_gross - $invoice->total; + $vat *= -1; + + if($invoice->total < 0) { + $buchsymbol = "GU"; + } else { + $buchsymbol = "AR"; + + } + + $buchungstext = "[".$invoice->customer_number."]"; + if($invoice->company) { + $buchungstext .= " ".$invoice->company; + } elseif($invoice->firstname || $invoice->lastname) { + $buchungstext .= " ".$invoice->firstname." ".$invoice->lastname; + } + + $buchungstext = str_replace(["\n","\r", ";"], "", $buchungstext); + + $is_sepa = ($invoice->billing_type == "sepa"); + + $iban = ""; + $bic = ""; + $sepa_id = ""; + $sepa_date = false; + $last_invoice_date = false; + + if($is_sepa) { + $iban = $invoice->bank_account_iban; + $bic = $invoice->bank_account_bic; + $sepa_id = $invoice->sepa_id; + if($invoice->sepa_date) { + $sepa_date = new DateTime($invoice->sepa_date); + if($invoice->sepa_last_date) { + $last_invoice_date = new DateTime($invoice->sepa_last_date); + + if($last_invoice_date->format("Y-m-d") < $sepa_date->format("Y-m-d")) { + $last_invoice_date = false; + } + } + } + + + } + + $csv_out .= "0;"; + $csv_out .= $invoice->fibu_account_number.";"; + $csv_out .= $invoice->fibu_cost_account.";"; + $csv_out .= $invoice->invoice_number.";"; + $csv_out .= date("d.m.Y", $invoice->invoice_date).";"; + $csv_out .= $buchsymbol.";"; + $csv_out .= "1;"; + $csv_out .= $vatrate.";"; + $csv_out .= $invoice->fibu_taxcode.";"; + $csv_out .= number_format($invoice->total_gross, 2, ",", "").";"; + $csv_out .= number_format($vat, 2, ",", "").";"; + $csv_out .= $buchungstext.";"; + $csv_out .= ";"; // kostenstelle + $csv_out .= $iban.";"; + $csv_out .= $bic.";"; + $csv_out .= $sepa_id.";"; + $csv_out .= ($sepa_date ? $sepa_date->format("d.m.Y") : "").";"; + $csv_out .= ($last_invoice_date ? "1" : "0").";"; + $csv_out .= ($last_invoice_date ? $last_invoice_date->format("d.m.Y") : "").";"; + $csv_out .= ($is_sepa ? 0 : 10).";"; + $csv_out .= ($is_sepa ? 1 : 0); + $csv_out .= "\n"; + } + + /*$this->layout()->setFlash("Export erfolgreich abgeschlossen", "success"); + $this->redirect("Invoice");*/ + + header("Content-type: text/csv"); + header('Content-disposition: attachment; filename="tt-rech-export-bmd-'.date('Y-m-d_H-i-s').'.csv"'); + + echo $csv_header."\n".$csv_out; + exit; + } } \ No newline at end of file diff --git a/application/Invoice/InvoiceModel.php b/application/Invoice/InvoiceModel.php index 2753f7c1c..1aa805a93 100644 --- a/application/Invoice/InvoiceModel.php +++ b/application/Invoice/InvoiceModel.php @@ -32,6 +32,7 @@ class InvoiceModel { public $bank_account_bic; public $total; public $total_gross; + public $bmd_export_date; public $total_vat; public $create_by; public $edit_by; @@ -252,6 +253,16 @@ class InvoiceModel { } } + if(array_key_exists("bmd_export_date", $filter)) { + $bmd_export_date = $filter['bmd_export_date']; + if(is_numeric($bmd_export_date)) { + $where .= " AND Invoice.bmd_export_date=$bmd_export_date"; + } elseif($bmd_export_date === null || $bmd_export_date === false) { + $where .= " AND Invoice.bmd_export_date IS NULL"; + } elseif($bmd_export_date === true) { + $where .= " AND Invoice.bmd_export_date > 0"; + } + } if(array_key_exists("billingaddress_id", $filter)) { $Invoiceaddress_id = $filter['billingaddress_id']; diff --git a/application/IvtBill/IvtBillModel.php b/application/IvtBill/IvtBillModel.php index d6365313f..c93cfa209 100644 --- a/application/IvtBill/IvtBillModel.php +++ b/application/IvtBill/IvtBillModel.php @@ -24,6 +24,7 @@ class IvtBillModel { $db = FronkDB::singleton(IVT_DBHOST, IVT_DBUSER, IVT_DBPASS, IVT_DBNAME); $where = self::getSqlFilter($filter); + mfLoghandler::singleton()->debug($where); $res = $db->select("bills", "*", "$where ORDER BY id LIMIT 1"); if($db->num_rows($res)) { $data = $db->fetch_object($res); @@ -41,6 +42,7 @@ class IvtBillModel { $db = FronkDB::singleton(IVT_DBHOST, IVT_DBUSER, IVT_DBPASS, IVT_DBNAME); $where = self::getSqlFilter($filter); + mfLoghandler::singleton()->debug($where); $res = $db->select("bills", "*", "$where ORDER BY id DESC LIMIT 1"); if($db->num_rows($res)) { $data = $db->fetch_object($res); @@ -109,6 +111,30 @@ class IvtBillModel { $where .= " AND bills.date_outgoing <= '$date_outgoing'"; } } + + if(array_key_exists("iban", $filter)) { + $iban = $filter['iban']; + if($iban === true) { + $where .= " AND bills.iban IS NOT NULL AND bills.iban <> ''"; + } elseif ($iban === null || $iban === false) { + $where .= " AND (bills.iban IS NULL OR bills.iban = '')"; + } else { + $iban = FronkDB::singleton()->escape($filter["iban"]); + $where .= " AND bills.iba='$iban' "; + } + } + + if(array_key_exists("bic", $filter)) { + $bic = $filter['bic']; + if($bic === true) { + $where .= " AND bills.bic IS NOT NULL AND bills.bic <> ''"; + } elseif ($bic === null || $bic === false) { + $where .= " AND (bills.bic IS NULL OR bills.bic = '')"; + } else { + $bic = FronkDB::singleton()->escape($filter["bic"]); + $where .= " AND bills.iba='$bic' "; + } + } /* if(array_key_exists("status_id", $filter)) { $status_id = $filter['status_id']; diff --git a/db/migrations/20240709105957_invoice_add_bmd_export.php b/db/migrations/20240709105957_invoice_add_bmd_export.php new file mode 100644 index 000000000..10523dd5d --- /dev/null +++ b/db/migrations/20240709105957_invoice_add_bmd_export.php @@ -0,0 +1,31 @@ +getEnvironment() == "thetool") { + $table = $this->table("Invoice"); + $table->addColumn("bmd_export_date", "integer", ["null" => true, "default" => null, "after" => "total_gross"]); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $this->table("Invoice")->addColumn("bmd_export_date")->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/scripts/import-sepa-date-from-ivt.php b/scripts/import-sepa-date-from-ivt.php index 84190f610..100ddbc0b 100755 --- a/scripts/import-sepa-date-from-ivt.php +++ b/scripts/import-sepa-date-from-ivt.php @@ -17,41 +17,64 @@ define("INTERNAL_USER_USERNAME", $me->username); $i = 0; //foreach(AddressModel::search(["customer_number" => true, "billing_type" => "sepa"]) as $address) { -foreach(AddressModel::search(["fibu_account_number" => true, "billing_type" => "sepa"]) as $address) { - if($address->sepa_date && $address->last_invoice_date) continue; +foreach(AddressModel::search(["billing_type" => "sepa"]) as $address) { + //if($address->sepa_date && $address->last_invoice_date) continue; + $sepa_date = false; + $last_invoice_date = false; + + if(!$address->customer_number) continue; $bill = IvtBillModel::getFirst(["cid" => $address->customer_number, "iban" => true, "bic" => true]); - if(!$bill) continue; - - if(!trim($bill->IBAN) || !trim($bill->BIC)) continue; - if(!$bill->date_outgoing) { - echo "date outgoing fehlt im ivt: ".$address->customer_number."\n"; - continue; + if($bill) { + $out_date = new DateTime($bill->date_outgoing); + $sepa_date = $out_date; + //echo "sepa date: $sepa_date - ".$bill->date_outgoing."\n"; + } else { + // find order + $order = OrderModel::getFirst(["owner_id" => $address->id]); + if($order) { + if($order->order_date) { + $sepa_date = new DateTime("@" . $order->order_date); + if($sepa_date->format("Y") < 2020) $sepa_date = false; + } + if(!$sepa_date) { + // order create + $sepa_date = new DateTime("@" . $order->create); + } + } } - $out_date = new DateTime($bill->date_outgoing); - $sepa_date = $out_date->getTimestamp(); - echo "sepa date: $sepa_date - ".$bill->date_outgoing."\n"; - - if(!$sepa_date){ - echo "Konnte Datum nicht umwandeln\n"; + if(!$sepa_date) { + echo "Kein sepa date für customer_number ".$address->customer_number."\n"; + continue; } $last_bill = IvtBillModel::getLast(["cid" => $address->customer_number, "iban" => true, "bic" => true]); - if(!$last_bill) continue; - $last_date = new DateTime($last_bill->date_outgoing); - $last_invoice_date = $last_date->getTimestamp(); - //echo "last invoice date: $last_invoice_date ".$last_bill->date_outgoing."\n"; + if($last_bill) { + $last_date = new DateTime($last_bill->date_outgoing); + if($last_date->format("Y-m") == "2024-07") { + var_dump($last_date, $last_bill);exit; + } + $last_invoice_date = $last_date->getTimestamp(); + //echo "last invoice date: $last_invoice_date ".$last_bill->date_outgoing."\n"; + } else { + $last_invoice_date = null; + } - if(!$address->sepa_date) { - $address->sepa_date = $sepa_date; + if(!$address->sepa_date && $sepa_date) { + //echo "updating sepa_date ".$address->customer_number."\n"; + $address->sepa_date = $sepa_date->getTimestamp(); $address->save(); } - if(!$address->last_invoice_date) { + if($last_invoice_date) { $address->last_invoice_date = $last_invoice_date; $address->save(); } + if($last_invoice_date === null) { + $address->last_invoice_date = null; + $address->save(); + } $i++; }