diff --git a/Layout/default/Address/View.php b/Layout/default/Address/View.php index 58e854665..591b4d778 100644 --- a/Layout/default/Address/View.php +++ b/Layout/default/Address/View.php @@ -27,6 +27,7 @@ $address->id, 's' => $s, 'f' => "view"])?>" class="btn btn-outline-success"> Adresse bearbeiten
+ $address->id])?>" class="btn btn-purple mr-1"> Tickets $address->id])?>" class="btn btn-purple mr-1"> Rechungsübersicht
diff --git a/Layout/default/ConstructionConsent/Index.php b/Layout/default/ConstructionConsent/Index.php index 437ce156e..4e79018ab 100644 --- a/Layout/default/ConstructionConsent/Index.php +++ b/Layout/default/ConstructionConsent/Index.php @@ -33,10 +33,10 @@ $pagination_entity_name = "Zustimmungserklärungen";
">
-
+
- +
-
+
+ + +
+ +
" />
diff --git a/Layout/default/Device/Detail.php b/Layout/default/Device/Detail.php index bb57d97bc..25d83adb0 100644 --- a/Layout/default/Device/Detail.php +++ b/Layout/default/Device/Detail.php @@ -1,6 +1,3 @@ - @@ -154,11 +151,14 @@

Device: data->name ?> - + is('Admin')) : ?> + $devices->id, 'returnto' => "device-detail"]) ?>"> -

+ + +
@@ -275,7 +275,7 @@ foreach ($devicesall as $deviceall) { } ?> -
+

@@ -289,7 +289,7 @@ foreach ($devicesall as $deviceall) { Pop Name - $devices->pop->id]) ?>">pop->name ?> + is('Admin')) ? ' $devices->pop->id]) . '">' . $devices->pop->name . '' : $devices->pop->name ?> @@ -338,67 +338,75 @@ foreach ($devicesall as $deviceall) { } ?>
-
-
-

Config Backups

- devicetype->devicemanufactor->config_backup > count()): ?> - - - -
- success == "true" && $devicesconfig->data > count()) { - ?> -
- - - - - - - - - data as $config) : - $configfileCleartext = trim($config->config_cleartext); - $configfileCompressed = trim($config->config_compressed); - $configid = $config->id; - if ($configfileCleartext && $configfileCompressed) : + is('Admin')) : ?> +
+
+

Config Backups

+ devicetype->devicemanufactor->config_backup > count()): ?> + + is('Admin')): + ?> + + +
+ success == "true" && $devicesconfig->data > count()) { + ?> +
+
Datum/Uhrzeit
+ + + + + + + + data as $config) : + $configfileCleartext = trim($config->config_cleartext); + $configfileCompressed = trim($config->config_compressed); + $configid = $config->id; + if ($configfileCleartext && $configfileCompressed) : - $configLinks = ' 'getconfig', 'id' => $configid, 'format' => 'txt', 'filename' => $configfileCleartext]) . '"> + $configLinks = ' 'getconfig', 'id' => $configid, 'format' => 'txt', 'filename' => $configfileCleartext]) . '"> TXT / 'getconfig', 'id' => $configid, 'format' => 'xml', 'filename' => $configfileCompressed]) . '"> XML'; - elseif ($configfileCleartext || $configfileCompressed) : - $configLinks = ' 'getconfig', 'id' => $configid, 'format' => 'txt', 'filename' => $configfileCleartext . $configfileCompressed]) . '"> + elseif ($configfileCleartext || $configfileCompressed) : + $configLinks = ' 'getconfig', 'id' => $configid, 'format' => 'txt', 'filename' => $configfileCleartext . $configfileCompressed]) . '"> TXT'; - endif; - ?> - - - + endif; + ?> + + + - - + + - -
Datum/Uhrzeit
config_timestamp); ?>
config_timestamp); ?>
-
- + +
+ +
+
Keine Configs vorhanden
+
+ -
-
Keine Configs vorhanden
-
- -
+ + + devicetype->olt && TT_MBI_API_ENABLE) : @@ -647,6 +655,7 @@ foreach ($devicesall as $deviceall) { $config = str_replace("&&YEAR&&", $year, $config); $config = str_replace("&&MONTH&&", $month, $config); $config = str_replace("&&DAY&&", $day, $config); + $config = str_replace("&&IP&&", $devices->ip, $config); ?> diff --git a/Layout/default/Invoice/Index.php b/Layout/default/Invoice/Index.php index 9e22ad4cb..5f269cc04 100644 --- a/Layout/default/Invoice/Index.php +++ b/Layout/default/Invoice/Index.php @@ -55,7 +55,7 @@ $pagination_entity_name = "Rechnungen"; "/>
- + "/>
@@ -474,4 +474,4 @@ $pagination_entity_name = "Rechnungen"; - \ No newline at end of file + diff --git a/Layout/default/Preorder/Index.php b/Layout/default/Preorder/Index.php index 01ce07859..1e4677ea4 100644 --- a/Layout/default/Preorder/Index.php +++ b/Layout/default/Preorder/Index.php @@ -738,7 +738,9 @@ $pagination_entity_name = "Vorbestellungen"; var marker_popup_content = ''; // popup fields + const preorder_view_url = `/Index?filter[ucode]=${preorder.ucode}#preorder=${preorder.id}`; [ + ["PREORDER_URL", preorder_view_url], ["street", preorder.adb_strasse], ["hausnummer", preorder.adb_hausnummer], ["zip", preorder.adb_plz], diff --git a/Layout/default/Preorder/include/preorder_popup.php b/Layout/default/Preorder/include/preorder_popup.php index e32a66709..9c580d8ab 100644 --- a/Layout/default/Preorder/include/preorder_popup.php +++ b/Layout/default/Preorder/include/preorder_popup.php @@ -37,6 +37,11 @@ ob_start(); Email: {{EMAIL}} - + + + + Bestellung ansehen + + \ No newline at end of file diff --git a/Layout/default/TimerecordingEmployee/Form.php b/Layout/default/TimerecordingEmployee/Form.php index 58e7b1d76..15c8cf7f5 100644 --- a/Layout/default/TimerecordingEmployee/Form.php +++ b/Layout/default/TimerecordingEmployee/Form.php @@ -4,6 +4,7 @@ foreach ($days as $key => $day) { $daysSelect .= ''; } $daysSelect .= ""; + ?> - \ No newline at end of file + diff --git a/Layout/default/VueViews/Vue.php b/Layout/default/VueViews/Vue.php index 491c0e354..35a73afdd 100644 --- a/Layout/default/VueViews/Vue.php +++ b/Layout/default/VueViews/Vue.php @@ -1,64 +1,47 @@ -
:path="window['TT_CONFIG']['PATH']"> - - <>> + <> +>
- \ No newline at end of file + diff --git a/Layout/default/WarehouseOrder/PDF_FOOTER.html b/Layout/default/WarehouseOrder/PDF_FOOTER.html new file mode 100644 index 000000000..0a984b7d6 --- /dev/null +++ b/Layout/default/WarehouseOrder/PDF_FOOTER.html @@ -0,0 +1,43 @@ + + + + Xinon Rechnung + + + + + + +
+
+ XINON GmbH | Fladnitz 150 | 8322 Studenzen
+ Tel.: +43 3115 40800 | E-Mail: office@xinon.at
+ UID: ATU68711968 | FN: 416556h | LG: Feldbach
+ IBAN: {{ bank_iban }} | BIC: {{ bank_bic }}
+
+ +
Seite von
+ +
+ + diff --git a/Layout/default/WarehouseOrder/PDF_HEADER.html b/Layout/default/WarehouseOrder/PDF_HEADER.html new file mode 100644 index 000000000..21802f9d5 --- /dev/null +++ b/Layout/default/WarehouseOrder/PDF_HEADER.html @@ -0,0 +1,92 @@ + + + + XINON Shipping Note Header + + + + + +
+ +
+ Xinon Logo +
+ + + + + + + +
+

Lieferant

+
{{ addressLine_1 }}
+
{{ addressLine_2 }}
+
{{ addressLine_3 }}
+
{{ addressLine_4 }}
+
+
{{ externalReference }}
+
+

Rechnungsadresse

+
{{ billingAddressLine_1 }}
+
{{ billingAddressLine_2 }}
+
{{ billingAddressLine_3 }}
+
{{ billingAddressLine_4 }}
+
{{ billingAddressLine_5 }}
+
{{ billingAddressLine_6 }}
+
+
{{ shippingAddressLine_1 }}
+
{{ shippingAddressLine_2 }}
+
{{ shippingAddressLine_3 }}
+
{{ shippingAddressLine_4 }}
+
+ + +
+ + + diff --git a/Layout/default/WarehouseOrder/PDF_MAIN.php b/Layout/default/WarehouseOrder/PDF_MAIN.php new file mode 100644 index 000000000..144555322 --- /dev/null +++ b/Layout/default/WarehouseOrder/PDF_MAIN.php @@ -0,0 +1,133 @@ +setReturnValue(['filename' => $order["id"] . ".pdf"]); +?> + + + + + Bestellung + + + + + + +
+ +

XINON Lieferantenbestellung vom

+ + + + + + + + + + + + + "> + + + + + + + + + + + + + + + + + +
PositionArtikelArt.-Nr. LieferantMengeEinzelpreisGesamtpreis
Summe
+ +
+

Anmerkungen

+

+ +

+
+ + \ No newline at end of file diff --git a/Layout/default/menu.php b/Layout/default/menu.php index b670b56fd..0acf0392f 100644 --- a/Layout/default/menu.php +++ b/Layout/default/menu.php @@ -49,7 +49,7 @@ - is(["Admin"]) || ($me->is("netowner") && $me->hasGwrNetworks())): ?> + is(["Admin"]) || ($me->is("netowner","lineplanner","pipeplanner","pipeworker","lineworker","salespartner"))): ?>
  • Stammdaten
    @@ -64,7 +64,11 @@
  • "> Netzgebiete
  • "> Pops
  • + + is(["Admin"]) || ($me->is("netowner","lineplanner","pipeplanner","pipeworker","lineworker","salespartner"))): ?>
  • "> Devices
  • + + is(["Admin"])): ?>
  • "> Benutzer
  • Grundstammdaten
  • @@ -194,7 +198,7 @@ is(["Admin","salespartner"]) && $me->can("Order")): ?>
  • "> Bestellungen
  • - is(["Admin","netowner","salespartner"]) && in_array($me->address_id, [1,209])): ?> + is(["Admin","netowner","salespartner"]) && in_array($me->address_id, [1,209,5908])): ?>
  • "> Zustimmungserklärungen
  • diff --git a/application/Address/AddressController.php b/application/Address/AddressController.php index 26c0fed77..cdb9f1543 100644 --- a/application/Address/AddressController.php +++ b/application/Address/AddressController.php @@ -1,659 +1,678 @@ needlogin=true; - $me = new User(); - $me->loadMe(); - $this->me = $me; - $this->layout()->set("me",$me); - - if(!$me->is(["Admin", "salespartner"])) { - $this->redirect("Dashboard"); - } - } - - protected function indexAction() { - $rfilter = $this->request->filter; - iF(!is_array($rfilter)) { - $rfilter = []; - } - if(!array_key_exists("addresstype", $rfilter)) { - $rfilter["addresstype"] = []; - } - - if($this->request->resetFilter) { - unset($_SESSION[MFAPPNAME.'-Address-filter']); - } - - $filter = []; - if(is_array($this->request->filter)) { - $filter = $this->request->filter; - $_SESSION[MFAPPNAME.'-Address-filter'] = $filter; - } else { - if(array_key_exists(MFAPPNAME.'-Address-filter', $_SESSION) && count($_SESSION[MFAPPNAME.'-Address-filter'])) { - $filter = $_SESSION[MFAPPNAME.'-Address-filter']; - } - } - - $this->layout->set("filter", $filter); - $filter = $this->getPreparedFilter($filter); - - // pagination defaults - $pagination = []; - $pagination['start'] = 0; - $pagination['count'] = 25; - $pagination['maxItems'] = 0; - - if(is_numeric($this->request->s)) { - $pagination['start'] = intval($this->request->s); - } - //var_dump($filter);exit; - $pagination['maxItems'] = AddressModel::count($filter); - $addresses = AddressModel::search($filter, $pagination); - - $this->layout()->set("addresses", $addresses); - $this->layout()->set("request", $this->request); - $this->layout()->set("pagination", $pagination); - - - $last_export = false; - $bmd_export_ts = new mfConfig("bmd.export.ts"); - if($bmd_export_ts->value()) { - $last_export = $bmd_export_ts->value(); - } - $this->layout()->set("last_bmd_export", $last_export); - - return true; - } - - - private function getPreparedFilter($filter) { - $new_filter = []; - - if(is_array($filter) && count($filter)) { - - $new_filter['add-where'] = ""; - - if(array_key_exists("kunde", $filter) && $filter["kunde"]) { - $kunde = $this->db()->escape($filter['kunde']); - // if kunde contains ß or ss we want to search both cases but not with % because it can lead to wrong results - if (strpos($kunde, "ß") !== false || strpos($kunde, "ss") !== false) { - $kundeWithSS = str_replace("ß", "ss", $kunde); - $kundeWithoutSS = str_replace("ss", "ß", $kunde); - $new_filter['add-where'] .= " AND (company like '%$kundeWithoutSS%' OR firstname like '%$kundeWithoutSS%' OR lastname like '%$kundeWithoutSS%' OR concat(firstname, ' ', lastname) like '%$kundeWithoutSS%' OR concat(lastname, ' ', firstname) like '%$kundeWithoutSS%')"; - $new_filter['add-where'] .= " OR (company like '%$kundeWithSS%' OR firstname like '%$kundeWithSS%' OR lastname like '%$kundeWithSS%' OR concat(firstname, ' ', lastname) like '%$kundeWithSS%' OR concat(lastname, ' ', firstname) like '%$kundeWithSS%')"; - } else { - $new_filter['add-where'] .= " AND (company like '%$kunde%' OR firstname like '%$kunde%' OR lastname like '%$kunde%' OR concat(firstname, ' ', lastname) like '%$kunde%' OR concat(lastname, ' ', firstname) like '%$kunde%')"; + private $filter; + + protected function init() { + $this->needlogin = true; + $me = new User(); + $me->loadMe(); + $this->me = $me; + $this->layout()->set("me", $me); + + if (!$me->is(["Admin", "salespartner"])) { + $this->redirect("Dashboard"); } - } - - if(!array_key_exists("parents_only", $filter)) { - $new_filter["parents_only"] = 1; - } - - if(array_key_exists("fibu_account_number", $filter) && $filter['fibu_account_number']) { - $new_filter['fibu_or_supplier_account_number'] = $filter['fibu_account_number']."%"; - unset($filter['fibu_account_number']); - } - - - if(!array_key_exists("customer_number", $filter) || !$filter["customer_number"]) { - if(array_key_exists("type", $filter)) { - if($filter["type"] == "systemowner") { - $new_filter["customer_or_fibu_numbers"] = true; - } elseif($filter["type"] == "others") { - $new_filter["customer_or_fibu_numbers"] = false; - } + } + + protected function indexAction() { + $rfilter = $this->request->filter; + iF(!is_array($rfilter)) { + $rfilter = []; + } + if (!array_key_exists("addresstype", $rfilter)) { + $rfilter["addresstype"] = []; + } + + if ($this->request->resetFilter) { + unset($_SESSION[MFAPPNAME . '-Address-filter']); + } + + $filter = []; + if (is_array($this->request->filter)) { + $filter = $this->request->filter; + $_SESSION[MFAPPNAME . '-Address-filter'] = $filter; } else { - if(defined("TT_ADDRESS_FILTER_DEFAULT_SYSOWNER") && TT_ADDRESS_FILTER_DEFAULT_SYSOWNER) { - $new_filter["customer_or_fibu_numbers"] = true; // default + if (array_key_exists(MFAPPNAME . '-Address-filter', $_SESSION) && count($_SESSION[MFAPPNAME . '-Address-filter'])) { + $filter = $_SESSION[MFAPPNAME . '-Address-filter']; } } - unset($filter["type"]); - unset($filter["customer_number"]); - } - - foreach($filter as $name => $value) { - $new_filter[$name] = $value; - } - } - return $new_filter; - } - - protected function addAction() { - $this->layout()->setTemplate("Address/Form"); + $this->layout->set("filter", $filter); + $filter = $this->getPreparedFilter($filter); - $this->layout->set("filter", $this->request->filter); - - //$parents = AddressModel::search(['parent_id' => null]); - //$this->layout()->set("parents", $parents); - } - - protected function viewAction() { - $this->layout()->setTemplate("Address/View"); - - $this->layout->set("filter", $this->request->filter); - $this->layout->set("f", $this->request->f); - $this->layout->set("s", $this->request->s); - - $address = new Address($this->request->id); - $this->layout()->set("address", $address); + // pagination defaults + $pagination = []; + $pagination['start'] = 0; + $pagination['count'] = 25; + $pagination['maxItems'] = 0; - //var_dump($address->links_to);exit; - - if(!$address->id) { - $this->layout()->setFlash("Addresse nicht gefunden", "error"); - $this->redirect("Address"); - } - - } + if (is_numeric($this->request->s)) { + $pagination['start'] = intval($this->request->s); + } + //var_dump($filter);exit; + $pagination['maxItems'] = AddressModel::count($filter); + $addresses = AddressModel::search($filter, $pagination); - protected function invoiceAction() { - $this->layout()->setTemplate("Address/invoice"); - - $address_id = $this->request->address_id; - if(!is_numeric($address_id) || $address_id < 1) { - $this->layout()->setFlash("Addresse nicht gefunden", "error"); - $this->redirect("Address"); - } - - $address = new Address($address_id); - if(!$address->id) { - $this->layout()->setFlash("Addresse nicht gefunden", "error"); - $this->redirect("Address"); - } - - $invoices = InvoiceModel::search(["owner_or_billingaddress_id" => $address->id], false, "invoice_date DESC"); - $this->layout()->set("invoices", $invoices); - $this->layout()->set("address", $address); + $this->layout()->set("addresses", $addresses); + $this->layout()->set("request", $this->request); + $this->layout()->set("pagination", $pagination); + $last_export = false; + $bmd_export_ts = new mfConfig("bmd.export.ts"); + if ($bmd_export_ts->value()) { + $last_export = $bmd_export_ts->value(); + } + $this->layout()->set("last_bmd_export", $last_export); - } - - protected function editAction() { - $address = new Address($this->request->id); - - $this->layout->set("filter", $this->request->filter); - $this->layout->set("f", $this->request->f); - $this->layout->set("s", $this->request->s); - - $this->layout()->set("address", $address); - - if(!$address->id) { - $this->layout()->setFlash("Addresse nicht gefunden", "error"); - return $this->addAction(); + return true; } - - return $this->addAction(); - } - - protected function deleteLink() { - $id = $this->request->id; - - if(!is_numeric($id) || !$id) { - $this->layout()->setFlash("Addresse nicht gefunden", "error"); - $this->redirect("Address"); - } - - $link = new AddressLink($id); - if(!$link->id) { - $this->layout()->setFlash("Addresse nicht gefunden", "error"); - $this->redirect("Address"); - } - - $address_id = $link->origin_address_id; - $link->delete(); - $this->layout()->setFlash("Verknüpfung erfolgreich entfernt", "success"); - $this->redirect("Address", "edit", ['id' => $address_id]); - - } - - protected function exportBmdAction() { - if(!$this->me->can("Fibu")) { - $this->layout()->setFlash("Sicha ned!", "error"); - $this->redirect("Address"); - } - - $return = Address::runBmdExport($this->request->type); - - if($return === 10) { - $this->layout()->setFlash("Export Pfad (".TT_ADDRESS_BMD_EXPORT_PATH.") nicht gefunden!", "error"); - $this->redirect("Address"); - } - - if($return === 11) { - $this->layout()->setFlash("Keine geänderten Adressdatensätze gefunden. Export abgebrochen.", "warn"); - $this->redirect("Address"); - } - - if($return === 19) { - $this->layout()->setFlash("Datei ".TT_ADDRESS_BMD_EXPORT_PATH."/".TT_ADDRESS_BMD_EXPORT_FILENAME." konnte nicht gespeichert werden!", "error"); - $this->redirect("Address"); - } - - if($return === true) { - $this->layout()->setFlash("Adressen erfolgreich exportiert", "success"); - $this->redirect("Address"); - } - - - } - - protected function saveAction() { - $r = $this->request; - $id = $r->id; - //var_dump($r->get());exit; - if(is_numeric($id) && $id > 0) { - $mode = "edit"; - $address = new Address($id); - if(!$address->id) { - $this->layout()->setFlash("Addresse nicht gefunden", "error"); - $this->redirect("Address"); - } - } else { - $mode = "add"; - } - - //var_dump($r->addresstypes);exit; - - $data = []; - $data['parent_id'] = (!$r->parent_id) ? null : $r->parent_id; - $data['company'] = trim($r->company); - $data['firstname'] = trim($r->firstname); - $data['lastname'] = trim($r->lastname); - $data['street'] = trim($r->street); - $data['zip'] = trim($r->zip); - $data['city'] = trim($r->city); - $data['country_id'] = $r->country_id; - $data['phone'] = trim($r->phone); - $data['fax'] = trim($r->fax); - $data['mobile'] = trim($r->mobile); - $data['email'] = trim($r->email); - $data['note'] = trim($r->note); - $data['uid'] = trim($r->uid); - if(trim($r->birthdate)) { - try { - $data["birthdate"] = (DateTime::createFromFormat("d.m.Y", trim($r->birthdate)))->format("Y-m-d"); - } catch(Exception $e) { - $this->layout()->setFlash("Ungültiges Geburtsdaum", "warning"); + + private function getPreparedFilter($filter) { + $new_filter = []; + + if (is_array($filter) && count($filter)) { + + $new_filter['add-where'] = ""; + + if (array_key_exists("kunde", $filter) && $filter["kunde"]) { + $kunde = $this->db()->escape($filter['kunde']); + // if kunde contains ß or ss we want to search both cases but not with % because it can lead to wrong results + if (strpos($kunde, "ß") !== false || strpos($kunde, "ss") !== false) { + $kundeWithSS = str_replace("ß", "ss", $kunde); + $kundeWithoutSS = str_replace("ss", "ß", $kunde); + $new_filter['add-where'] .= " AND (company like '%$kundeWithoutSS%' OR firstname like '%$kundeWithoutSS%' OR lastname like '%$kundeWithoutSS%' OR concat(firstname, ' ', lastname) like '%$kundeWithoutSS%' OR concat(lastname, ' ', firstname) like '%$kundeWithoutSS%')"; + $new_filter['add-where'] .= " OR (company like '%$kundeWithSS%' OR firstname like '%$kundeWithSS%' OR lastname like '%$kundeWithSS%' OR concat(firstname, ' ', lastname) like '%$kundeWithSS%' OR concat(lastname, ' ', firstname) like '%$kundeWithSS%')"; + } else { + $new_filter['add-where'] .= " AND (company like '%$kunde%' OR firstname like '%$kunde%' OR lastname like '%$kunde%' OR concat(firstname, ' ', lastname) like '%$kunde%' OR concat(lastname, ' ', firstname) like '%$kunde%')"; + } + } + + if (!array_key_exists("parents_only", $filter)) { + $new_filter["parents_only"] = 1; + } + + if (array_key_exists("fibu_account_number", $filter) && $filter['fibu_account_number']) { + $new_filter['fibu_or_supplier_account_number'] = $filter['fibu_account_number'] . "%"; + unset($filter['fibu_account_number']); + } + + + if (!array_key_exists("customer_number", $filter) || !$filter["customer_number"]) { + if (array_key_exists("type", $filter)) { + if ($filter["type"] == "systemowner") { + $new_filter["customer_or_fibu_numbers"] = true; + } elseif ($filter["type"] == "others") { + $new_filter["customer_or_fibu_numbers"] = false; + } + } else { + if (defined("TT_ADDRESS_FILTER_DEFAULT_SYSOWNER") && TT_ADDRESS_FILTER_DEFAULT_SYSOWNER) { + $new_filter["customer_or_fibu_numbers"] = true; // default + } + } + unset($filter["type"]); + unset($filter["customer_number"]); + } + + foreach ($filter as $name => $value) { + $new_filter[$name] = $value; + } + } + + return $new_filter; + } + + protected function addAction() { + $this->layout()->setTemplate("Address/Form"); + + $this->layout->set("filter", $this->request->filter); + + //$parents = AddressModel::search(['parent_id' => null]); + //$this->layout()->set("parents", $parents); + } + + protected function viewAction() { + $this->layout()->setTemplate("Address/View"); + + $this->layout->set("filter", $this->request->filter); + $this->layout->set("f", $this->request->f); + $this->layout->set("s", $this->request->s); + + $address = new Address($this->request->id); + $this->layout()->set("address", $address); + + //var_dump($address->links_to);exit; + + if (!$address->id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("Address"); } } + protected function invoiceAction() { + $this->layout()->setTemplate("Address/invoice"); - if($this->me->can("Fibu")) { - $data["sepa_date"] = ($r->sepa_date) ? Layout::dateToInt($r->sepa_date) : null; - - $data['fibu_account_number'] = ($r->fibu_account_number) ? trim($r->fibu_account_number) : null; - $data['fibu_supplier_number'] = ($r->fibu_supplier_number) ? trim($r->fibu_supplier_number) : null; - if($r->fibu_primary_account) { - $data['fibu_primary_account'] = 1; - } else { - $data['fibu_primary_account'] = 0; - } - - if($r->fibu_supplier_paymentblock) { - $data['fibu_supplier_paymentblock'] = 1; - } else { - $data['fibu_supplier_paymentblock'] = 0; - } - - $data['fibu_supplier_due'] = ($r->fibu_supplier_due) ? trim($r->fibu_supplier_due) : null; - $data['fibu_supplier_skonto'] = ($r->fibu_supplier_skonto) ? trim($r->fibu_supplier_skonto) : null; - $data['fibu_supplier_skonto_rate'] = ($r->fibu_supplier_skonto_rate) ? trim($r->fibu_supplier_skonto_rate) : null; - } - - - // billing data - // validate sepa - if(!$r->billing_type) { - $this->layout()->setFlash("Ungültige Verrechnungsart."); - $this->layout()->set("order", $r); - return $this->add(); - } - - if($r->billing_type == "sepa") { - foreach(['owner', 'iban', 'bic'] as $required) { - if(!$r->{"bank_account_$required"}) { - $this->layout()->setFlash("Bitte Bankdaten für SEPA ausfüllen.", "warn"); - $this->layout()->set("address", $r); - return $this->add(); + $address_id = $this->request->address_id; + if (!is_numeric($address_id) || $address_id < 1) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("Address"); } - } - } - - if($r->billing_type == "sepa") { - $data['billing_type'] = "sepa"; - if(!$r->sepa_date) { - if($mode == "add" || ($mode == "edit" && !$address->sepa_date)) { - $data['sepa_date'] = date('U'); + + $address = new Address($address_id); + if (!$address->id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("Address"); } - } else { - $data['sepa_date'] = Layout::dateToInt($r->sepa_date); - } - } else { - $data['billing_type'] = "invoice"; + + $invoices = InvoiceModel::search(["owner_or_billingaddress_id" => $address->id], false, "invoice_date DESC"); + $this->layout()->set("invoices", $invoices); + $this->layout()->set("address", $address); + + } - - if($r->billing_delivery == "paper") { - $data['billing_delivery'] = "paper"; - } else { - $data['billing_delivery'] = "email"; + + protected function editAction() { + $address = new Address($this->request->id); + + $this->layout->set("filter", $this->request->filter); + $this->layout->set("f", $this->request->f); + $this->layout->set("s", $this->request->s); + + $this->layout()->set("address", $address); + + if (!$address->id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + return $this->addAction(); + } + + return $this->addAction(); } - - - $data['bank_account_bank'] = trim($r->bank_account_bank); - $data['bank_account_owner'] = trim($r->bank_account_owner); - $data['bank_account_iban'] = trim($r->bank_account_iban); - $data['bank_account_bic'] = trim($r->bank_account_bic); - $data['allow_contact'] = ($r->allow_contact) ? 1 : 0; - $data['allow_spin'] = ($r->allow_spin) ? 1 : 0; - - if($mode == "add") { - $address = AddressModel::create($data); - } else { - $address->update($data); + + protected function deleteLink() { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("Address"); + } + + $link = new AddressLink($id); + if (!$link->id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("Address"); + } + + $address_id = $link->origin_address_id; + $link->delete(); + $this->layout()->setFlash("Verknüpfung erfolgreich entfernt", "success"); + $this->redirect("Address", "edit", ['id' => $address_id]); + } - - //var_dump($address);exit; - - $new_id = $address->save(); - if(!$new_id) { - $this->layout()->setFlash("Fehler beim Speichern", "error"); - $this->layout()->set("address", $address); - return $this->add(); + + protected function exportBmdAction() { + if (!$this->me->can("Fibu")) { + $this->layout()->setFlash("Sicha ned!", "error"); + $this->redirect("Address"); + } + + $return = Address::runBmdExport($this->request->type); + + if ($return === 10) { + $this->layout()->setFlash("Export Pfad (" . TT_ADDRESS_BMD_EXPORT_PATH . ") nicht gefunden!", "error"); + $this->redirect("Address"); + } + + if ($return === 11) { + $this->layout()->setFlash("Keine geänderten Adressdatensätze gefunden. Export abgebrochen.", "warn"); + $this->redirect("Address"); + } + + if ($return === 19) { + $this->layout()->setFlash("Datei " . TT_ADDRESS_BMD_EXPORT_PATH . "/" . TT_ADDRESS_BMD_EXPORT_FILENAME . " konnte nicht gespeichert werden!", "error"); + $this->redirect("Address"); + } + + if ($return === true) { + $this->layout()->setFlash("Adressen erfolgreich exportiert", "success"); + $this->redirect("Address"); + } + + } - - // check for multiple primary fibu accounts, and remove from any other than this one - if($address->fibu_primary_account && $address->fibu_account_number) { - foreach(AddressModel::search(["fibu_primary_account" => true, "fibu_account_number" => $address->fibu_account_number]) as $fibu_primary) { - if($fibu_primary->id == $address->id) continue; - $fibu_primary->fibu_primary_account = 0; - $fibu_primary->save(); - } - } - - - // save address types - $new_types = $r->addresstypes; - if(is_array($new_types)) { - foreach($address->types as $existing_type) { - //var_dump($existing_type); - //var_dump($new_types); - //echo $existing_type->type; - if(!in_array($existing_type->type, $new_types)) { - $existing_type->delete(); + + protected function saveAction() { + $r = $this->request; + $id = $r->id; + //var_dump($r->get());exit; + if (is_numeric($id) && $id > 0) { + $mode = "edit"; + $address = new Address($id); + if (!$address->id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("Address"); + } } else { - // remove existing type from new_types array (dont need to create again) - $new_types = array_diff($new_types, [$existing_type->type]); - //unset($new_types[$existing_type]); + $mode = "add"; } - } - //exit; - foreach($new_types as $type) { - $type_object = AddresstypeModel::create(['address_id' => $address->id, 'type' => $type]); - $type_object->save(); - $address->types[$type] = $type_object; - } - } - - // generate new supplier account number if is supplier and supplier num empty - //var_dump($mode, $address->fibu_supplier_number, $address->types);exit; - if(!$address->fibu_supplier_number && array_key_exists("supplier", $address->types)) { - $supplier_num = Address::getNextSupplierNumber(); - if(!$supplier_num) { - $this->layout()->setFlash("Lieferantennummer konnte nicht generiert werden."); - } else { - $this->log->debug("new supplier number: ". $supplier_num); - $address->fibu_supplier_number = $supplier_num; - $address->save(); - } - } - - $attribs = $r->attributes; - //var_dump($attribs);exit; - if(is_array($attribs) && count($attribs)) { - foreach($attribs as $attrib => $value) { - $aa = AddressattributeModel::getFirst(["address_id" => $new_id, "name" => $attrib]); - - if(!$aa) { - $aa = AddressattributeModel::create(["address_id" => $new_id, "name" => $attrib]); + + //var_dump($r->addresstypes);exit; + + $data = []; + $data['parent_id'] = (!$r->parent_id) ? null : $r->parent_id; + $data['company'] = trim($r->company); + $data['firstname'] = trim($r->firstname); + $data['lastname'] = trim($r->lastname); + $data['street'] = trim($r->street); + $data['zip'] = trim($r->zip); + $data['city'] = trim($r->city); + $data['country_id'] = $r->country_id; + $data['phone'] = trim($r->phone); + $data['fax'] = trim($r->fax); + $data['mobile'] = trim($r->mobile); + $data['email'] = trim($r->email); + $data['note'] = trim($r->note); + $data['uid'] = trim($r->uid); + + if (trim($r->birthdate)) { + try { + $data["birthdate"] = (DateTime::createFromFormat("d.m.Y", trim($r->birthdate)))->format("Y-m-d"); + } catch (Exception $e) { + $this->layout()->setFlash("Ungültiges Geburtsdaum", "warning"); + } + } - $aa->value = $value; - $aa->save(); - } - } - - - //$address->deleteLinks(); - - $existing_links = []; - foreach(AddressLinkModel::search(['origin_address_id', $new_id]) as $elink) { - $existing_links[$elink->address_id] = $elink; - } - - //var_dump($r->links);exit; - if(is_array($r->links) && count($r->links)) { - //var_dump($r->links);exit; - foreach($r->links as $linknum => $link) { - if(!$link['type'] || !$link['address_id']) { - continue; + + + if ($this->me->can("Fibu")) { + $data["sepa_date"] = ($r->sepa_date) ? Layout::dateToInt($r->sepa_date) : null; + + $data['fibu_account_number'] = ($r->fibu_account_number) ? trim($r->fibu_account_number) : null; + $data['fibu_supplier_number'] = ($r->fibu_supplier_number) ? trim($r->fibu_supplier_number) : null; + if ($r->fibu_primary_account) { + $data['fibu_primary_account'] = 1; + } else { + $data['fibu_primary_account'] = 0; + } + + if ($r->fibu_supplier_paymentblock) { + $data['fibu_supplier_paymentblock'] = 1; + } else { + $data['fibu_supplier_paymentblock'] = 0; + } + + $data['fibu_supplier_due'] = ($r->fibu_supplier_due) ? trim($r->fibu_supplier_due) : null; + $data['fibu_supplier_skonto'] = ($r->fibu_supplier_skonto) ? trim($r->fibu_supplier_skonto) : null; + $data['fibu_supplier_skonto_rate'] = ($r->fibu_supplier_skonto_rate) ? trim($r->fibu_supplier_skonto_rate) : null; } - if(array_key_exists($link['address_id'], $existing_links)) { - continue; + + + // billing data + // validate sepa + if (!$r->billing_type) { + $this->layout()->setFlash("Ungültige Verrechnungsart."); + $this->layout()->set("order", $r); + return $this->add(); } - $l = AddressLinkModel::create([ - 'origin_address_id' => $new_id, - 'type' => $link['type'], - 'address_id' => $link['address_id'] - ]); - $l->save(); - - } + + if ($r->billing_type == "sepa") { + foreach (['owner', 'iban', 'bic'] as $required) { + if (!$r->{"bank_account_$required"}) { + $this->layout()->setFlash("Bitte Bankdaten für SEPA ausfüllen.", "warn"); + $this->layout()->set("address", $r); + return $this->add(); + } + } + } + + if ($r->billing_type == "sepa") { + $data['billing_type'] = "sepa"; + if (!$r->sepa_date) { + if ($mode == "add" || ($mode == "edit" && !$address->sepa_date)) { + $data['sepa_date'] = date('U'); + } + } else { + $data['sepa_date'] = Layout::dateToInt($r->sepa_date); + } + } else { + $data['billing_type'] = "invoice"; + } + + if ($r->billing_delivery == "paper") { + $data['billing_delivery'] = "paper"; + } else { + $data['billing_delivery'] = "email"; + } + + + $data['bank_account_bank'] = trim($r->bank_account_bank); + $data['bank_account_owner'] = trim($r->bank_account_owner); + $data['bank_account_iban'] = trim($r->bank_account_iban); + $data['bank_account_bic'] = trim($r->bank_account_bic); + $data['allow_contact'] = ($r->allow_contact) ? 1 : 0; + $data['allow_spin'] = ($r->allow_spin) ? 1 : 0; + + if ($mode == "add") { + $address = AddressModel::create($data); + } else { + $address->update($data); + } + + //var_dump($address);exit; + + $new_id = $address->save(); + if (!$new_id) { + $this->layout()->setFlash("Fehler beim Speichern", "error"); + $this->layout()->set("address", $address); + return $this->add(); + } + + // check for multiple primary fibu accounts, and remove from any other than this one + if ($address->fibu_primary_account && $address->fibu_account_number) { + foreach (AddressModel::search(["fibu_primary_account" => true, "fibu_account_number" => $address->fibu_account_number]) as $fibu_primary) { + if ($fibu_primary->id == $address->id) continue; + $fibu_primary->fibu_primary_account = 0; + $fibu_primary->save(); + } + } + + + // save address types + $new_types = $r->addresstypes; + if (is_array($new_types)) { + foreach ($address->types as $existing_type) { + //var_dump($existing_type); + //var_dump($new_types); + //echo $existing_type->type; + if (!in_array($existing_type->type, $new_types)) { + $existing_type->delete(); + } else { + // remove existing type from new_types array (dont need to create again) + $new_types = array_diff($new_types, [$existing_type->type]); + //unset($new_types[$existing_type]); + } + } + //exit; + foreach ($new_types as $type) { + $type_object = AddresstypeModel::create(['address_id' => $address->id, 'type' => $type]); + $type_object->save(); + $address->types[$type] = $type_object; + } + } + + // generate new supplier account number if is supplier and supplier num empty + //var_dump($mode, $address->fibu_supplier_number, $address->types);exit; + if (!$address->fibu_supplier_number && array_key_exists("supplier", $address->types)) { + $supplier_num = Address::getNextSupplierNumber(); + if (!$supplier_num) { + $this->layout()->setFlash("Lieferantennummer konnte nicht generiert werden."); + } else { + $this->log->debug("new supplier number: " . $supplier_num); + $address->fibu_supplier_number = $supplier_num; + $address->save(); + } + } + + $attribs = $r->attributes; + //var_dump($attribs);exit; + if (is_array($attribs) && count($attribs)) { + foreach ($attribs as $attrib => $value) { + $aa = AddressattributeModel::getFirst(["address_id" => $new_id, "name" => $attrib]); + + if (!$aa) { + $aa = AddressattributeModel::create(["address_id" => $new_id, "name" => $attrib]); + } + $aa->value = $value; + $aa->save(); + } + } + + + //$address->deleteLinks(); + + $existing_links = []; + foreach (AddressLinkModel::search(['origin_address_id', $new_id]) as $elink) { + $existing_links[$elink->address_id] = $elink; + } + + //var_dump($r->links);exit; + if (is_array($r->links) && count($r->links)) { + //var_dump($r->links);exit; + foreach ($r->links as $linknum => $link) { + if (!$link['type'] || !$link['address_id']) { + continue; + } + if (array_key_exists($link['address_id'], $existing_links)) { + continue; + } + $l = AddressLinkModel::create([ + 'origin_address_id' => $new_id, + 'type' => $link['type'], + 'address_id' => $link['address_id'] + ]); + $l->save(); + + } + } + + // run afterSave() again in case anything importand has changed + $address->afterSave(); + + $sq = ""; + $query = []; + if ($r->s) { + $query['s'] = $r->s; + } + if ($r->return != "index") { + $query['id'] = $new_id; + } + + $qs = http_build_query($query); + + $this->layout()->setFlash("Adresse erfolgreich gespeichert.", "success"); + if ($r->return == "index") { + $this->redirect("Address", "Index", $qs); + } + if ($r->f == "view") { + $this->redirect("Address", "View", $qs); + } + $this->redirect("Address", "Edit", $qs); } - // run afterSave() again in case anything importand has changed - $address->afterSave(); - - $sq = ""; - $query = []; - if($r->s) { - $query['s'] = $r->s; - } - if($r->return != "index") { - $query['id'] = $new_id; - } - - $qs = http_build_query($query); - - $this->layout()->setFlash("Adresse erfolgreich gespeichert.", "success"); - if($r->return == "index") { - $this->redirect("Address", "Index", $qs); - } - if($r->f == "view") { - $this->redirect("Address", "View", $qs); - } - $this->redirect("Address", "Edit", $qs); - } - - - protected function apiAction() { - if(!$this->me->is(["Admin","salespartner"])) { - $this->redirect("Dashboard"); - } - $do = $this->request->do; - $data = []; - - switch($do) { - case "getAddress": - $return = $this->getAddressApi(); - break; - case "findAddress": - $return = $this->findAddressApi(); - break; - case "validateIbanBic": - $return = $this->validateIbanBicApi(); - break; - default: - $return = false; - } - - if(!is_array($return) || !count($return)) { - $data = ["status" => "error"]; - $this->returnJson($data); - } - $data['status'] = "OK"; - $data['result'] = $return; - $this->returnJson($data); - } - - private function getAddressApi() { - $id = trim($this->request->id); - if(!is_numeric($id) || !$id) { - return false; - } - - $address = new Address($id); - if(!$address->id) { - return false; - } - - $a = $address->toArray(); - $a['name'] = $address->getCompanyOrName(); - - return ['address' => $a]; - } - - private function findAddressApi() { - $search = trim($this->request->q); - $autocomplete = $this->request->autocomplete; - if($autocomplete && $this->request->searchedID) { - $address = new Address($this->request->searchedID); - if($address->id) { - $result = [ - 'value' => $address->id, - 'text' => str_replace("'", "\\'", str_replace(["\n", "\r"], " ",$address->getCompanyOrName()))." (".$address->zip." ".$address->city.", ".$address->street.")".(($address->customer_number) ? " [".$address->customer_number."]" : "") - ]; + protected function apiAction() { + if (!$this->me->is(["Admin", "salespartner"])) { + $this->redirect("Dashboard"); + } + $do = $this->request->do; + $data = []; + + switch ($do) { + case "getAddress": + $return = $this->getAddressApi(); + break; + case "findAddress": + $return = $this->findAddressApi(); + break; + case "validateIbanBic": + $return = $this->validateIbanBicApi(); + break; + default: + $return = false; + } + + if (!is_array($return) || !count($return)) { + $data = ["status" => "error"]; + $this->returnJson($data); + } + $data['status'] = "OK"; + $data['result'] = $return; + $this->returnJson($data); + } + + private function getAddressApi() { + $id = trim($this->request->id); + if (!is_numeric($id) || !$id) { + return false; + } + + $address = new Address($id); + if (!$address->id) { + return false; + } + + $a = $address->toArray(); + $a['name'] = $address->getCompanyOrName(); + + return ['address' => $a]; + } + + private function findAddressApi() { + $search = trim($this->request->q); + $autocomplete = $this->request->autocomplete; + + if ($autocomplete && $this->request->searchedID) { + $address = new Address($this->request->searchedID); + if ($address->id) { + $result = [ + 'value' => $address->id, + 'text' => str_replace("'", "\\'", str_replace(["\n", + "\r"], " ", $address->getCompanyOrName())) . " (" . $address->zip . " " . $address->city . ", " . $address->street . ")" . (($address->customer_number) ? " [" . $address->customer_number . "]" : "") + ]; + $results[] = $result; + $this->returnJson($results); + die(); + } + } + + $po = 1; + $role = false; + // if searching for billingaddress, set role and parents_only to 0 + if ($this->request->role == "billingaddress") { + $role = "billing"; + $po = 0; + } + if ($this->request->role == "techcontact") { + $role = "techcontact"; + $po = 0; + } + + $this->log->debug(print_r($this->request->get(), true)); + + $addresses = []; + + if (is_numeric($search)) { + $cnumbers = AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "customer_number" => $search]); + if ($cnumbers) { + $addresses = array_merge($addresses, $cnumbers); + } + } + + + if (isset($_GET['fibu_primary_account'])) { + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, + "addresstype" => [$role], + "mergedName" => $search, + "fibu_primary_account" => true])); + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, + "addresstype" => [$role], + "company" => $search, + "fibu_primary_account" => true])); + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, + "addresstype" => [$role], + "firstname" => $search, + "fibu_primary_account" => true])); + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, + "addresstype" => [$role], + "lastname" => $search, + "fibu_primary_account" => true])); + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, + "addresstype" => [$role], + "street" => $search, + "fibu_primary_account" => true])); + + } else { + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "mergedName" => $search])); + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "company" => $search])); + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "firstname" => $search])); + $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "lastname" => $search])); + } + + if (!is_array($addresses) || !count($addresses)) { + return false; + } + + $all_addresses = []; + + // remove duplicates + foreach ($addresses as $address) { + if (!array_key_exists($address->id, $all_addresses)) { + $all_addresses[$address->id] = $address; + } + } + + $results = []; + + if (!$autocomplete) { + foreach ($all_addresses as $id => $address) { + $results[$id] = str_replace("'", "\\'", str_replace(["\n", + "\r"], " ", $address->getCompanyOrName())) . " (" . $address->zip . " " . $address->city . ", " . $address->street . ")" . (($address->customer_number) ? " [" . $address->customer_number . "]" : ""); + if (count($results) > 15) { + $results["more"] = "..."; + break; + } + } + + return ["addresses" => $results]; + } + + // return bootstrap-autocomplete format + foreach ($all_addresses as $id => $address) { + $result = ['value' => $id, + 'text' => str_replace("'", "\\'", str_replace(["\n", + "\r"], " ", $address->getCompanyOrName())) . " (" . $address->zip . " " . $address->city . ", " . $address->street . ")" . (($address->customer_number) ? " [" . $address->customer_number . "]" : "")]; $results[] = $result; - $this->returnJson($results); - die(); + if (count($results) > 15) { + $results[] = ['value' => 0, + 'text' => "  -->   Mehr Suchergebnisse vorhanden. Bitte Suchbegriff genauer definieren   <--"]; + break; + } } + + $this->returnJson($results); } - $po = 1; - $role = false; - // if searching for billingaddress, set role and parents_only to 0 - if($this->request->role == "billingaddress") { - $role = "billing"; - $po = 0; - } - if($this->request->role == "techcontact") { - $role = "techcontact"; - $po = 0; - } - - $this->log->debug(print_r($this->request->get(),true)); - - $addresses = []; - - if(is_numeric($search)) { - $cnumbers = AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "customer_number" => $search]); - if($cnumbers) { - $addresses = array_merge($addresses, $cnumbers); - } - } - + private function validateIbanBicApi() { + $iban = trim($this->request->iban); + $bic = trim($this->request->bic); - if (isset($_GET['fibu_primary_account'])) { - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "mergedName" => $search, "fibu_primary_account" => true])); - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "company" => $search, "fibu_primary_account" => true])); - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "firstname" => $search, "fibu_primary_account" => true])); - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "lastname" => $search, "fibu_primary_account" => true])); - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "street" => $search, "fibu_primary_account" => true])); - - } else { - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "mergedName" => $search])); - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "company" => $search])); - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "firstname" => $search])); - $addresses = array_merge($addresses, AddressModel::search(["parents_only" => $po, "addresstype" => [$role], "lastname" => $search])); - } - - if(!is_array($addresses) || !count($addresses)) { - return false; - } - - $all_addresses = []; - - // remove duplicates - foreach($addresses as $address) { - if(!array_key_exists($address->id, $all_addresses)) { - $all_addresses[$address->id] = $address; - } - } - - $results = []; - - if(!$autocomplete) { - foreach($all_addresses as $id => $address) { - $results[$id] = str_replace("'", "\\'", str_replace(["\n", "\r"], " ",$address->getCompanyOrName()))." (".$address->zip." ".$address->city.", ".$address->street.")".(($address->customer_number) ? " [".$address->customer_number."]" : ""); - if(count($results) > 15) { - $results["more"] = "..."; - break; + if (!$iban) { + return false; } - } - return ["addresses" => $results]; - } - - // return bootstrap-autocomplete format - foreach($all_addresses as $id => $address) { - $result = ['value' => $id, 'text' => str_replace("'", "\\'", str_replace(["\n", "\r"], " ",$address->getCompanyOrName()))." (".$address->zip." ".$address->city.", ".$address->street.")".(($address->customer_number) ? " [".$address->customer_number."]" : "")]; - $results[] = $result; - if(count($results) > 15) { - $results[] = ['value' => 0, 'text' => "  -->   Mehr Suchergebnisse vorhanden. Bitte Suchbegriff genauer definieren   <--"]; - break; - } + $result = IbanValidator::validate($iban, $bic); + if (is_array($result) && $result) { + return $result; + } + + return false; + } - $this->returnJson($results); - } - - private function validateIbanBicApi() { - $iban = trim($this->request->iban); - $bic = trim($this->request->bic); - - if(!$iban) { - return false; - } - - $result = IbanValidator::validate($iban, $bic); - if(is_array($result) && $result) { - return $result; - } - - return false; - - } - - public function createTicketAction() { + public function createTicketAction() { // die('{"derivedStartDate":null,"derivedDueDate":null,"spentTime":"PT0S","laborCosts":"0,00 EUR","materialCosts":"0,00 EUR","overallCosts":"0,00 EUR","_embedded":{"attachments":{"_type":"Collection","total":0,"count":0,"_embedded":{"elements":[]},"_links":{"self":{"href":"/api/v3/work_packages/6664/attachments"}}},"relations":{"_type":"Collection","total":0,"count":0,"_embedded":{"elements":[]},"_links":{"self":{"href":"/api/v3/work_packages/6664/relations"}}},"type":{"_type":"Type","id":12,"name":"Störung","color":"#FF3300","position":4,"isDefault":true,"isMilestone":false,"createdAt":"2023-02-22T20:19:25Z","updatedAt":"2023-02-23T11:59:16Z","_links":{"self":{"href":"/api/v3/types/12","title":"Störung"}}},"priority":{"_type":"Priority","id":8,"name":"Residential","position":2,"color":"#74C0FC","isDefault":true,"isActive":true,"_links":{"self":{"href":"/api/v3/priorities/8","title":"Residential"}}},"project":{"_type":"Project","id":10,"identifier":"storungen-and-support","name":"Störungen & Support","active":true,"public":false,"description":{"format":"markdown","raw":"","html":""},"createdAt":"2023-02-22T19:45:24Z","updatedAt":"2024-01-19T19:56:27Z","statusExplanation":{"format":"markdown","raw":"","html":""},"_links":{"self":{"href":"/api/v3/projects/10","title":"Störungen & Support"},"createWorkPackage":{"href":"/api/v3/projects/10/work_packages/form","method":"post"},"createWorkPackageImmediately":{"href":"/api/v3/projects/10/work_packages","method":"post"},"workPackages":{"href":"/api/v3/projects/10/work_packages"},"categories":{"href":"/api/v3/projects/10/categories"},"versions":{"href":"/api/v3/projects/10/versions"},"memberships":{"href":"/api/v3/memberships?filters=%5B%7B%22project%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%2210%22%5D%7D%7D%5D"},"types":{"href":"/api/v3/projects/10/types"},"schema":{"href":"/api/v3/projects/schema"},"status":{"href":null},"ancestors":[{"href":"/api/v3/projects/5","title":"XINON"}],"parent":{"href":"/api/v3/projects/5","title":"XINON"}}},"status":{"_type":"Status","id":1,"name":"Neu","isClosed":false,"color":"#1098AD","isDefault":true,"isReadonly":false,"defaultDoneRatio":null,"position":1,"_links":{"self":{"href":"/api/v3/statuses/1","title":"Neu"}}},"author":{"_type":"User","id":30,"name":"Luca Haid","createdAt":"2024-02-05T11:35:52Z","updatedAt":"2024-10-21T06:32:44Z","login":"luca.haid@xinon.eu","firstName":"Luca","lastName":"Haid","email":"luca.haid@xinon.eu","avatar":"https://secure.gravatar.com/avatar/37a35a87af3c506c1ce722826834ce38?default=404&secure=true","status":"active","identityUrl":null,"language":"de","_links":{"self":{"href":"/api/v3/users/30","title":"Luca Haid"},"memberships":{"href":"/api/v3/memberships?filters=%5B%7B%22principal%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%2230%22%5D%7D%7D%5D","title":"Mitglieder"},"showUser":{"href":"/users/30","type":"text/html"}}},"customActions":[],"costsByType":{"_type":"Collection","total":0,"count":0,"_embedded":{"elements":[]},"_links":{"self":{"href":"/api/v3/work_packages/6664/summarized_costs_by_type"}}}},"_type":"WorkPackage","id":6664,"lockVersion":1,"subject":"tes","description":{"format":"markdown","raw":"ttest","html":"

    ttest

    "},"scheduleManually":false,"startDate":null,"dueDate":null,"estimatedTime":null,"derivedEstimatedTime":null,"duration":null,"ignoreNonWorkingDays":false,"percentageDone":0,"createdAt":"2024-10-31T12:48:27Z","updatedAt":"2024-10-31T12:48:27Z","readonly":false,"remainingTime":null,"customField1":null,"customField2":"4 Quality GmbH & Co KG","customField3":"Grazerstraße 87, 8111 Judendorf-Straßengel","customField4":"test","customField5":"office@4quality.at","customField6":"2215","customField7":"ZE4889","_links":{"attachments":{"href":"/api/v3/work_packages/6664/attachments"},"addAttachment":{"href":"/api/v3/work_packages/6664/attachments","method":"post"},"self":{"href":"/api/v3/work_packages/6664","title":"tes"},"update":{"href":"/api/v3/work_packages/6664/form","method":"post"},"schema":{"href":"/api/v3/work_packages/schemas/10-12"},"updateImmediately":{"href":"/api/v3/work_packages/6664","method":"patch"},"logTime":{"href":"/api/v3/time_entries","title":"Log time on tes"},"move":{"href":"/work_packages/6664/move/new","type":"text/html","title":"Move tes"},"copy":{"href":"/work_packages/6664/copy","title":"Copy tes"},"pdf":{"href":"/work_packages/6664.pdf","type":"application/pdf","title":"Export as PDF"},"atom":{"href":"/work_packages/6664.atom","type":"application/rss+xml","title":"Atom feed"},"availableRelationCandidates":{"href":"/api/v3/work_packages/6664/available_relation_candidates","title":"Potential work packages to relate to"},"activities":{"href":"/api/v3/work_packages/6664/activities"},"availableWatchers":{"href":"/api/v3/work_packages/6664/available_watchers"},"relations":{"href":"/api/v3/work_packages/6664/relations"},"revisions":{"href":"/api/v3/work_packages/6664/revisions"},"watchers":{"href":"/api/v3/work_packages/6664/watchers"},"addWatcher":{"href":"/api/v3/work_packages/6664/watchers","method":"post","payload":{"user":{"href":"/api/v3/users/{user_id}"}},"templated":true},"removeWatcher":{"href":"/api/v3/work_packages/6664/watchers/{user_id}","method":"delete","templated":true},"addRelation":{"href":"/api/v3/work_packages/6664/relations","method":"post","title":"Add relation"},"addChild":{"href":"/api/v3/projects/storungen-and-support/work_packages","method":"post","title":"Add child of tes"},"changeParent":{"href":"/api/v3/work_packages/6664","method":"patch","title":"Change parent of tes"},"addComment":{"href":"/api/v3/work_packages/6664/activities","method":"post","title":"Add comment"},"previewMarkup":{"href":"/api/v3/render/markdown?context=/api/v3/work_packages/6664","method":"post"},"timeEntries":{"href":"/api/v3/time_entries?filters=%5B%7B%22work_package_id%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%226664%22%5D%7D%7D%5D","title":"Time entries"},"category":{"href":null},"type":{"href":"/api/v3/types/12","title":"Störung"},"priority":{"href":"/api/v3/priorities/8","title":"Residential"},"project":{"href":"/api/v3/projects/10","title":"Störungen & Support"},"status":{"href":"/api/v3/statuses/1","title":"Neu"},"author":{"href":"/api/v3/users/30","title":"Luca Haid"},"responsible":{"href":null},"assignee":{"href":null},"version":{"href":null},"logCosts":{"href":"/work_packages/6664/cost_entries/new","type":"text/html","title":"Log costs on tes"},"showCosts":{"href":"/projects/10/cost_reports?fields%5B%5D=WorkPackageId&operators%5BWorkPackageId%5D=%3D&set_filter=1&values%5BWorkPackageId%5D=6664","type":"text/html","title":"Show cost entries"},"costsByType":{"href":"/api/v3/work_packages/6664/summarized_costs_by_type"},"github_pull_requests":{"href":"/api/v3/work_packages/6664/github_pull_requests","title":"GitHub pull requests"},"unwatch":{"href":"/api/v3/work_packages/6664/watchers/30","method":"delete"},"ancestors":[],"parent":{"href":null,"title":null},"customActions":[]}}'); - // subject: test - //description: test - //customer_name: 4 Quality GmbH & Co KG - //customer_number: 2215 - //customer_address: Grazerstraße 87, 8111 Judendorf-Straßengel - //customer_phone_number: 0664 - //customer_email: office@4quality.at - //customer_service_pin: ZE4889 + // subject: test + //description: test + //customer_name: 4 Quality GmbH & Co KG + //customer_number: 2215 + //customer_address: Grazerstraße 87, 8111 Judendorf-Straßengel + //customer_phone_number: 0664 + //customer_email: office@4quality.at + //customer_service_pin: ZE4889 - $subject = $this->request->subject; + $subject = $this->request->subject; $description = $this->request->description; $customer_name = $this->request->customer_name; $customer_number = $this->request->customer_number; @@ -661,12 +680,29 @@ class AddressController extends mfBaseController { $customer_phone_number = $this->request->customer_phone_number; $customer_email = $this->request->customer_email; $customer_service_pin = $this->request->customer_service_pin; - $user_api_key = (string)$this->me->getFlag('project_api_key'); + $user_api_key = (string) $this->me->getFlag('project_api_key'); $xinon_project = new XinonProject(); $response = $xinon_project->createNewFaultTicket($subject, $description, $customer_name, $customer_number, $customer_address, $customer_phone_number, $customer_email, $customer_service_pin, $user_api_key); die($response); - } + } + + protected function ticketsAction() { + $address_id = $this->request->address_id; + + $address = new Address($address_id); + if (!$address->id) { + $this->layout()->setFlash("Addresse nicht gefunden", "error"); + $this->redirect("Address"); + } + + $xinon_project = new XinonProject(); + $tickets = $xinon_project->searchSupportTickets('', 0, ['pageSize' => 100, + 'filters' => json_encode([['customField6' => ['operator' => '=', 'values' => [$address->customer_number]]]])]); + + Helper::renderVue($this,"AddressTickets", + "Tickets von Kunden: " . $address->getCompanyOrName() . '(' . $address->customer_number . ')', ["TICKETS" => $tickets]); + } } diff --git a/application/Calendar/CalendarController.php b/application/Calendar/CalendarController.php index fae309a24..f15cb4f2c 100644 --- a/application/Calendar/CalendarController.php +++ b/application/Calendar/CalendarController.php @@ -70,10 +70,27 @@ class CalendarController extends mfBaseController $email->send(); } else if ($r->customer_info_type == 2) { $sms = new SmsNotification(); - $body = "Xinon Terminbestätigung:" . PHP_EOL . $r->customer_info_text; + $customerText = trim($r->customer_info_text); + $body = "Xinon Terminbestätigung:" . PHP_EOL . $customerText; $sms->setBody($body); - $sms->setRecipient($r->customer_info_type_text); - $sms->send(); + $customerNumber = trim($r->customer_info_type_text); + $customerNumber = str_replace(" ", "", $customerNumber); + $customerNumber = str_replace("(", "", $customerNumber); + $customerNumber = str_replace(")", "", $customerNumber); + $customerNumber = str_replace("-", "", $customerNumber); + $customerNumber = str_replace("/", "", $customerNumber); + $customerNumber = str_replace(".", "", $customerNumber); + $customerNumber = str_replace(",", "", $customerNumber); + $customerNumber = str_replace(";", "", $customerNumber); + $customerNumber = str_replace(":", "", $customerNumber); + + if (preg_match('/^0/', $customerNumber)) { + $customerNumber = "+43" . substr($customerNumber, 1); + } + $sms->setRecipient($customerNumber); + if (!empty($customerNumber) && !empty($customerText)) { + $sms->send(); + } } } die(); @@ -104,10 +121,26 @@ class CalendarController extends mfBaseController $email->send(); } else if ($r->customer_info_type == 2) { $sms = new SmsNotification(); - $body = "Xinon Terminbestätigung:" . PHP_EOL . $r->customer_info_text; + $customerText = trim($r->customer_info_text); + $body = "Xinon Terminbestätigung:" . PHP_EOL . $customerText; $sms->setBody($body); - $sms->setRecipient($r->customer_info_type_text); - $sms->send(); + $customerNumber = trim($r->customer_info_type_text); + $customerNumber = str_replace(" ", "", $customerNumber); + $customerNumber = str_replace("(", "", $customerNumber); + $customerNumber = str_replace(")", "", $customerNumber); + $customerNumber = str_replace("-", "", $customerNumber); + $customerNumber = str_replace("/", "", $customerNumber); + $customerNumber = str_replace(".", "", $customerNumber); + $customerNumber = str_replace(",", "", $customerNumber); + $customerNumber = str_replace(";", "", $customerNumber); + $customerNumber = str_replace(":", "", $customerNumber); + if (preg_match('/^0/', $customerNumber)) { + $customerNumber = "+43" . substr($customerNumber, 1); + } + $sms->setRecipient($customerNumber); + if (!empty($customerNumber) && !empty($customerText)) { + $sms->send(); + } } } die(); @@ -327,17 +360,18 @@ class CalendarController extends mfBaseController echo trim($json); die(); } + private function getTicket($r) { $project = new XinonProject(); - $data=$project->searchSupportTickets($r->term); + $data = $project->searchSupportTickets($r->term); foreach ($data as $key => $value) { $rows[] = array( 'id' => $value['id'], - 'text' => 'Ticket: '.$value['id']." ".$value['subject'], + 'text' => 'Ticket: ' . $value['id'] . " " . $value['subject'], 'subject' => $value['subject'], 'mail' => $value['customField5'], 'mobilenumber' => $value['customField4'], diff --git a/application/Calendar/CalendarModel.php b/application/Calendar/CalendarModel.php index 5ca1ca2ff..f88dd22db 100644 --- a/application/Calendar/CalendarModel.php +++ b/application/Calendar/CalendarModel.php @@ -47,6 +47,8 @@ class CalendarModel 3 => 'Grüne Kategorie', //ESTMK IBN 4 => 'Lila Kategorie', //Snopp IBN 5 => 'Rote Kategorie', //Störung + 98 => 'Gru00fcne Kategorie', //ESTMK IBN + 99 => 'Gr\u00fcne Kategorie', //ESTMK IBN ); public static $specialCalendarColors = array(997 => '#bd0000', 998 => '#8000A3', 999 => '#08769b'); @@ -694,7 +696,7 @@ WHERE `TimerecordingCategory`.`hourday`!='1' AND `TimerecordingCategory`.`hourda if (($r->customer_info_type_text)) { $customer_info_type_text = $r->customer_info_type_text; } - if ($r->customer_info_reminder_check) { + if ($r->customer_info_reminder_check || $r->customer_info_reminder_check == 0) { $updateArray['customer_info_reminder'] = $r->customer_info_reminder_check; } $customerJson = array('customer_info_type' => $customer_info_type, 'customer_info_text' => $customer_info_text, 'customer_info_type_text' => $customer_info_type_text); diff --git a/application/ConstructionConsent/ConstructionConsent.php b/application/ConstructionConsent/ConstructionConsent.php index 13678782f..ec54bedb7 100644 --- a/application/ConstructionConsent/ConstructionConsent.php +++ b/application/ConstructionConsent/ConstructionConsent.php @@ -353,6 +353,7 @@ class ConstructionConsent extends mfBaseModel { $where = self::getSqlFilter($filter); $sql = "SELECT COUNT(*) as cnt FROM ConstructionConsent + LEFT JOIN ".ADDRESSDB_DBNAME.".view_hausnummer ON (ConstructionConsent.adb_hausnummer_id = view_hausnummer.hausnummer_id) WHERE $where"; //mfLoghandler::singleton()->debug($sql); @@ -377,6 +378,7 @@ class ConstructionConsent extends mfBaseModel { $where = self::getSqlFilter($filter); $sql = "SELECT * FROM ConstructionConsent + LEFT JOIN ".ADDRESSDB_DBNAME.".view_hausnummer ON (ConstructionConsent.adb_hausnummer_id = view_hausnummer.hausnummer_id) WHERE $where ORDER BY $order"; @@ -494,6 +496,13 @@ class ConstructionConsent extends mfBaseModel { } } + if(array_key_exists("network", $filter)) { + $network = FronkDB::singleton()->escape($filter["network"]); + if($network) { + $where .= " AND view_hausnummer.netzgebiet_id=$network"; + } + } + if(array_key_exists("add-where", $filter)) { diff --git a/application/ConstructionConsent/ConstructionConsentController.php b/application/ConstructionConsent/ConstructionConsentController.php index fd39c11e7..7ed55d299 100644 --- a/application/ConstructionConsent/ConstructionConsentController.php +++ b/application/ConstructionConsent/ConstructionConsentController.php @@ -10,9 +10,7 @@ class ConstructionConsentController extends mfBaseController { $this->me = $me; $this->layout()->set("me", $me); - if (!$me->is(["Admin"])) { - $this->redirect("Dashboard"); - } + if (!($me->is(["Admin","netowner","salespartner"]) && in_array($me->address_id, [1,209,5908]))) $this->redirect("Dashboard"); } protected function indexAction() : void { diff --git a/application/ConstructionConsentContact/ConstructionConsentContactController.php b/application/ConstructionConsentContact/ConstructionConsentContactController.php index 84d215b9d..afaf61e7d 100644 --- a/application/ConstructionConsentContact/ConstructionConsentContactController.php +++ b/application/ConstructionConsentContact/ConstructionConsentContactController.php @@ -11,9 +11,7 @@ class ConstructionConsentContactController extends mfBaseController $this->me = $me; $this->layout()->set("me", $me); - if (!$me->is(["Admin"])) { - $this->redirect("Dashboard"); - } + if (!($me->is(["Admin","netowner","salespartner"]) && in_array($me->address_id, [1,209,5908]))) $this->redirect("Dashboard"); } protected function saveAction() diff --git a/application/ConstructionConsentJournal/ConstructionConsentJournalController.php b/application/ConstructionConsentJournal/ConstructionConsentJournalController.php index f7203f25f..98cab83af 100644 --- a/application/ConstructionConsentJournal/ConstructionConsentJournalController.php +++ b/application/ConstructionConsentJournal/ConstructionConsentJournalController.php @@ -9,9 +9,7 @@ class ConstructionConsentJournalController extends mfBaseController { $this->me = $me; $this->layout()->set("me",$me); - if(!$me->is(["Admin"])) { - $this->redirect("Dashboard"); - } + if (!($me->is(["Admin","netowner","salespartner"]) && in_array($me->address_id, [1,209,5908]))) $this->redirect("Dashboard"); } protected function saveAction() { diff --git a/application/ConstructionConsentOwner/ConstructionConsentOwnerController.php b/application/ConstructionConsentOwner/ConstructionConsentOwnerController.php index 08c08f7fb..c9c1eb425 100644 --- a/application/ConstructionConsentOwner/ConstructionConsentOwnerController.php +++ b/application/ConstructionConsentOwner/ConstructionConsentOwnerController.php @@ -11,9 +11,7 @@ class ConstructionConsentOwnerController extends mfBaseController $this->me = $me; $this->layout()->set("me", $me); - if (!$me->is(["Admin"])) { - $this->redirect("Dashboard"); - } + if (!($me->is(["Admin","netowner","salespartner"]) && in_array($me->address_id, [1,209,5908]))) $this->redirect("Dashboard"); } protected function uploadDocumentAction() { diff --git a/application/ConstructionConsentProject/ConstructionConsentProjectController.php b/application/ConstructionConsentProject/ConstructionConsentProjectController.php index 744cfc136..fa6b13769 100644 --- a/application/ConstructionConsentProject/ConstructionConsentProjectController.php +++ b/application/ConstructionConsentProject/ConstructionConsentProjectController.php @@ -10,9 +10,7 @@ class ConstructionConsentProjectController extends mfBaseController { $this->me = $me; $this->layout()->set("me", $me); - if (!$me->is(["Admin"])) { - $this->redirect("Dashboard"); - } + if (!($me->is(["Admin","netowner","salespartner"]) && in_array($me->address_id, [1,209,5908]))) $this->redirect("Dashboard"); } protected function indexAction() : void { diff --git a/application/DashboardNew/DashboardNewController.php b/application/DashboardNew/DashboardNewController.php index c7fc25f0b..c79e9ef35 100644 --- a/application/DashboardNew/DashboardNewController.php +++ b/application/DashboardNew/DashboardNewController.php @@ -10,6 +10,7 @@ class DashboardNewController extends mfBaseController { $me->loadMe(); $this->layout()->set("me", $me); $this->me = $me; + if ($this->me->address_id === '5908') $this->me->address_id = '209'; } protected function indexAction() { @@ -73,7 +74,6 @@ class DashboardNewController extends mfBaseController { $netowner_ids = isset($post['netOwners']) ? [$post['netOwners']] : []; $campaign_ids = isset($post['campaigns']) ? [$post['campaigns']] : []; $campaigns = []; - $all_campaigns = $this->me->is("Admin") ? PreordercampaignModel::getAll() : PreordercampaignModel::search(["owner_id" => $this->me->address_id]); if (!empty($netowner_ids)) { @@ -140,10 +140,16 @@ class DashboardNewController extends mfBaseController { if (!empty($netowner_ids)) { $all_campaigns = $this->me->is("Admin") ? PreordercampaignModel::getAll() : PreordercampaignModel::search(["owner_id" => $this->me->address_id]); + if ($all_campaigns[0] === NULL) { + http_response_code(500); + self::returnJson(["status" => 500, "message" => "Keine Kampagnen gefunden"]); + } + $campaign_ids = empty($campaign_ids) ? array_map(fn($campaign) => $campaign->id, $all_campaigns) : $campaign_ids; + $campaign_ids = array_filter($campaign_ids, function ($campaign_id) use ($netowner_ids) { $campaign = new Preordercampaign($campaign_id); return in_array($campaign->network->owner_id, $netowner_ids); @@ -152,6 +158,12 @@ class DashboardNewController extends mfBaseController { if (empty($campaign_ids) && !$this->me->is("Admin")) { $owner_campaigns = PreordercampaignModel::search(["owner_id" => $this->me->address_id]); + + if (empty($owner_campaigns)) { + http_response_code(500); + self::returnJson(["status" => 500, "message" => "Keine Kampagnen gefunden"]); + } + $campaign_ids = array_map(fn($campaign) => $campaign->id, $owner_campaigns); } diff --git a/application/Device/DeviceController.php b/application/Device/DeviceController.php index 9ec484eb2..6cd20e58a 100644 --- a/application/Device/DeviceController.php +++ b/application/Device/DeviceController.php @@ -10,9 +10,20 @@ class DeviceController extends mfBaseController $this->me = $me; $this->layout()->set("me", $me); - if (!$me->is(["Admin"])) { + if (!$me->is(["Admin", "netowner", "lineplanner", "pipeplanner", "pipeworker", "lineworker"])) { $this->redirect("Dashboard"); } + + if ($this->me->is(["Admin"])) { + $this->allowedPops = null; + } else { + $networkIds = array_column($this->me->getProperty('my_networks'), 'id'); + $pops=PopNetworkModel::search(['Networks' => $networkIds]); + foreach ($pops as $pop) { + $popIds[] = $pop->pop_id; + } + $this->allowedPops = $popIds; + } } protected function indexAction() @@ -75,6 +86,13 @@ class DeviceController extends mfBaseController $this->redirect("Device"); } + if (!$this->me->is(["Admin"])) { + if (!in_array($device->pop_id, $this->allowedPops)) { + $this->layout()->setFlash("Gerät nicht gefunden", "error"); + $this->redirect("Device"); + } + } + $this->layout()->setTemplate("Device/Detail"); $devicesconfig = DeviceModel::getconifg($id); $devices = DeviceModel::getOne($id); @@ -99,7 +117,6 @@ class DeviceController extends mfBaseController $this->layout()->set("devicetypes", DevicetypeModel::getAll()); $this->layout()->set("pops", PopModel::getAll()); $this->layout()->set("devices", DeviceModel::getAll()); - } protected function editAction() @@ -123,6 +140,11 @@ class DeviceController extends mfBaseController protected function saveAction() { + if (!$this->me->is(["Admin"])) { + $this->layout()->setFlash("Keine Berechtigung", "error"); + $this->redirect("Device"); + } + $r = $this->request; $id = $r->id; //var_dump($r->get());exit; @@ -395,7 +417,8 @@ class DeviceController extends mfBaseController private function getDevices() { - $devices = DeviceModel::getAll(); + if ($this->allowedPops === null) return []; + $devices = DeviceModel::search(['popIds' => $this->allowedPops]); foreach ($devices as $device) { $locationText = ""; @@ -415,7 +438,7 @@ class DeviceController extends mfBaseController if ($device->last_config_backup) { if (time() - $device->last_config_backup <= 172800) { $backup = 'ok'; - if ($device->autobackup==1) { + if ($device->autobackup == 1) { $backup = 'auto'; } } else { @@ -443,5 +466,4 @@ class DeviceController extends mfBaseController return $data ?? []; } - -} \ No newline at end of file +} diff --git a/application/Device/DeviceModel.php b/application/Device/DeviceModel.php index c0f65f472..7ed65c35f 100644 --- a/application/Device/DeviceModel.php +++ b/application/Device/DeviceModel.php @@ -136,6 +136,13 @@ class DeviceModel } } + if (array_key_exists("popIds", $filter)) { + $popids = $filter['popIds']; + if (is_array($popids)) { + $where .= " AND pop_id IN (" . implode(",", $popids) . ")"; + } + } + //var_dump($filter, $where);exit; return $where; } diff --git a/application/PopNetwork/PopNetworkModel.php b/application/PopNetwork/PopNetworkModel.php index 63fe70a2b..0b624f765 100644 --- a/application/PopNetwork/PopNetworkModel.php +++ b/application/PopNetwork/PopNetworkModel.php @@ -146,6 +146,11 @@ class PopNetworkModel $where .= " AND network_id=$networkid"; } } + if (array_key_exists("Networks", $filter)) { + $Networks = $filter['Networks']; + $where .= " AND network_id IN (" . implode(",", $Networks) . ")"; + + } //var_dump($filter, $where);exit; return $where; diff --git a/application/Timerecording/TimerecordingController.php b/application/Timerecording/TimerecordingController.php index e28d7a9ac..db4bcde7e 100644 --- a/application/Timerecording/TimerecordingController.php +++ b/application/Timerecording/TimerecordingController.php @@ -528,8 +528,36 @@ class TimerecordingController extends mfBaseController $workingHours[$workinghour->day] = $workingHours[$workinghour->day] + $whend - $whstart; } } + $workinghourshistory = TimerecordingEmployeeWorkingHourHistoryModel::search(['user_id' => $userid]); + if ($workinghourshistory) { + $workingHoursHistory[2147483500]=$workingHours; + foreach ($workinghourshistory as $workinghourhistory) { + $whenddate = $workinghourhistory->enddate; + $workinghourhistoryhours = json_decode($workinghourhistory->workinghours, true); + foreach ($workinghourhistoryhours as $workinghourhistoryhour) { + $whstart = strtotime(date('Y-m-d', time()) . " " . $workinghourhistoryhour['start'] . ":00"); + $whend = strtotime(date('Y-m-d', time()) . " " . $workinghourhistoryhour['end'] . ":00"); + if (!$workingHoursHistory[$whenddate][$workinghourhistoryhour['day']]) { + $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] = $whend - $whstart; + } else { + $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] = $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] + $whend - $whstart; + } + } + } + } //check if holiday is already in the list foreach ($holidayDays as $key => $holidayDay) { + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + $timestamp = strtotime($key); + if ($whtimestamp >= $timestamp) + { + $workingHours = $whdata; + } + } + } if (($realholiDay[$key])) { } else if ($workingHours[date('w', strtotime($key))]) { @@ -605,6 +633,7 @@ class TimerecordingController extends mfBaseController if ($plushours_timestamp > 0) { $return = $this->getTimerecordingsApi(5, null, null, null, $plushours_timestamp, $endtime, $userid); +// echo $return['is'] ." ". $return['must'].PHP_EOL; $diffTime = $return['is'] - $return['must']; $plushours_now = $plushours_now + $diffTime; } else { @@ -681,6 +710,25 @@ class TimerecordingController extends mfBaseController $workingHours[$workinghour->day] = $workingHours[$workinghour->day] + $whend - $whstart; } } + + $workinghourshistory = TimerecordingEmployeeWorkingHourHistoryModel::search(['user_id' => $userid]); + if ($workinghourshistory) { + $workingHoursHistory[2147483500]=$workingHours; + foreach ($workinghourshistory as $workinghourhistory) { + $whenddate = $workinghourhistory->enddate; + $workinghourhistoryhours = json_decode($workinghourhistory->workinghours, true); + foreach ($workinghourhistoryhours as $workinghourhistoryhour) { + $whstart = strtotime(date('Y-m-d', time()) . " " . $workinghourhistoryhour['start'] . ":00"); + $whend = strtotime(date('Y-m-d', time()) . " " . $workinghourhistoryhour['end'] . ":00"); + if (!$workingHoursHistory[$whenddate][$workinghourhistoryhour['day']]) { + $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] = $whend - $whstart; + } else { + $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] = $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] + $whend - $whstart; + } + } + } + } + foreach ($holidays as $holiday) { $holiDay[date('Y-m-d', $holiday->timestamp)] = $holiday->description; } @@ -704,6 +752,18 @@ class TimerecordingController extends mfBaseController } $dDate = date('Y-m-d', $timestamp + $WintertimeCompensation); $dDay = date('w', $timestamp + $WintertimeCompensation); + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $timestamp) + { + unset($workingHours); + $workingHours = $whdata; + } + } + } + if (!$holiDay[$dDate] && $dDate >= date('Y-m-d', $startdate) && $dDate <= date('Y-m-d', $enddate)) { $mustSeconds = $mustSeconds + $workingHours[$dDay]; } elseif ($holiDay[$dDate]) { @@ -727,6 +787,18 @@ class TimerecordingController extends mfBaseController } $dDate = date('Y-m-d', $timestamp + $WintertimeCompensation); $dDay = date('w', $timestamp + $WintertimeCompensation); + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $timestamp) + { + unset($workingHours); + $workingHours = $whdata; + } + } + } + if (!$holiDay[$dDate] && $dDate >= date('Y-m-d', $startdate) && $dDate <= date('Y-m-d', $enddate)) { $mustSeconds = $mustSeconds + $workingHours[$dDay]; } elseif ($holiDay[$dDate]) { @@ -749,6 +821,18 @@ class TimerecordingController extends mfBaseController } $dDate = date('Y-m-d', $timestamp + $WintertimeCompensation); $dDay = date('w', $timestamp + $WintertimeCompensation); + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $timestamp) + { + unset($workingHours); + $workingHours = $whdata; + } + } + } + if (!$holiDay[$dDate] && $dDate >= date('Y-m-d', $startdate) && $dDate <= date('Y-m-d', $enddate)) { $mustSeconds = $mustSeconds + $workingHours[$dDay]; } elseif ($holiDay[$dDate]) { @@ -770,9 +854,23 @@ class TimerecordingController extends mfBaseController if (date('I', $timestamp) == 0) { $WintertimeCompensation = 3600; } + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $timestamp) + { + unset($workingHours); + $workingHours = $whdata; +// echo date('Y-m-d 23:59:59', $whkey).PHP_EOL; + } + } + } + $dDate = date('Y-m-d', $timestamp + $WintertimeCompensation); $dDay = date('w', $timestamp + $WintertimeCompensation); if (!$holiDay[$dDate]) { + $mustSeconds = $mustSeconds + $workingHours[$dDay]; } @@ -828,6 +926,17 @@ class TimerecordingController extends mfBaseController $savecounter = 0; $sumdays = 0; for ($i = $starttimecalc; $i <= $endtimecalc; $i = $i + 86400) { + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $i) + { + unset($workingHours); + $workingHours = $whdata; + } + } + } $holidaycounter = $workingHours[date("w", $i)]; $daycheck = date("Y-m-d", $i); if (!$holiDay[$daycheck]) { @@ -877,6 +986,17 @@ class TimerecordingController extends mfBaseController $savecounter = 0; // echo $starttimecalc."
    "; for ($i = $starttimecalc; $i <= $endtimecalc; $i = $i + 86400) { + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $i) + { + unset($workingHours); + $workingHours = $whdata; + } + } + } $holidaycounter = $workingHours[$timerecording->user_id][date("w", $i)]; $daycheck = date("Y-m-d", $i); if (!$holiDay[$daycheck]) { diff --git a/application/TimerecordingEmployee/TimerecordingEmployeeController.php b/application/TimerecordingEmployee/TimerecordingEmployeeController.php index 51836ac9f..07c679399 100644 --- a/application/TimerecordingEmployee/TimerecordingEmployeeController.php +++ b/application/TimerecordingEmployee/TimerecordingEmployeeController.php @@ -16,6 +16,47 @@ class TimerecordingEmployeeController extends mfBaseController } } + protected function apiAction() + { + $do = $this->request->do; + $r = $this->request; + + $data = []; + + switch ($do) { + case "saveWorkingHours": + $userid = $r->userid; + $enddate = $r->enddate; + $workinghours = $r->workingHours; + $data = []; + $data['user_id'] = $userid; + $data['enddate'] = strtotime($enddate) + 10800; + $data['workinghours'] = json_encode($workinghours); + $timerecordingemployeesworkinghoursHistory = TimerecordingEmployeeWorkingHourHistoryModel::create($data); + $timerecordingemployeesworkinghoursHistory->save(); + break; + case "deleteWorkingHours": + $id = $r->id; + $timerecordingemployeesworkinghoursHistory = new TimerecordingEmployeeWorkingHourHistory($id); + if (!$timerecordingemployeesworkinghoursHistory->id || $timerecordingemployeesworkinghoursHistory->id != $id) { + $data = ["status" => "error"]; + $this->returnJson($data); + } + $timerecordingemployeesworkinghoursHistory->delete(); + break; + default: + $data = ["status" => "error"]; + $this->returnJson($data); + } + if (!is_array($return) || !count($return)) { + $data = ["status" => "error"]; + $this->returnJson($data); + } + $data['status'] = "OK"; + $data['result'] = $return; + $this->returnJson($data); + } + protected function indexAction() { @@ -56,6 +97,8 @@ class TimerecordingEmployeeController extends mfBaseController $this->layout()->set("timerecordingemployees", $timerecordingemployees); } + $timerecordingworkinghourshistory = $this->generateWorkingHoursHistory($userid); + $this->layout()->set("timerecordingworkinghourshistory", $timerecordingworkinghourshistory); $timerecordinguser = UserModel::search(['worker_id' => $userid]); $this->layout()->set("timerecordinguser", $timerecordinguser); return $this->addAction(); @@ -202,6 +245,8 @@ class TimerecordingEmployeeController extends mfBaseController } else if ($mode = "add") { $this->layout()->setFlash("Personaladministration erfolgreich angelegt", "success"); } + $employee = new TimerecordingController(); + $employee->updatePlushours($r->user_id); $this->redirect("TimerecordingEmployee"); } @@ -219,4 +264,28 @@ class TimerecordingEmployeeController extends mfBaseController $this->redirect("TimerecordingEmployee"); } + protected function generateWorkingHoursHistory($userid) + { + $days_short = TimerecordingEmployeeWorkingHourModel::$days_short; + $TimerecordingEmployeeWorkingHourHistory = TimerecordingEmployeeWorkingHourHistoryModel::search(['user_id' => $userid]); + foreach ($TimerecordingEmployeeWorkingHourHistory as $key => $value) { + $workinghours = json_decode($value->workinghours, true); + $datetimetext = ""; + $secondcounter = ""; + foreach ($workinghours as $key2 => $data) { + $secondcounter = $secondcounter + strtotime(date("Y-m-d " . $data['end'] . ":00")) - strtotime(date("Y-m-d " . $data['start'] . ":00")); + $datetimetext .= $days_short[$data['day']] . " " . $data['start'] . " - " . $data['end'] . "
    "; + $datetimetext = TimerecordingEmployeeWorkingHourModel::cleardays($datetimetext); + } + + + $result[$value->enddate]['workinghours'] = $datetimetext; + $result[$value->enddate]['workingtime'] = $secondcounter; + $result[$value->enddate]['id'] = $value->id; + } + $employee = new TimerecordingController(); + $employee->updatePlushours($userid); + return $result; + } + } diff --git a/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistory.php b/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistory.php new file mode 100644 index 000000000..36d7ea7ff --- /dev/null +++ b/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistory.php @@ -0,0 +1,60 @@ +$name == null) { + + if (!$this->id) { + return null; + } + + if ($name == "creator") { + $this->creator = mfValuecache::singleton()->get("Worker-id-" . $this->create_by); + if ($this->creator === null) { + $this->creator = new User($this->create_by); + if ($this->creator->id) { + mfValuecache::singleton()->set("Worker-id-" . $this->create_by, $this->creator); + } + } + return $this->creator; + } + + if ($name == "editor") { + $this->editor = mfValuecache::singleton()->get("Worker-id-" . $this->edit_by); + if ($this->editor === null) { + $this->editor = new User($this->edit_by); + if ($this->editor->id) { + 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; +} + +} \ No newline at end of file diff --git a/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistoryController.php b/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistoryController.php new file mode 100644 index 000000000..4deac35fa --- /dev/null +++ b/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistoryController.php @@ -0,0 +1,131 @@ +needlogin = true; + $me = new User(); + $me->loadMe(); + $this->me = $me; + $this->layout()->set("me", $me); + + if (!$me->is(["Admin"])) { + $this->redirect("Dashboard"); + } + } + + protected function indexAction() + { + + $this->layout()->setTemplate("TimerecordingEmployeeWorkingHourHistory/Index"); + $timerecordingemployeeworkinghourhistorys = TimerecordingEmployeeWorkingHourHistoryModel::getAll(); + $this->layout()->set("timerecordingemployeeworkinghourhistorys", $timerecordingemployeeworkinghourhistorys); + + } + + protected function addAction() + { + $users=UserModel::getAll(); + $this->layout()->set("users", $users); + + $this->layout()->setTemplate("TimerecordingEmployeeWorkingHourHistory/Form"); + + } + + protected function editAction() + { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("tt History nicht gefunden", "error"); + $this->redirect("TimerecordingEmployeeWorkingHourHistory"); + } + + $timerecordingemployeeworkinghourhistorys = new TimerecordingEmployeeWorkingHourHistory($id); + if ($timerecordingemployeeworkinghourhistorys->id != $id) { + $this->layout()->setFlash("tt History nicht gefunden", "error"); + $this->redirect("TimerecordingEmployeeWorkingHourHistory"); + } + + $this->layout()->set("timerecordingemployeeworkinghourhistorys", $timerecordingemployeeworkinghourhistorys); + return $this->addAction(); + } + + protected function saveAction() + { + $r = $this->request; + $id = $r->id; + //var_dump($r->get());exit; + if (is_numeric($id) && $id > 0) { + $mode = "edit"; + $timerecordingemployeeworkinghourhistorys = new TimerecordingEmployeeWorkingHourHistory($id); + if (!$timerecordingemployeeworkinghourhistorys->id) { + $this->layout()->setFlash("tt History nicht gefunden", "error"); + $this->redirect("TimerecordingEmployeeWorkingHourHistory"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['user_id'] = trim($r->user_id); + $data['end'] = trim($r->end); + $data['times'] = trim($r->times); + + + if (!$data['user_id']) { + $data['user_id']=NULL; + } + if (!$data['end']) { + $data['end']=NULL; + } + if (!$data['times']) { + $data['times']=NULL; + } + + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $timerecordingemployeeworkinghourhistorys->update($data); + + } else { + $timerecordingemployeeworkinghourhistorys = TimerecordingEmployeeWorkingHourHistoryModel::create($data); + } +// var_dump($filestore); +// exit; + $id = $timerecordingemployeeworkinghourhistorys->save(); + + if (!$id) { + $this->layout()->setFlash("tt History konnte nicht angelegt werden", "error"); + $this->redirect("TimerecordingEmployeeWorkingHourHistory"); + } + + if ($mode == "edit") { + $this->layout()->setFlash("tt History erfolgreich geändert", "success"); + } else if ($mode = "add") { + $this->layout()->setFlash("tt History erfolgreich angelegt", "success"); + } + $this->redirect("TimerecordingEmployeeWorkingHourHistory"); + } + + + protected function deleteAction() + { + $id = $this->request->id; + $timerecordingemployeeworkinghourhistorys = new TimerecordingEmployeeWorkingHourHistory($id); + if (!$timerecordingemployeeworkinghourhistorys->id || $timerecordingemployeeworkinghourhistorys->id != $id) { + $this->layout()->setFlash("tt History nicht gefunden.", "error"); + $this->redirect("TimerecordingEmployeeWorkingHourHistory"); + } + + $timerecordingemployeeworkinghourhistorys->delete(); + $this->redirect("TimerecordingEmployeeWorkingHourHistory"); + } + +} diff --git a/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistoryModel.php b/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistoryModel.php new file mode 100644 index 000000000..23eff1dba --- /dev/null +++ b/application/TimerecordingEmployeeWorkingHourHistory/TimerecordingEmployeeWorkingHourHistoryModel.php @@ -0,0 +1,128 @@ + $value) { + if (property_exists(get_called_class(), $field)) { + if (substr($field, 0, 5) == "vlan_" && !$value) { + $model->$field = null; + continue; + } + $model->$field = $value; + } + } + + $me = mfValuecache::singleton()->get("me"); + if (!$me) { + $me = new User(); + $me->loadMe(); + mfValuecache::singleton()->set("me", $me); + } + + 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 getOne($id) + { + if (!is_numeric($id) || !$id) { + throw new Exception("Invalid number", 400); + } + $item = []; + $db = FronkDB::singleton(); + + $res = $db->select("TimerecordingEmployeeWorkingHourHistory", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingEmployeeWorkingHourHistory($data); + } + return $item; + } + + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("TimerecordingEmployeeWorkingHourHistory", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingEmployeeWorkingHourHistory($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("TimerecordingEmployeeWorkingHourHistory", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingEmployeeWorkingHourHistory($data); + if ($item->id) { + return $item; + } else { + return null; + } + } + return null; + } + + public static function search($filter) + { + $items = []; + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("TimerecordingEmployeeWorkingHourHistory", "*", "$where ORDER by enddate DESC"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingEmployeeWorkingHourHistory($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("user_id", $filter)) { + $userid = $filter['user_id']; + if (is_numeric($userid)) { + $where .= " AND user_id=$userid"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/TimerecordingReport/TimerecordingReportController.php b/application/TimerecordingReport/TimerecordingReportController.php index bbaf8a881..ee53f8ac6 100644 --- a/application/TimerecordingReport/TimerecordingReportController.php +++ b/application/TimerecordingReport/TimerecordingReportController.php @@ -95,6 +95,8 @@ class TimerecordingReportController extends mfBaseController $workingHours[$workinghour->user_id][$workinghour->day] = $workingHours[$workinghour->user_id][$workinghour->day] + $whend - $whstart; } } + + foreach ($this->holidays as $holiday) { $holiDay[date('Y-m-d', $holiday->timestamp)] = $holiday->timestamp; } @@ -556,13 +558,32 @@ class TimerecordingReportController extends mfBaseController $workingHours[$workinghour->day] = $workingHours[$workinghour->day] + $whend - $whstart; } } + + $workinghourshistory = TimerecordingEmployeeWorkingHourHistoryModel::search(['user_id' => $user_id]); + if ($workinghourshistory) { + $workingHoursHistory[9732489200]=$workingHours; + foreach ($workinghourshistory as $workinghourhistory) { + $whenddate = $workinghourhistory->enddate; + $workinghourhistoryhours = json_decode($workinghourhistory->workinghours, true); + foreach ($workinghourhistoryhours as $workinghourhistoryhour) { + $whstart = strtotime(date('Y-m-d', time()) . " " . $workinghourhistoryhour['start'] . ":00"); + $whend = strtotime(date('Y-m-d', time()) . " " . $workinghourhistoryhour['end'] . ":00"); + if (!$workingHoursHistory[$whenddate][$workinghourhistoryhour['day']]) { + $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] = $whend - $whstart; + } else { + $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] = $workingHoursHistory[$whenddate][$workinghourhistoryhour['day']] + $whend - $whstart; + } + } + } + } + foreach ($this->holidays as $holiday) { $holiDay[date('Y-m-d', $holiday->timestamp)] = $holiday->timestamp; } if ($datatype == 1) { $kw = date('W', $dataweek); - $year = date(o, $dataweek); + $year = date('o', $dataweek); $timestamp_montag = strtotime("{$year}-W{$kw}"); $timestamp_sonntag = strtotime("{$year}-W{$kw}-7"); $firstdate = strtotime(date("Y-m-d", $timestamp_montag) . " 00:00:00"); @@ -579,6 +600,16 @@ class TimerecordingReportController extends mfBaseController } $dDate = date('Y-m-d', $timestamp + $WintertimeCompensation); $dDay = date('w', $timestamp + $WintertimeCompensation); + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $timestamp) + { + $workingHours = $whdata; + } + } + } if (!$holiDay[$dDate] && $dDate >= date('Y-m-d', $startdate) && $dDate <= date('Y-m-d', $enddate)) { $mustSeconds = $mustSeconds + $workingHours[$dDay]; @@ -605,6 +636,17 @@ class TimerecordingReportController extends mfBaseController } $dDate = date('Y-m-d', $timestamp + $WintertimeCompensation); $dDay = date('w', $timestamp + $WintertimeCompensation); + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $timestamp) + { + $workingHours = $whdata; + } + } + } + if (!$holiDay[$dDate] && $dDate >= date('Y-m-d', $startdate) && $dDate <= date('Y-m-d', $enddate)) { $mustSeconds = $mustSeconds + $workingHours[$dDay]; } @@ -628,6 +670,16 @@ class TimerecordingReportController extends mfBaseController } $dDate = date('Y-m-d', $timestamp + $WintertimeCompensation); $dDay = date('w', $timestamp + $WintertimeCompensation); + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $timestamp) + { + $workingHours = $whdata; + } + } + } if (!$holiDay[$dDate]) { $mustSeconds = $mustSeconds + $workingHours[$dDay]; } @@ -756,6 +808,16 @@ class TimerecordingReportController extends mfBaseController $sumdays = 0; for ($i = $starttimecalc; $i <= $endtimecalc; $i = $i + 86400) { + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $i) + { + $workingHours = $whdata; + } + } + } $holidaycounter = $workingHours[date("w", $i)]; $daycheck = date("Y-m-d", $i); if (!$holiDay[$daycheck]) { @@ -812,6 +874,16 @@ class TimerecordingReportController extends mfBaseController $summcounter = 0; $savecounter = 0; for ($i = $starttimecalc; $i <= $endtimecalc; $i = $i + 86400) { + if ($workingHoursHistory) + { + foreach ($workingHoursHistory as $whkey => $whdata) { + $whtimestamp = strtotime(date('Y-m-d 23:59:59', $whkey)); + if ($whtimestamp >= $i) + { + $workingHours = $whdata; + } + } + } $holidaycounter = $workingHours[date("w", $i)]; $isSeconds = $isSeconds + $holidaycounter; $summcounter = $summcounter + $holidaycounter; diff --git a/application/WarehouseArticle/WarehouseArticleController.php b/application/WarehouseArticle/WarehouseArticleController.php index 77c80a59e..93eae95cc 100644 --- a/application/WarehouseArticle/WarehouseArticleController.php +++ b/application/WarehouseArticle/WarehouseArticleController.php @@ -24,6 +24,8 @@ class WarehouseArticleController extends TTCrud { ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center', 'priority' => 8]] ]; + protected array $autocompleteColumns = ['articleNumber', 'title', 'description', 'category']; + protected array $additionalActions = [ ['key' => 'openHistory','title' => 'Historie','class' => 'fas fa-history text-secondary'], ['key' => 'editDistributorEntries','title' => 'Lieferanten','class' => 'fas fa-truck text-cyan'], diff --git a/application/WarehouseEShop/WarehouseEShopController.php b/application/WarehouseEShop/WarehouseEShopController.php index af598a276..956689926 100644 --- a/application/WarehouseEShop/WarehouseEShopController.php +++ b/application/WarehouseEShop/WarehouseEShopController.php @@ -4,7 +4,6 @@ // Hide Articles - class WarehouseEShopController extends TTCrud { protected string $headerTitle = 'Energie Steiermark Shop'; protected bool $createText = false; @@ -12,11 +11,13 @@ class WarehouseEShopController extends TTCrud { protected array $columns = [ ['key' => 'title', 'text' => 'Artikel', 'priority' => 11], ['key' => 'category', 'text' => 'Kategorie', 'table' => false], - ['key' => 'price', 'text' => 'Preis', 'table' => ['filter' => false,'sortable' => false,'class' => 'text-right']], - ['key' => 'amount', 'text' => 'Menge', 'table' => ['filter' => false,'sortable' => false,'class' => 'p-0 width-80'], 'priority' => 9], - ['key' => 'add', 'text' => 'Hinzufügen', 'table' => ['filter' => false,'sortable' => false, 'class' => 'width-120 text-center'], 'priority' => 5000] + ['key' => 'price', 'text' => 'Preis', 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-right']], + ['key' => 'amount', 'text' => 'Menge', 'table' => ['filter' => false, 'sortable' => false, 'class' => 'p-0 width-80'], 'priority' => 9], + ['key' => 'add', 'text' => 'Hinzufügen', 'table' => ['filter' => false, 'sortable' => false, 'class' => 'width-120 text-center'], 'priority' => 5000] ]; + protected array $permissionCheck = ['WarehouseEShop']; + protected array $infoMessages = [ 'create' => 'Not possible', 'update' => 'Not possible', @@ -24,10 +25,6 @@ class WarehouseEShopController extends TTCrud { 'noChanges' => 'Keine Änderungen', ]; - public function permissionCheck(): bool { - return $this->user->can(["WarehouseEShop"]); - } - protected function prepareCrudConfig() { if (!$this->user->can('WarehouseAdmin')) { $this->columns[2]['table'] = false; @@ -62,5 +59,6 @@ class WarehouseEShopController extends TTCrud { "total_pages" => ceil($filteredAvailable / $perPage), "per_page" => $perPage, "filtered_available" => $filteredAvailable, - "total_rows" => $totalRows]]); } + "total_rows" => $totalRows]]); + } } \ No newline at end of file diff --git a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php index 72c0fe1fc..85af3dd82 100644 --- a/application/WarehouseEShopOrder/WarehouseEShopOrderController.php +++ b/application/WarehouseEShopOrder/WarehouseEShopOrderController.php @@ -23,6 +23,8 @@ class WarehouseEShopOrderController extends TTCrud { ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']] ]; + protected array $permissionCheck = ['WarehouseEShop']; + protected array $additionalActions = [ ['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'], ['key' => 'showTrackingHistory', 'title' => 'Tracking Historie', 'class' => 'fas fa-truck text-primary'], @@ -38,10 +40,6 @@ class WarehouseEShopOrderController extends TTCrud { ]; //@formatter:on - public function permissionCheck(): bool { - return $this->user->can(["WarehouseEShop"]); - } - protected function customRowsHandler($rows): array { $statusToText = [ 'new' => 'Neu', @@ -338,6 +336,7 @@ class WarehouseEShopOrderController extends TTCrud { $id = WarehouseEShopOrderModel::create(['status' => 'new', 'extRef' => $json['extRef'], 'deliveryMode' => $json['deliveryMode'], + 'deliveryAddressAdditional' => $json['deliveryAddressAdditional'], 'deliveryAddressName' => $json['deliveryAddressName'], 'deliveryAddressLine' => $json['deliveryAddressLine'], 'deliveryAddressPLZ' => $json['deliveryAddressPLZ'], diff --git a/application/WarehouseHistory/WarehouseHistoryController.php b/application/WarehouseHistory/WarehouseHistoryController.php index ea395d65b..e52dcbccd 100644 --- a/application/WarehouseHistory/WarehouseHistoryController.php +++ b/application/WarehouseHistory/WarehouseHistoryController.php @@ -19,7 +19,7 @@ class WarehouseHistoryController { WarehouseHistoryModel::create(['table' => $mod, 'row_id' => $postData['id'], 'key' => $key, - 'old_value' => $currentData->$key, + 'old_value' => $currentData->$key ?? '', 'new_value' => $value, 'note' => '', 'user_id' => $me->id, diff --git a/application/WarehouseOrderItem/WarehouseOrderItem.php b/application/WarehouseOffer/WarehouseOffer.php similarity index 52% rename from application/WarehouseOrderItem/WarehouseOrderItem.php rename to application/WarehouseOffer/WarehouseOffer.php index 95e2c10dc..7aff40082 100644 --- a/application/WarehouseOrderItem/WarehouseOrderItem.php +++ b/application/WarehouseOffer/WarehouseOffer.php @@ -3,7 +3,7 @@ /** * @property mixed|null $name */ -class WarehouseOrderItem extends mfBaseModel +class WarehouseOffer extends mfBaseModel { } \ No newline at end of file diff --git a/application/WarehouseOffer/WarehouseOfferController.php b/application/WarehouseOffer/WarehouseOfferController.php new file mode 100644 index 000000000..e9a80096b --- /dev/null +++ b/application/WarehouseOffer/WarehouseOfferController.php @@ -0,0 +1,56 @@ + 'id', 'text' => 'ID', 'modal' => false], + ['key' => 'offerNumber', 'text' => 'Angebotsnummer', 'required' => true, 'modal' => false], + ['key' => 'customerNumber', 'text' => 'Kundennummer', 'required' => true, 'modal' => false], + ['key' => 'customerName', 'text' => 'Kundenname', 'required' => true, 'modal' => false], + ['key' => 'customerCity', 'text' => 'Stadt', 'required' => true, 'modal' => false], + ['key' => 'customerVAT', 'text' => 'UID', 'required' => true, 'modal' => false], + ['key' => 'editor', 'text' => 'Sachbearbeiter', 'required' => true, 'modal' => false], + ['key' => 'totalAmount', 'text' => 'Gesamtbetrag', 'required' => true, 'modal' => false], + ['key' => 'status', 'text' => 'Status', 'required' => true, 'modal' => ['type' => 'select']], + ['key' => 'create', 'text' => 'Erstellt', 'required' => true, 'modal' => false], + ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'modal' => ['type' => 'select']], + ['key' => 'actions', + 'text' => 'Aktionen', + 'required' => false, + 'modal' => false, + 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']], + ]; + + protected array $permissionCheck = ['WarehouseAdmin']; + + protected array $additionalActions = [ + ['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'], + ['key' => 'sendOffer', 'title' => 'Angebot senden', 'class' => 'fas fa-paper-plane text-success'] + ]; + + protected array $infoMessages = [ + 'create' => 'Angebot wurde erfolgreich erstellt.', + 'update' => 'Angebot wurde aktualisiert.', + 'delete' => 'Angebot wurde gelöscht', + 'noChanges' => 'Keine Änderungen', + 'sent' => 'Angebot wurde erfolgreich gesendet', + ]; + + protected function beforeCreate(): bool { + $currentCount = WarehouseOfferModel::count(['create' => ['from' => strtotime(date('Y-01-01'))]]); + $this->postData['offerNumber'] = 'AN' . date('Y') . '-' . str_pad($currentCount + 1, 4, '0', STR_PAD_LEFT); + + return true; + } + + protected function beforeUpdate($postData): bool { + (new WarehouseHistoryController)->create($postData, $this->mod); + return true; + } + + protected function getHistoryAction() { + self::returnJson((new WarehouseHistoryController)->getHistory($this->request->id, $this->mod, $this->columns)); + } +} diff --git a/application/WarehouseOffer/WarehouseOfferModel.php b/application/WarehouseOffer/WarehouseOfferModel.php new file mode 100644 index 000000000..c49405483 --- /dev/null +++ b/application/WarehouseOffer/WarehouseOfferModel.php @@ -0,0 +1,52 @@ + 'id', 'text' => 'ID', 'modal' => false], - ['key' => 'distributorId', 'text' => 'Lieferant', 'required' => true, 'type' => 'autocomplete','table' => ['class' => 'text-nowrap', 'filter' => 'autocomplete'],'modal' => [ - 'apiUrl' => 'WarehouseDistributor/autocomplete','items' => 'WarehouseDistributor/autocomplete', 'type' => 'autocomplete']], - ['key' => 'extRef', 'text' => 'Externe Referenz', 'required' => false], - ['key' => 'intRef', 'text' => 'Interne Referenz', 'required' => false], - ['key' => 'status', 'text' => 'Status', 'required' => true, 'modal' => ['type' => 'select', 'items' => [ - ['value' => 'new', 'text' => 'Neu'], - ['value' => 'accepted', 'text' => 'An Lieferant übergeben'], - ['value' => 'sent', 'text' => 'Gesendet'], - ['value' => 'done', 'text' => 'Erledigt'], - ]]], - ['key' => 'trackingNumber', 'text' => 'Trackingnummer', 'required' => false], - ['key' => 'sum', 'text' => 'Summe', 'required' => true, 'modal' => false, 'table' => ['filter' => 'numberRange']], - ['key' => 'create', 'text' => 'Erstellt', 'required' => true, 'modal' => false, 'filter' => 'datetime'], - ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'table' => ['filter' => 'select'], 'modal' => ['type' => 'select', 'items' => []]], + ['key' => 'id', 'text' => 'ID', 'modal' => false, 'table' => false], + ['key' => 'orderNumber', 'text' => 'Bestellnummer', 'required' => true, 'modal' => false], + ['key' => 'distributor', 'text' => 'Lieferant', 'required' => false, 'modal' => false, 'table' => ['filter' => false]], + ['key' => 'delAddrCity', 'text' => 'Stadt', 'required' => true, 'modal' => false, 'table' => false], + ['key' => 'delAddrEMail', 'text' => 'E-Mail', 'required' => true, 'modal' => false, 'table' => false], + ['key' => 'delAddrLine', 'text' => 'Adresse', 'required' => true, 'modal' => false, 'table' => false], + ['key' => 'delAddrName', 'text' => 'Name', 'required' => true, 'modal' => false, 'table' => false], + ['key' => 'delAddrPLZ', 'text' => 'PLZ', 'required' => true, 'modal' => false, 'table' => false], + ['key' => 'editor', 'text' => 'Bearbeiter', 'required' => true, 'modal' => ['type' => 'select'], 'table' => ['filter' => 'select']], + ['key' => 'note', 'text' => 'Notiz', 'required' => true, 'modal' => false, 'table' => false], + ['key' => 'sum', 'text' => 'Summe', 'required' => false, 'modal' => false, 'table' => ['class' => 'text-right']], + ['key' => 'status', 'text' => 'Status', 'required' => false, 'modal' => ['type' => 'select', 'items' => []], 'table' => ['filter' => 'select']], + ['key' => 'positions', 'text' => 'Positionen', 'required' => true, 'modal' => false, 'table' => false], + ['key' => 'extReference', 'text' => 'Externe Referenz', 'required' => true, 'modal' => false], + ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'modal' => ['type' => 'select'], 'table' => ['filter' => 'select']], + ['key' => 'create', 'text' => 'Erstellt', 'required' => true, 'modal' => false], ['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']], ]; - - protected array $additionalActions = [['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary']]; + //@formatter:on protected array $infoMessages = ['create' => 'Bestellung wurde erfolgreich erstellt.', 'update' => 'Bestellung wurde aktualisiert.', 'delete' => 'Bestellung wurde gelöscht', 'noChanges' => 'Keine Änderungen',]; - public function permissionCheck(): bool { - return $this->user->can(["WarehouseEShop"]); - } - - protected function prepareCrudConfig() { - // Fill Users in createBy column - $column = array_search('createBy', array_column($this->columns, 'key')); - $this->columns[$column]['modal']['items'] = array_map(function ($user) { + protected function prepareCrudConfig(): void { + $editorColumnIndex = array_search('editor', array_column($this->columns, 'key')); + $this->columns[$editorColumnIndex]['modal']['items'] = array_map(function ($user) { return ['value' => intval($user->id), 'text' => $user->name]; - }, UserModel::search()); + }, UserModel::search(['employee' => true])); + $statusIndex = array_search('status', array_column($this->columns, 'key')); + $this->columns[$statusIndex]['modal']['items'] = [ + ['value' => 'new', 'text' => 'Neu'], + ['value' => 'accepted', 'text' => 'Akzeptiert'], + ['value' => 'ordered', 'text' => 'Bestellt'], + ['value' => 'sent', 'text' => 'Versendet'], + ['value' => 'partiallyDelivered', 'text' => 'Teilweise geliefert'], + ['value' => 'fullyDelivered', 'text' => 'Geliefert'], + ['value' => 'cancelled', 'text' => 'Storniert'], + ]; } - protected function createOrderAction() { - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); - error_reporting(E_ALL); + protected function beforeCreate(): bool { + $this->postData['orderNumber'] = 'PO' . date('Y') . '-' . str_pad(WarehouseOrderModel::count(['create' => ['from' => strtotime(date('Y-01-01'))]]) + 1, 4, '0', STR_PAD_LEFT); - $json = json_decode(file_get_contents('php://input'), true); - $orders = $json; - $orderIds = []; - - foreach ($orders as $order) { - $distributor = $order['distributor'][0]; - $orderAmount = $order['orderAmount']; - $orders = $order['orders']; - - $order = [ - 'distributorId' => $distributor['id'], - 'extRef' => null, - 'status' => 'new', - 'trackingNumber' => null, - 'sum' => $orderAmount, - 'create' => time(), - 'createBy' => $this->user->id, - ]; - - $orderId = WarehouseOrderModel::create($order); - $orderIds[] = $orderId; - - foreach ($orders as $orderItem) { - $article = WarehouseArticleModel::get($orderItem['articleId']); - - WarehouseEShopOrderItemModel::create([ - 'orderId' => $orderId, - 'articleId' => $orderItem['articleId'], - 'quantity' => $orderItem['amount'], - 'price' => $article->cheapestPurchasePrice, - ]); - } - } - - self::returnJson(['success' => true, 'message' => $this->infoMessages['create'], 'ids' => $orderIds]); - } - - protected function getOrderItemsAction() { - $orderItems = WarehouseEShopOrderItemModel::getAll(['orderId' => $this->request->id]); - - // also get the article name of the order items - - foreach ($orderItems as $key => $orderItem) { - $article = WarehouseArticleModel::get($orderItem->articleId); - $orderItem->articleName = $article->title; - } - - self::returnJson($orderItems); - } - - protected function beforeUpdate($postData): bool { - (new WarehouseHistoryController)->create($postData, $this->mod); return true; } - protected function getHistoryAction() { - self::returnJson((new WarehouseHistoryController)->getHistory($this->request->id, $this->mod, $this->columns)); + protected function getArticleDistributorDataAction() { + $articleId = $this->request->articleId; + if ($this->request->allDistributor === 'true') self::returnJson(array_map(fn($d) => ['id' => $d->id, + 'name' => $d->name], WarehouseDistributorModel::getAll())); + else if (!empty($articleId)) self::returnJson(array_map(fn($d) => ['id' => $d->distributorId, + 'name' => WarehouseDistributorModel::get($d->distributorId)->name, + 'purchasePrice' => $d->purchasePrice, + 'externalArticleNumber' => $d->externalArticleNumber], WarehouseArticleDistributorModel::getAll(['articleId' => $articleId]))); + else self::returnJson([]); } + + protected function getByIdParse(array $order): array { + $order['positions'] = json_decode($order['positions'], true); + + foreach ($order['positions'] as &$position) { + $position['distributorName'] = WarehouseDistributorModel::get($position['distributorId'])->name; + $position['articleName'] = WarehouseArticleModel::get($position['article'])->title; + } + + return $order; + } + + protected function createPDFAction() { + $order = (array) WarehouseOrderModel::get($this->request->id); + $order['positions'] = json_decode($order['positions'], true); + // check if all positions have the same distributor + $distributorId = $order['positions'][0]['distributorId']; + foreach ($order['positions'] as $key => $position) { + if ($position['distributorId'] !== $distributorId) { + self::returnJson(['error' => 'Die Bestellung enthält Positionen von verschiedenen Lieferanten.']); + } + + // we need to get the article name and distributor name for the pdf + $position['distributorName'] = WarehouseDistributorModel::get($position['distributorId'])->name; + $position['articleName'] = WarehouseArticleModel::get($position['article'])->title; + + $order['positions'][$key] = $position; + } + + $pdf_vars = ['order' => $order, + 'distributor' => WarehouseDistributorModel::get($distributorId), + "bank_iban" => TT_INVOICE_BANK_IBAN, + "bank_bic" => TT_INVOICE_BANK_BIC, + "bank_bank" => TT_INVOICE_BANK_BANK, + "bank_owner" => TT_INVOICE_BANK_OWNER]; + + + $countryText = CountryModel::search(['id' => WarehouseDistributorModel::get($distributorId)->countryId])[0]->name; + + $headerHtml = file_get_contents(BASEDIR . "/Layout/default/WarehouseOrder/PDF_HEADER.html"); + $headerHtml = str_replace("{{ basedir }}", BASEDIR, $headerHtml); + $headerHtml = str_replace("{{ externalReference }}","Ihre Referenz: ". $order['extReference'], $headerHtml); + + $headerHtml = str_replace("{{ addressLine_1 }}", WarehouseDistributorModel::get($distributorId)->name, $headerHtml); + $headerHtml = str_replace("{{ addressLine_2 }}", WarehouseDistributorModel::get($distributorId)->address, $headerHtml); + $headerHtml = str_replace("{{ addressLine_3 }}", WarehouseDistributorModel::get($distributorId)->plz . " " . WarehouseDistributorModel::get($distributorId)->city, $headerHtml); + $headerHtml = str_replace("{{ addressLine_4 }}", $countryText, $headerHtml); + + $headerHtml = str_replace("{{ billingAddressLine_1 }}", "Xinon GmbH", $headerHtml); + $headerHtml = str_replace("{{ billingAddressLine_2 }}", "Fladnitz im Raabtal 150", $headerHtml); + $headerHtml = str_replace("{{ billingAddressLine_3 }}", "8322 Studenzen", $headerHtml); + $headerHtml = str_replace("{{ billingAddressLine_4 }}", "Österreich", $headerHtml); + $headerHtml = str_replace("{{ billingAddressLine_5 }}", "einkauf@xinon.at", $headerHtml); + $headerHtml = str_replace("{{ billingAddressLine_6 }}", "Referenz: ". $order["orderNumber"] . "", $headerHtml); + + // if order dellAddrLine is Fladnitz im Raabtal 150 we need to set all template strings to empty + + $chk = $order['delAddrLine'] == "Fladnitz im Raabtal 150"; + + $headerHtml = str_replace("{{ shippingAddressLine_1 }}", $chk ? "" : $order['delAddrName'], $headerHtml); + $headerHtml = str_replace("{{ shippingAddressLine_2 }}", $chk ? "" : $order['delAddrLine'], $headerHtml); + $headerHtml = str_replace("{{ shippingAddressLine_3 }}", $chk ? "" : $order['delAddrPLZ'] . " " . $order['delAddrCity'], $headerHtml); + $headerHtml = str_replace("{{ shippingAddressLine_4 }}", $chk ? "" : $order['delAddrEMail'], $headerHtml); + + + $headerFile = BASEDIR . "/var/temp/order_header-" . date("U") . "-" . rand(1000, 9999) . ".html"; + file_put_contents($headerFile, $headerHtml); + + $footerHtml = file_get_contents(BASEDIR . "/Layout/default/WarehouseOrder/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/order_footer-" . date("U") . "-" . rand(1000, 9999) . ".html"; + file_put_contents($footerFile, $footerHtml); + + + $pdf = new PdfForm("WarehouseOrder/PDF_MAIN", $pdf_vars); + $wkhtmltopdfArgs = "--header-html $headerFile --footer-html $footerFile"; + $filename = $pdf->render($wkhtmltopdfArgs); + + // return the pdf and die so the client sees the pdf not the filename + header('Content-Type: application/pdf'); + header('Content-Disposition: inline; filename="' . $filename . '"'); + readfile($filename); + + } + + } \ No newline at end of file diff --git a/application/WarehouseOrder/WarehouseOrderModel.php b/application/WarehouseOrder/WarehouseOrderModel.php index 65f5d80dc..ac4677800 100644 --- a/application/WarehouseOrder/WarehouseOrderModel.php +++ b/application/WarehouseOrder/WarehouseOrderModel.php @@ -1,28 +1,40 @@ \ No newline at end of file diff --git a/application/WarehouseOrderItem/WarehouseOrderItemModel.php b/application/WarehouseOrderItem/WarehouseOrderItemModel.php deleted file mode 100644 index fd681ac82..000000000 --- a/application/WarehouseOrderItem/WarehouseOrderItemModel.php +++ /dev/null @@ -1,16 +0,0 @@ - ['filter' => 'select'], 'modal' => ['type' => 'select', 'items' => []]], ['key' => 'warehouseLocation', 'text' => 'Lagerort', 'required' => false, 'type' => 'varchar'], - ['key' => 'canceled', 'text' => 'Storniert', 'required' => false, 'modal' => ['visible' => false, 'type' => 'select', 'items' => [['value' => 0, 'text' => 'Nein'], ['value' => 1, 'text' => 'Ja']]], 'table' => ['filter' => 'select']], + ['key' => 'canceled', + 'text' => 'Storniert', + 'required' => false, + 'modal' => ['visible' => false, 'type' => 'select', 'items' => [['value' => 0, 'text' => 'Nein'], ['value' => 1, 'text' => 'Ja']]], + 'table' => ['filter' => 'select']], ['key' => 'note', 'text' => 'Notiz', 'required' => false, 'type' => 'textarea'], ['key' => 'actions', 'text' => 'Aktionen', @@ -50,6 +54,8 @@ class WarehouseOrderRequestController extends TTCrud { 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']], ]; + protected array $permissionCheck = ['WarehouseUser']; + protected array $additionalActions = [['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary']]; protected array $infoMessages = ['create' => 'Bestellwunsch wurde erstellt.', @@ -59,10 +65,6 @@ class WarehouseOrderRequestController extends TTCrud { protected array $additionalJSVariables = ['BASE_URL' => '/WarehouseOrderRequest', 'WAREHOUSE_ADMIN' => true]; - public function permissionCheck(): bool { - return $this->user->can(["WarehouseUser"]); - } - protected function prepareCrudConfig() { // Fill Users in createBy column $userArray = array_map(function ($user) { @@ -96,10 +98,10 @@ class WarehouseOrderRequestController extends TTCrud { } protected function customAutoCompleteWare($value) { - if (!is_numeric($value)) return [ 'id' => $value, 'title' => $value]; + if (!is_numeric($value)) return ['id' => $value, 'title' => $value]; $article = WarehouseArticleModel::get(intval($value)); - return [ 'id' => $article->id, 'title' => $article->title ]; + return ['id' => $article->id, 'title' => $article->title]; } protected function beforeUpdate($postData): bool { diff --git a/application/WarehouseProject/WarehouseProject.php b/application/WarehouseProject/WarehouseProject.php new file mode 100644 index 000000000..8554d7bfa --- /dev/null +++ b/application/WarehouseProject/WarehouseProject.php @@ -0,0 +1,4 @@ + 'title', 'text' => 'Titel', 'required' => true, 'table' => ['class' => 'text-nowrap', 'priority' => 9]], + ['key' => 'description', 'text' => 'Beschreibung', 'required' => true, 'table' => ['class' => 'text-nowrap']], + ['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'type' => 'select', 'table' => ['class' => 'text-nowrap', 'filter' => 'select'], 'modal' => ['items' => [], 'type' => 'select']], + ['key' => 'create', 'text' => 'Erstellt am', 'required' => true, 'table' => ['filter' => 'date', 'class' => 'text-center']], + ['key' => 'address', 'text' => 'Adresse', 'required' => true, 'type' => 'autocomplete', 'table' => ['class' => 'text-nowrap', 'filter' => false], 'modal' => ['apiUrl' => '/Address/api?do=findAddress', 'items' => '/Address/api?do=findAddress', 'type' => 'autocomplete']], + ['key' => 'status', 'text' => 'Status', 'required' => true, 'table' => ['filter' => 'select'], 'modal' => [ 'type' => 'select', 'items' => [ ['value' => 'erstellt', 'text' => 'Erstellt'], ['value' => 'in_bearbeitung', 'text' => 'In Bearbeitung'], ['value' => 'erledigt', 'text' => 'Erledigt'], ['value' => 'verrechnet', 'text' => 'Verrechnet']]]] + ]; + + + protected array $additionalActions = [ + ]; + + protected array $infoMessages = [ + 'create' => 'Projekt wurde erstellt', + 'update' => 'Projekt wurde aktualisiert', + 'delete' => 'Projekt wurde gelöscht', + 'noChanges' => 'Keine Änderungen', + ]; + //@formatter:on + + public function prepareCrudConfig() { + $users = array_map(function($user) { + return ['value' => $user->id, 'text' => $user->name]; + }, UserModel::search(['employee' => true])); + + $this->columns[1]['modal']['items'] = $users; + } +} \ No newline at end of file diff --git a/application/WarehouseProject/WarehouseProjectModel.php b/application/WarehouseProject/WarehouseProjectModel.php new file mode 100644 index 000000000..a1aa8f680 --- /dev/null +++ b/application/WarehouseProject/WarehouseProjectModel.php @@ -0,0 +1,15 @@ +getEnvironment() == "thetool") { + // Drop the existing tables + $this->table("WarehouseOrder")->drop()->save(); + $this->table("WarehouseOrderItem")->drop()->save(); + + // Create the new WarehouseOrder table + $table = $this->table("WarehouseOrder", ["id" => false, "primary_key" => ["id"]]); + $table->addColumn("id", "integer", ["identity" => true]) + ->addColumn("orderNumber", "string", ["null" => false, "limit" => 255]) + ->addColumn("delAddrCity", "string", ["null" => false, "limit" => 255]) + ->addColumn("delAddrEMail", "string", ["null" => false, "limit" => 255]) + ->addColumn("delAddrLine", "string", ["null" => false, "limit" => 255]) + ->addColumn("delAddrName", "string", ["null" => false, "limit" => 255]) + ->addColumn("delAddrPLZ", "string", ["null" => false, "limit" => 255]) + ->addColumn("editor", "integer", ["null" => false]) + ->addColumn("note", "text", ["null" => false]) + ->addColumn("positions", "text", ["null" => false]) + ->addColumn("create", "integer", ["null" => false]) + ->addColumn("createBy", "integer", ["null" => false]) + ->create(); + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $this->table("WarehouseOrder")->drop()->save(); + + $WarehouseOrder = $this->table("WarehouseOrder", ["signed" => true]); + $WarehouseOrder + ->addColumn('distributorId', 'integer', ['null' => false]) + ->addColumn('intRef', 'string', ['null' => true]) + ->addColumn('extRef', 'string', ['null' => true]) + ->addColumn('status', 'enum', ['values' => ['new', 'accepted', 'sent', 'done'], 'null' => false, 'default' => 'new']) + ->addColumn('sum', 'float', ['null' => true]) + ->addColumn('trackingNumber', 'string', ['null' => true]) + ->addColumn('create', 'integer', ['null' => false, 'default' => 1728541890]) + ->addColumn('createBy', 'integer', ['null' => false, 'default' => 1]) + ->create(); + + $WarehouseOrderItem = $this->table("WarehouseOrderItem", ["signed" => true]); + $WarehouseOrderItem + ->addColumn('orderId', 'integer', ['null' => false]) + ->addColumn('articleId', 'integer', ['null' => false]) + ->addColumn('quantity', 'integer', ['null' => false]) + ->addColumn('price', 'float', ['null' => false]) + ->addForeignKey('orderId', 'WarehouseOrder', 'id') + ->addForeignKey('articleId', 'WarehouseArticle', 'id') + ->create(); + } + } +} diff --git a/db/migrations/20250131160000_warehouse_modify_11.php b/db/migrations/20250131160000_warehouse_modify_11.php new file mode 100644 index 000000000..7c3810d4c --- /dev/null +++ b/db/migrations/20250131160000_warehouse_modify_11.php @@ -0,0 +1,21 @@ +getEnvironment() == "thetool") { + $table = $this->table("WarehouseOrder"); + $table->addColumn("distributorId", "integer", ["null" => false]); + $table->save();; + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $table = $this->table("WarehouseOrder"); + $table->removeColumn("distributorId"); + $table->save();; + } + } +} diff --git a/db/migrations/20250204190000_warehouse_modify_12.php b/db/migrations/20250204190000_warehouse_modify_12.php new file mode 100644 index 000000000..028289ce1 --- /dev/null +++ b/db/migrations/20250204190000_warehouse_modify_12.php @@ -0,0 +1,21 @@ +getEnvironment() == "thetool") { + $table = $this->table("WarehouseOrder"); + $table->addColumn("extReference", "string", ["length" => 255, "null" => true]); + $table->save();; + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $table = $this->table("WarehouseOrder"); + $table->removeColumn("extReference"); + $table->save();; + } + } +} diff --git a/db/migrations/20250207063605_timerecording_employee_working_hour_history.php b/db/migrations/20250207063605_timerecording_employee_working_hour_history.php new file mode 100644 index 000000000..84c915de5 --- /dev/null +++ b/db/migrations/20250207063605_timerecording_employee_working_hour_history.php @@ -0,0 +1,37 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingEmployeeWorkingHourHistory", ["signed" => true]); + $table->addColumn("user_id", "integer", ["null" => false]); + $table->addColumn("enddate", "integer", ["null" => false, "limit" => 64]); + $table->addColumn("workinghours", "string", ["null" => true]); + $table->addColumn("create_by", "integer", ["null" => false]); + $table->addColumn("edit_by", "integer", ["null" => false]); + $table->addColumn("create", "integer", ["null" => false]); + $table->addColumn("edit", "integer", ["null" => false]); + $table->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $this->table("TimerecordingEmployeeWorkingHourHistory")->drop()->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/lib/Helper/Helper.php b/lib/Helper/Helper.php index 3668e1b8d..aa31b8c6e 100644 --- a/lib/Helper/Helper.php +++ b/lib/Helper/Helper.php @@ -8,7 +8,7 @@ class Helper { * @param string $columnName The name of the column in the database table. * @return string The SQL condition generated based on the filter value and column name. */ - public static function generateFilterCondition($filterValue, string $columnName, bool $exactMatch = false): string { + public static function generateFilterCondition($filterValue, $columnName, bool $exactMatch = false): string { $sql = ""; if (is_array($filterValue)) { @@ -30,6 +30,9 @@ class Helper { } else if (!empty($filterValue)) { if ($exactMatch) { $sql .= " AND `$columnName` = '" . $filterValue . "'"; + } else if (strpos($columnName, "|") !== false) { + foreach (explode(" ", $filterValue) as $item) + $sql .= " AND CONCAT(" . join(",", explode("|", $columnName)) . ") LIKE '%" . str_replace("%", "", $item) . "%'"; } else if ($filterValue[0] === "%") { $sql .= " AND `$columnName` LIKE '" . $filterValue . "'"; } else if ($filterValue[strlen($filterValue) - 1] === "%") { diff --git a/lib/SNOPP/SNOPP.php b/lib/SNOPP/SNOPP.php new file mode 100644 index 000000000..d995ea3e5 --- /dev/null +++ b/lib/SNOPP/SNOPP.php @@ -0,0 +1,36 @@ + [ + 'method' => 'GET', + 'header' => "X-Api-Key: $SNOPP_API_KEY\r\n", + ] + ]; + + $snopp_output = file_get_contents("$SNOPP_API_URL/ticket/find?provider_id=all&status=open", false, stream_context_create($ctx_opts)); + $ticket_obj = json_decode($snopp_output); + $tickets = $ticket_obj->result->tickets; + + return $tickets; + } + +} +?> diff --git a/lib/TTCrud/TTCrud.php b/lib/TTCrud/TTCrud.php index 484b59c7c..daca7bbcc 100644 --- a/lib/TTCrud/TTCrud.php +++ b/lib/TTCrud/TTCrud.php @@ -10,6 +10,8 @@ * @property array $additionalJSVariables * @property array $infoMessages * @property bool $onlyView + * @property array $defaultOrder + * @property array $autocompleteColumns */ class TTCrud extends mfBaseController { public User $user; @@ -25,11 +27,8 @@ class TTCrud extends mfBaseController { $this->user = $me; $this->layout()->set('me', $me); - if (method_exists($this, 'permissionCheck')) { - $allowed = $this->permissionCheck(); - if (!$allowed) { - $this->redirect("Dashboard"); - } + if (isset($this->permissionCheck) && !$me->can($this->permissionCheck)) { + $this->redirect("Dashboard"); } else if (!$me->is(["Admin"])) { $this->redirect("Dashboard"); } @@ -57,35 +56,43 @@ class TTCrud extends mfBaseController { return $checkArray; } + + protected function indexAction() { $this->layout()->set('additionalJS', ['js/pages/WarehouseHistory/WarehouseHistoryModal.js']); - $customJsFile = defined('BASEDIR') ? BASEDIR . "/public/js/pages/{$this->mod}/{$this->mod}.js" : null; + $pageName = (defined('BASEDIR') && file_exists(BASEDIR . "/public/js/pages/{$this->mod}/{$this->mod}.js")) + ? $this->mod + : "DefaultCrudView"; - if ($customJsFile && file_exists($customJsFile)) { - $pageName = $this->mod; - } else { - $pageName = "DefaultCrudView"; - } + $JS_VARIABLES = [ + "CRUD_CONFIG" => $this->getCrudConfig(), + "CREATE_URL" => $this::getUrl("{$this->mod}/create"), + "TABLE_URL" => $this::getUrl("{$this->mod}/get"), + "UPDATE_URL" => $this::getUrl("{$this->mod}/update"), + "DELETE_URL" => $this::getUrl("{$this->mod}/delete"), + "USER_ID" => $this->user->id + ]; - $JS_VARIABLES = ["CRUD_CONFIG" => $this->getCrudConfig(), - "CREATE_URL" => $this::getUrl($this->mod . "/create"), - "TABLE_URL" => $this::getUrl($this->mod . "/get"), - "UPDATE_URL" => $this::getUrl($this->mod . "/update"), - "DELETE_URL" => $this::getUrl($this->mod . "/delete"), - "USER_ID" => $this->user->id]; - - if ($this->additionalJSVariables && is_array($this->additionalJSVariables)) { - $JS_VARIABLES = array_merge($JS_VARIABLES, $this->additionalJSVariables); - } + if (!empty($this->additionalJSVariables) && is_array($this->additionalJSVariables)) $JS_VARIABLES = array_merge($JS_VARIABLES, $this->additionalJSVariables); Helper::renderVue($this, $pageName, $this->headerTitle, $JS_VARIABLES); } + /** * Returns the configuration for the CRUD component for the Vue component. * @return array */ protected function getCrudConfig(): array { + + + $column = array_search('createBy', array_column($this->columns, 'key')); + if ($column !== false) { + $this->columns[$column]['modal']['items'] = array_map(function ($user) { + return ['value' => intval($user->id), 'text' => $user->name]; + }, UserModel::search(['employee' => true])); + } + if (method_exists($this, 'prepareCrudConfig')) { $this->prepareCrudConfig(); } @@ -186,7 +193,6 @@ class TTCrud extends mfBaseController { } protected function createAction() { - // if this->model has property createBy, set it to the current user id and create to current epoch time if (property_exists($this->model, 'createBy')) { $this->postData['createBy'] = $this->user->id; } @@ -194,12 +200,12 @@ class TTCrud extends mfBaseController { $this->postData['create'] = time(); } - Helper::validateArray($this->postData, $this->checkArray); - if (method_exists($this, 'beforeCreate') && !$this->beforeCreate($this->postData)) { self::returnJson(['success' => false, 'message' => 'Ein Fehler ist aufgetreten.']); } + Helper::validateArray($this->postData, $this->checkArray); + $id = $this->model::create($this->postData); if (method_exists($this, 'afterCreate')) { @@ -212,12 +218,12 @@ class TTCrud extends mfBaseController { } protected function updateAction() { -// if (property_exists($this->model, 'createBy') && !isset($this->postData['createBy'])) { -// $this->postData['createBy'] = $this->user->id; -// } -// if (property_exists($this->model, 'create') && !isset($this->postData['create'])) { -// $this->postData['create'] = time(); -// } + if (property_exists($this->model, 'create') && isset($this->postData['create'])) { + $this->postData['create'] = $this->model::get($this->postData['id'])->create; + } + if (property_exists($this->model, 'createBy') && isset($this->postData['createBy'])) { + $this->postData['createBy'] = $this->model::get($this->postData['id'])->createBy; + } Helper::validateArray($this->postData, array_merge($this->checkArray, ['id' => ['required' => true]])); @@ -249,18 +255,20 @@ class TTCrud extends mfBaseController { } protected function autocompleteAction() { - $searchedID = $this->request->searchedID; - $textKey = property_exists($this->model, 'name') ? 'name' : 'title'; - - if (strlen($searchedID) > 0) { - $filter = ['id' => $searchedID]; + if (strlen($this->request->searchedID) > 0) { + $filter = ['id' => $this->request->searchedID]; $data = $this->model::getAll($filter, 10); } else { - $filter = [$textKey => $this->request->q . '%']; - $data = $this->model::getAll($filter, 10); + if (isset($this->autocompleteColumns) && is_array($this->autocompleteColumns)) { + $filterKey = join('|', $this->autocompleteColumns); + } else { + $filterKey = $textKey; + } + + $data = []; if (count($data) < 11) { - $filter = [$textKey => $this->request->q]; + $filter = [$filterKey => '%' . $this->request->q . '%']; $lazyData = $this->model::getAll($filter, 10); $data = array_merge($data, $lazyData); $data = array_unique($data, SORT_REGULAR); @@ -268,7 +276,6 @@ class TTCrud extends mfBaseController { } } - self::returnJson(array_map(function ($item) use ($textKey) { return ['value' => $item->id, 'text' => $item->$textKey]; }, $data)); @@ -283,6 +290,7 @@ class TTCrud extends mfBaseController { } $data = (array) $this->model::get($id); + if (method_exists($this, 'getByIdParse') && !isset($_GET['disableParse'])) $data = $this->getByIdParse($data); self::returnJson($data); } } diff --git a/lib/TTCrudBaseModel/TTCrudBaseModel.php b/lib/TTCrudBaseModel/TTCrudBaseModel.php index 3184ffa10..4815dde9f 100644 --- a/lib/TTCrudBaseModel/TTCrudBaseModel.php +++ b/lib/TTCrudBaseModel/TTCrudBaseModel.php @@ -81,17 +81,13 @@ class TTCrudBaseModel { } - public static function get($id, $die= false): TTCrudBaseModel { + public static function get($id): TTCrudBaseModel { $FronkDB = FronkDB::singleton(); $db = $FronkDB->link; $id = $db->real_escape_string($id); $table = self::getTable(); $sql = "SELECT * FROM `$table` WHERE `id` = $id"; - if($die) { - die($sql); - } - $result = $db->query($sql); // as TTCRudBaseModel is abstract, we need to get the class name of the child class $class = get_called_class(); @@ -109,16 +105,16 @@ class TTCrudBaseModel { return $result->fetch_assoc()['count']; } - public static function getSQLFilter($filter): string { - if (empty($filter)) { - return ""; - } + public static function getSQLFilter(array $filter): string { + if (empty($filter)) return ''; + $sql = 'WHERE 1=1'; + $calledClass = get_called_class(); - $sql = "WHERE 1=1"; foreach ($filter as $key => $value) { - if (!property_exists(get_called_class(), $key)) { - http_response_code(500); - throw new Exception("Field $key does not exist in " . get_called_class()); + foreach (explode('|', $key) as $column) { + if (!property_exists($calledClass, $column)) { + throw new InvalidArgumentException("Field $column does not exist in $calledClass"); + } } $sql .= Helper::generateFilterCondition($value, $key, gettype($value) === "integer"); } diff --git a/lib/XinonProject/XinonProject.php b/lib/XinonProject/XinonProject.php index 9fdd63394..f32895350 100644 --- a/lib/XinonProject/XinonProject.php +++ b/lib/XinonProject/XinonProject.php @@ -58,14 +58,13 @@ class XinonProject { * @param int $pageSize - The number of results to return. * @return array - The search results. */ - public function searchSupportTickets(string $search, int $pageSize = 25): array { + public function searchSupportTickets(string $search, int $pageSize = 25, $overrideQueryParams = null): array { $curl = curl_init(); $baseUrl = 'https://project.xinon.at/api/v3/projects/10/work_packages'; - $queryParams = [ - 'pageSize' => 25, - 'filters' => json_encode([['search' => ['operator' => '**', 'values' => [$search]]]]) - ]; + $queryParams = ['pageSize' => $pageSize, 'filters' => json_encode([['search' => ['operator' => '**', 'values' => [$search]]]])]; + + if (!is_null($overrideQueryParams)) $queryParams = $overrideQueryParams; curl_setopt_array($curl, array( CURLOPT_URL => $baseUrl . '?' . http_build_query($queryParams), diff --git a/public/bundler.php b/public/bundler.php index 721fb6431..9bd9e99eb 100644 --- a/public/bundler.php +++ b/public/bundler.php @@ -47,6 +47,7 @@ $jsFiles = [ "plugins/vue/tt-components/tt-number-range.js", "plugins/vue/tt-components/tt-checkbox.js", "plugins/vue/tt-components/tt-textarea.js", + "plugins/vue/tt-components/tt-position-manager.js", ]; diff --git a/public/js/pages/AddressTickets/AddressTickets.js b/public/js/pages/AddressTickets/AddressTickets.js new file mode 100644 index 000000000..8103c0a9d --- /dev/null +++ b/public/js/pages/AddressTickets/AddressTickets.js @@ -0,0 +1,55 @@ +Vue.component('AddressTickets', { + template: ` + +
    + + + + + + + + + + + + + + + + + + + +
    KundennummerErstellt amBetreffLetztes UpdateAktion
    {{ ticket.customField7 }}{{ formatDate(ticket.createdAt) }}{{ ticket.subject }}{{ formatDate(ticket.updatedAt) }} + + + Ticket anzeigen + +
    +
    +
    + `, + data() { + return { + window: window, + } + }, + computed: { + parsedTickets() { + return this.window.TT_CONFIG.TICKETS.map(ticket => ({ + id: ticket.id, + customField7: ticket.customField7, + createdAt: ticket.createdAt, + subject: ticket.subject, + updatedAt: ticket.updatedAt, + activitiesHref: ticket._links.activities.href + })); + } + }, + methods: { + formatDate(dateString) { + return this.window.moment(dateString).format('DD.MM.YYYY HH:mm'); + } + } +}); diff --git a/public/js/pages/Calendar/View.js b/public/js/pages/Calendar/View.js index 2d32dc2c7..fe98fbf28 100644 --- a/public/js/pages/Calendar/View.js +++ b/public/js/pages/Calendar/View.js @@ -409,7 +409,11 @@ document.addEventListener('DOMContentLoaded', function () { $('#customer').html(''); } if (data.data.customer_info_reminder.customer_info_reminder) { - $('#customer-info-reminder-check').prop('checked', true); + if (data.data.customer_info_reminder.customer_info_reminder == 1) { + $('#customer-info-reminder-check').prop('checked', true); + } else { + $('#customer-info-reminder-check').prop('checked', false); + } } $('#customer').select2({ placeholder: "Kunden Suche", @@ -454,8 +458,12 @@ document.addEventListener('DOMContentLoaded', function () { } else if (obj.customer_info_type == 2) { typeText = 'SMS'; } + let customer_info_text = ""; + if (obj.customer_info_text) { + customer_info_text = obj.customer_info_text.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1
    $2'); + } let title = `
    Letzte gesendete Info (` + typeText + `):
    -
    ` + obj.customer_info_text.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1
    $2') + `
    +
    ` + customer_info_text + `
    gesendet an: ` + obj.customer_info_type_text + `
    gesendet von: ` + obj.sendby + `
    gesendet am: ` + germanDateTime + `
    @@ -1706,8 +1714,7 @@ $(document).ready(function () { } } }); - } - else if ($(this).val() == "5") { + } else if ($(this).val() == "5") { $('.customer-div').hide(); $('.ticket-div').show(); $('#ticket').select2({ diff --git a/public/js/pages/Device/Device.js b/public/js/pages/Device/Device.js index da6b62c0e..e7758ae00 100644 --- a/public/js/pages/Device/Device.js +++ b/public/js/pages/Device/Device.js @@ -1,41 +1,54 @@ const deviceManufacturerFilterOptions = window?.TT_CONFIG?.DEVICE_MANUFACTURERS.map(manufacturer => ({ value: manufacturer.name, - text: manufacturer.name, + text: manufacturer.name, })); const deviceTypeFilterOptions = window?.TT_CONFIG?.DEVICE_TYPES.map(type => ({ value: type.name, - text: type.name, + text: type.name, })); Vue.component('device-view-switch', { //language=Vue template: ` -
    -
    - - - -
    -
    - -
    -
    - `, - props: ['value'], +
    +
    + + + +
    +
    + +
    +
    + `, + props: ['value'], data() { return { - window: window, + window: window, isOverflowing: false, - showDropdown: false, + showDropdown: false, }; }, mounted() { @@ -53,115 +66,142 @@ Vue.component('device-view-switch', { }) Vue.component('DeviceTable', { - //language=Vue - template: ` - + //language=Vue + template: ` + - + - + - + - + + + + `, data() { - return { - window: window, - DeviceTableConfig: { - key: 'DeviceTable', - tableHeader: 'Device-Liste', - defaultPageSize: 25, - headers: [ - { text: 'Device Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10 }, - { text: 'Hersteller', key: 'devicemanufactor', filter: 'select',class: 'text-nowrap text-center', filterOptions: deviceManufacturerFilterOptions }, - { text: 'Geräte Typ', key: 'devicetype', filter: 'select', class: 'text-nowrap text-center', filterOptions: deviceTypeFilterOptions , priority: 7}, - { text: 'Pop/Adresse', key: 'locationText', filter: 'search' , class: 'text-nowrap text-center'}, - { text: 'IP-Adresse', key: 'ip', filter: 'search',class: 'text-center', priority: 8}, - { text: 'Mac-Adresse', key: 'mac', filter: 'search',class: 'text-center' }, - { text: 'Seriennummer', key: 'serial', filter: 'search',class: 'text-center' }, - { text: 'Preis', key: 'price', filter: 'numberRange',class: 'text-center', suffix: ' €' }, - { text: 'max. Leistung', key: 'power', filter: 'numberRange',class: 'text-center', suffix: ' W' }, - { - text: 'Backup', - key: 'backup', - filter: 'iconSelect', - filterOptions: [ - { value: 'ok', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-check text-success' }, - { value: 'auto', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-a text-success' }, - { value: 'aged', text: 'Letztes Configbackup älter als 48 Stunden', icon: 'fa-regular fa-circle-xmark' }, - { value: 'na', text: 'N/A', icon: 'fa-regular fa-ban text-warning' } - ], - priority: 6, - sortable: false, - }, { - text: 'Status', - key: 'zabbix_online', - filter: 'iconSelect', - filterOptions: [ - { value: 0, text: 'Status unbekannt', icon: 'fa-regular fa-circle-xmark' }, - { value: 1, text: 'Offline', icon: 'fa-regular fa-circle-xmark text-danger' }, - { value: 2, text: 'Online', icon: 'fa-regular fa-circle-check text-success' }, - ], - priority: 5, - sortable: false, - }, - {text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9}, - ], - }, - } + return { + window: window, + DeviceTableConfig: { + key: 'DeviceTable', + tableHeader: 'Device-Liste', + defaultPageSize: 25, + headers: [], + }, + } + }, + mounted() { + this.DeviceTableConfig.headers = [ + {text: 'Device Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10}, + {text: 'Hersteller', key: 'devicemanufactor', filter: 'select', class: 'text-nowrap text-center', filterOptions: deviceManufacturerFilterOptions}, + {text: 'Geräte Typ', key: 'devicetype', filter: 'select', class: 'text-nowrap text-center', filterOptions: deviceTypeFilterOptions, priority: 7}, + {text: 'Pop/Adresse', key: 'locationText', filter: 'search', class: 'text-nowrap text-center'}, + {text: 'IP-Adresse', key: 'ip', filter: 'search', class: 'text-center', priority: 8}, + {text: 'Mac-Adresse', key: 'mac', filter: 'search', class: 'text-center'}, + {text: 'Seriennummer', key: 'serial', filter: 'search', class: 'text-center'}, + ]; + + if (this.window.TT_CONFIG['IS_ADMIN'] === '1') { + this.DeviceTableConfig.headers = [ + ...this.DeviceTableConfig.headers, + {text: 'Preis', key: 'price', filter: 'numberRange', class: 'text-center', suffix: ' €'}, + {text: 'max. Leistung', key: 'power', filter: 'numberRange', class: 'text-center', suffix: ' W'}, + { + text: 'Backup', + key: 'backup', + filter: 'iconSelect', + filterOptions: [ + {value: 'ok', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-check text-success'}, + {value: 'auto', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-a text-success'}, + {value: 'aged', text: 'Letztes Configbackup älter als 48 Stunden', icon: 'fa-regular fa-circle-xmark'}, + {value: 'na', text: 'N/A', icon: 'fa-regular fa-ban text-warning'} + ], + priority: 6, + sortable: false, + }, { + text: 'Status', + key: 'zabbix_online', + filter: 'iconSelect', + filterOptions: [ + {value: 0, text: 'Status unbekannt', icon: 'fa-regular fa-circle-xmark'}, + {value: 1, text: 'Offline', icon: 'fa-regular fa-circle-xmark text-danger'}, + {value: 2, text: 'Online', icon: 'fa-regular fa-circle-check text-success'}, + ], + priority: 5, + sortable: false, + }, + {text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9}, + ] + } + } }); Vue.component('DeviceManufacturer', { //language=Vue template: ` - + - + - + - - `, + + `, data() { return { - window: window, + window: window, DeviceManufacturerConfig: { - key: 'DeviceManufacturer', - tableHeader: 'Hersteller', + key: 'DeviceManufacturer', + tableHeader: 'Hersteller', defaultPageSize: 25, - headers: [ - { text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10 }, - { text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'}, - { text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'}, - { text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9}, + headers: [ + {text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10}, + {text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'}, + {text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'}, + {text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9}, ], }, } @@ -171,36 +211,39 @@ Vue.component('DeviceManufacturer', { Vue.component('DeviceType', { //language=Vue template: ` - - - - - - - - `, + + + + + + + + `, data() { - return { - window: window, + return { + window: window, DeviceTypeConfig: { - key: 'DeviceType', - tableHeader: 'Gerätetypen', + key: 'DeviceType', + tableHeader: 'Gerätetypen', defaultPageSize: 25, - headers: [ - { text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10 }, - { text: 'Hersteller', key: 'manufacturer', filter: 'search', class: 'text-center'}, - { text: 'Preis', key: 'price', filter: 'numberRange', class: 'text-center', suffix: ' €' }, - { text: 'max. Leistung', key: 'power', filter: 'numberRange', class: 'text-center', suffix: ' W' }, - { text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'}, - { text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'}, - { text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9}, + headers: [ + {text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10}, + {text: 'Hersteller', key: 'manufacturer', filter: 'search', class: 'text-center'}, + {text: 'Preis', key: 'price', filter: 'numberRange', class: 'text-center', suffix: ' €'}, + {text: 'max. Leistung', key: 'power', filter: 'numberRange', class: 'text-center', suffix: ' W'}, + {text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'}, + {text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'}, + {text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9}, ], }, } @@ -210,15 +253,15 @@ Vue.component('DeviceType', { Vue.component('Device', { //language=Vue template: ` - - - - - - `, + + + + + + `, data() { return { - window: window, + window: window, currentView: 'DeviceTable', }; }, diff --git a/public/js/pages/Radius/Radius.css b/public/js/pages/Radius/Radius.css index 66f1a5ee1..ac8f00c41 100644 --- a/public/js/pages/Radius/Radius.css +++ b/public/js/pages/Radius/Radius.css @@ -19,7 +19,7 @@ .filters { display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); grid-gap: 15px; margin-bottom: 20px; justify-content: center; diff --git a/public/js/pages/Radius/Radius.js b/public/js/pages/Radius/Radius.js index 182f7a37b..bb57045ca 100644 --- a/public/js/pages/Radius/Radius.js +++ b/public/js/pages/Radius/Radius.js @@ -273,6 +273,45 @@ Vue.component('radius-ont-parser', { } }); +Vue.component('radius-online-state', { + props: ['username'], + template: ` +
    + + +
    + `, + data() { + return { + data: null, + }; + }, + async created() { + await this.fetchOnlineState(); + }, + methods: { + async fetchOnlineState() { + const response = await fetch(window.TT_CONFIG['BASE_PATH'] + '/Radius/proxyUnsecureHTTPRequestToRadius?action2=fetchRadacct&username=' + this.username); + if (response.ok) this.data = await response.json(); + } + } +}) Vue.component('radius', { template: ` @@ -292,6 +331,7 @@ Vue.component('radius', { +
    @@ -301,6 +341,7 @@ Vue.component('radius', { Kundennummer Username Info + Status Aktionen @@ -317,6 +358,11 @@ Vue.component('radius', { {{ user.info }} + + + @@ -419,10 +465,12 @@ Vue.component('radius', { custnum: '', window: window, showRadacctModal: false, + checkOnlineState: 0, radacctData: null, } }, async mounted() { + console.log("hallo"); await this.loadFreeUsers(); }, methods: { @@ -442,7 +490,11 @@ Vue.component('radius', { }); const response = await fetch(`${window.TT_CONFIG['BASE_PATH']}/Radius/proxyUnsecureHTTPRequestToRadius?${params.toString()}`); if (response.ok) { - this.radiusUsers = await response.json(); + const users = await response.json() + if (users.length < 6) { + this.checkOnlineState = 1; + } + this.radiusUsers = users; } else { console.error('Failed to load radius users'); } diff --git a/public/js/pages/WarehouseOffer/WarehouseOffer.css b/public/js/pages/WarehouseOffer/WarehouseOffer.css new file mode 100644 index 000000000..7951745f0 --- /dev/null +++ b/public/js/pages/WarehouseOffer/WarehouseOffer.css @@ -0,0 +1,14 @@ +@media (min-width: 992px) { + .modal-lg, .modal-xl { + /*max width either 90% or 1120px*/ + max-width: min(90vw, 1120px) !important; + } +} + +@media (max-width: 992px) { + .warehouse-order-modal-positions-entry-container { + display: grid; + grid-template-columns: 1fr 1fr !important; + grid-gap: 10px; + } +} \ No newline at end of file diff --git a/public/js/pages/WarehouseOffer/WarehouseOffer.js b/public/js/pages/WarehouseOffer/WarehouseOffer.js new file mode 100644 index 000000000..fe1365051 --- /dev/null +++ b/public/js/pages/WarehouseOffer/WarehouseOffer.js @@ -0,0 +1,178 @@ +Vue.component('warehouse-offer-modal', { + props: { + id: {type: [String, Number], required: true}, + mode: {type: String, default: 'edit'} + }, + template: ` + +

    Angebotdetails

    + + + + +
    +

    Kundenadresse

    +
    + + + + + +
    +
    +

    Positionen

    + +
    +

    Alternative Artikel

    + +
    + + + + +
    + +
    +
    + `, + data() { + return { + window: window, + positionsConfig: { + fields: { + article: { + type: 'autocomplete', + label: 'Artikel', + apiUrl: '/WarehouseArticle/autoComplete', + customFieldReference: 'WarehouseArticle', + }, + amount: {type: 'input', label: 'Menge', inputType: 'number'}, + unit: {type: 'input', label: 'Einheit'}, + articleNumber: {type: 'input', label: 'Artikelnummer'}, + unitPrice: {type: 'input', label: 'Einzelpreis', inputType: 'number'}, + discount: {type: 'input', label: 'Rabatt (%)', inputType: 'number'}, + }, + validateForm: (formData) => { + const requiredFields = ['article', 'amount', 'unitPrice']; + for (const field of requiredFields) { + if (!formData[field]) { + window.notify('error', `Bitte füllen Sie ${this.positionsConfig.fields[field].label} aus`); + return false; + } + } + return true; + }, + }, + alternativePositionsConfig: { + fields: { + article: {type: 'input', label: 'Artikel'}, + description: {type: 'textarea', label: 'Beschreibung'}, + }, + }, + paymentTerms: [ + {value: 'net30', text: '30 Tage netto'}, + {value: 'net60', text: '60 Tage netto'}, + {value: 'immediate', text: 'Sofort fällig'}, + ], + deliveryTerms: [ + {value: 'ex_works', text: 'Ab Werk'}, + {value: 'free_delivery', text: 'Frei Haus'}, + {value: 'fob', text: 'FOB'}, + ], + closingTexts: [ + {value: 'standard', text: 'Standardtext'}, + {value: 'custom1', text: 'Angepasster Text 1'}, + {value: 'custom2', text: 'Angepasster Text 2'}, + ], + offer: { + editor: window.TT_CONFIG['USER_ID'], + customerNumber: '', + reference: '', + purpose: '', + customerName: '', + customerStreet: '', + customerZip: '', + customerCity: '', + customerVAT: '', + positions: [], + alternativePositions: [], + totalDiscount: 0, + paymentTerms: 'net30', + deliveryTerms: 'ex_works', + closingText: 'standard', + notes: '', + } + } + }, + async mounted() { + if (this.id !== 'create') { + const response = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseOffer/getById`, {params: {id: this.id}}); + this.offer = response.data; + this.offer.positions = JSON.parse(this.offer.positions); + this.offer.alternativePositions = JSON.parse(this.offer.alternativePositions); + } + }, + methods: { + async submit() { + if (this.offer.positions.length === 0) return window.notify('error', 'Bitte fügen Sie mindestens eine Position hinzu.'); + + const url = this.id === 'create' + ? `${window.TT_CONFIG["BASE_PATH"]}/WarehouseOffer/create` + : `${window.TT_CONFIG["BASE_PATH"]}/WarehouseOffer/update`; + + const response = await axios.post(url, this.offer); + + if (response.data.success) { + window.notify('success', response.data.message ?? 'Angebot erfolgreich gespeichert'); + this.$emit('close'); + } else { + window.notify('error', + response.data.errors ? Object.values(response.data.errors).join('
    ') : response.data.message || 'Ein Fehler ist aufgetreten'); + } + }, + async fetchArticleData(article) { + if (typeof article === 'number') { + const response = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseArticle/getById`, {params: {id: article}}); + this.$refs.positionsManager.updateField('articleNumber', response.data.articleNumber); + this.$refs.positionsManager.updateField('unitPrice', + Object.values(JSON.parse(response.data.cheapestSellPrice)).find(price => price.title === 'Verkauf').price); + this.$refs.positionsManager.updateField('unit', response.data.unit); + } + }, + }, +}); + +Vue.component('warehouse-offer', { + template: ` + + + + + + + + `, + data() { + return { + window: window, + offerModalId: null, + } + }, +}); diff --git a/public/js/pages/WarehouseOrder/WarehouseOrder.css b/public/js/pages/WarehouseOrder/WarehouseOrder.css new file mode 100644 index 000000000..9b3746d82 --- /dev/null +++ b/public/js/pages/WarehouseOrder/WarehouseOrder.css @@ -0,0 +1,52 @@ +.warehouse-order-modal-positions-entry-container { + display: grid; + grid-template-columns: 2fr 1fr 1fr 0.5fr 1fr 1fr 0.5fr; + grid-gap: 10px; +} + +.warehouse-order-modal-positions-entry-actions { + display: flex; + flex-direction: column; + justify-content: center; + padding-top: 13px; +} + +@media (min-width: 992px) { + .modal-lg, .modal-xl { + /*max width either 90% or 1120px*/ + max-width: min(90vw, 1120px) !important; + } +} + +@media (max-width: 992px) { + .warehouse-order-modal-positions-entry-container { + display: grid; + grid-template-columns: 1fr 1fr !important; + grid-gap: 10px; + } +} + + +/* Expanded Row Styling */ +.order-summary { + padding: 1rem; +} +.position-item { + margin-bottom: 1rem; + border: 1px solid #ddd; + border-radius: 4px; +} +.position-header { + background-color: #f0f0f0; + padding: 0.5rem; + font-weight: bold; +} +.position-details { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr; + padding: 0.5rem; +} +.field-item { + margin-bottom: 0.5rem; +} + diff --git a/public/js/pages/WarehouseOrder/WarehouseOrder.js b/public/js/pages/WarehouseOrder/WarehouseOrder.js index ab63807d5..c9b937d86 100644 --- a/public/js/pages/WarehouseOrder/WarehouseOrder.js +++ b/public/js/pages/WarehouseOrder/WarehouseOrder.js @@ -1,70 +1,246 @@ -// noinspection JSUnusedLocalSymbols -Vue.component('warehouse-order', { +Vue.component('warehouse-order-modal', { + props: { + id: {type: [String, Number], required: true}, + mode: {type: String, default: 'sign'} + }, + template: ` + +
    +

    Bestelldetails

    + + + +
    +

    Positionen

    + + +
    +

    Lieferadresse

    +
    + + + + + +
    + +
    + +
    +
    + `, + + data() { + return { + window: window, + positionsConfig: { + customOrdering: 'distributorId', + fields: { + article: { + type: 'autocomplete', + label: 'Artikel', + apiUrl: '/WarehouseArticle/autoComplete', + customFieldReference: 'WarehouseArticle', + }, + distributorId: {type: 'select', label: 'Lieferant', options: [], customFieldReference: 'WarehouseDistributor'}, + distributorArticleNumber: {type: 'input', label: 'Lieferant Art-Nr.'}, + amount: {type: 'input', label: 'Menge', inputType: 'number'}, + buyPrice: {type: 'input', label: 'Einkaufspreis', inputType: 'number'}, + verwendung: {type: 'input', label: 'Verwendung'}, + }, + validateForm: (formData) => { + const fields = [ + {key: 'amount', message: 'Bitte füllen Sie die Menge aus'}, + {key: 'distributorId', message: 'Bitte füllen Sie den Lieferanten aus'}, + {key: 'article', message: 'Bitte füllen Sie den Artikel aus'}, + {key: 'buyPrice', message: 'Bitte füllen Sie den Einkaufspreis aus'} + ]; + + for (const field of fields) { + if (!formData[field.key]) { + window.notify('error', field.message); + return false; + } + } + + return true; + }, + }, + order: { + extReference: '', + delAddrName: 'XINON GmbH', + delAddrLine: 'Fladnitz im Raabtal 150', + delAddrPLZ: '8322', + delAddrCity: 'Studenzen', + delAddrEMail: 'einkauf@xinon.at', + note: '', + editor: window.TT_CONFIG['USER_ID'], + positions: [], + } + } + }, + async mounted() { + if (this.id === 'create') return; + + console.log(this.id); + + const response = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseOrder/getById?disableParse`, {params: {id: this.id}}); + response.data.positions = JSON.parse(response.data.positions); + this.order = response.data; + }, + methods: { + async submit() { + if (this.order.positions.length === 0) return window.notify('error', 'Bitte fügen Sie mindestens eine Position hinzu.'); + + if (this.id === 'create') { + const distributorIds = [...new Set(this.order.positions.map(position => position.distributorId))]; + + for (const distributorId of distributorIds) { + const response = await axios.post(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseOrder/create`, { + ...this.order, + distributorId, + positions: this.order.positions.filter(position => position.distributorId === distributorId) + } + ); + if (response.data.success) { + this.$emit('close'); + window.notify('success', response.data.message ?? 'Bestellung erfolgreich erstellt'); + } else window.notify('error', + response.data.errors ? Object.values(response.data.errors).join('
    ') : response.data.message || 'Ein Fehler ist aufgetreten'); + } + } else { + const response = await axios.post(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseOrder/update`, this.order); + if (response.data.success) { + this.$emit('close'); + window.notify('success', response.data.message ?? 'Bestellung erfolgreich aktualisiert'); + } else window.notify('error', + response.data.errors ? Object.values(response.data.errors).join('
    ') : response.data.message || 'Ein Fehler ist aufgetreten'); + } + }, + async fetchDistributors(article) { + const url = `${window.TT_CONFIG["BASE_PATH"]}/WarehouseOrder/getArticleDistributorData`; + const params = typeof article === 'string' ? {allDistributor: true} : {articleId: article}; + + const response = await axios.get(url, {params}); + this.positionsConfig.fields.distributorId.options = response.data.map(distributor => ({ + value: distributor.id, + text: distributor.name, + externalArticleNumber: distributor.externalArticleNumber || null, + purchasePrice: distributor.purchasePrice || null, + })); + }, + async fetchDistributorData(distributorId) { + if (distributorId && typeof this.$refs.positionsManager.formData.article === 'number') { + const distributor = this.positionsConfig.fields.distributorId.options.find(distributor => parseInt(distributor.value) === + parseInt(distributorId)); + this.$refs.positionsManager.updateField('distributorArticleNumber', distributor.externalArticleNumber); + this.$refs.positionsManager.updateField('buyPrice', distributor.purchasePrice); + } + }, + }, +}); + +Vue.component('warehouse-order-detail', { //language=Vue template: ` - + - - - - -