diff --git a/Layout/default/Address/Form.php b/Layout/default/Address/Form.php index 907e976e2..392b8550c 100644 --- a/Layout/default/Address/Form.php +++ b/Layout/default/Address/Form.php @@ -472,159 +472,180 @@ var check = parseInt(iban.substr(2, 2)); var account = iban.substr(4); - var searchRange = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(''); - //var replaceRange = []; - var checkStr = account + cc + "00"; - for(var i = 0; i <= 25; i++) { - checkStr = checkStr.replace(searchRange[i], i + 10); - }; - // make checksum - var checksum = parseInt(checkStr.substr(0,1)); - for(pos = 1; pos < checkStr.length; pos++) { - checksum *= 10; - checksum += parseInt(checkStr.substr(pos, 1)); - checksum %= 97; - } - - if(98 - checksum == check) { - return true; - } else { - return false; - } - } - - function validateIbanBic(iban, bic) { - if(!iban) return false; - iban = iban.toUpperCase().replace(/\s+/, ''); - - $.post("", { - do: "validateIbanBic", - iban: iban, - bic: bic - }, - function(success) { - if(success.status == "OK") { - var data = success.result; - $("#bank-error").hide(); - $("#bank-error").text(""); - - if(data.iban_correct && data.bic_correct && (!data.iban_sus || data.iban_sus === "www")) { - bankdata_valid = true; - $('#addressForm').submit(); - return; - } - - var bank_error = []; - - if(!data.iban_correct) { - $("#bank_account_iban").addClass("invalid"); - bank_error.push("Ungültige IBAN!"); - } - if(data.iban_sus && data.iban_sus !== "www") { - $("#bank_account_iban").addClass("invalid"); - bank_error.push("IBAN verdächtig (" + data.iban_sus + ")!"); - } - if(!data.bic_correct) { - $("#bank_account_bic").addClass("invalid"); - bank_error.push("Ungültige BIC!"); - if(Array.isArray(data.bic)) { - bank_error.push(" Mögliche korrekte BIC: " + data.bic.join(", ")); - } - } - - $("#bank-error").html(bank_error.join("
\n")); - $("#bank-error").show(); - $('html, body').animate( {scrollTop: $('#billing-data').offset().top - 230}, 200); - - - - } else { - $("#bank-error").text("Beim Validieren der Bankdaten ist ein Fehler aufgetreten."); + var searchRange = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(''); + //var replaceRange = []; + var checkStr = account + cc + "00"; + for(var i = 0; i <= 25; i++) { + checkStr = checkStr.replace(searchRange[i], i + 10); + }; + // make checksum + var checksum = parseInt(checkStr.substr(0,1)); + for(pos = 1; pos < checkStr.length; pos++) { + checksum *= 10; + checksum += parseInt(checkStr.substr(pos, 1)); + checksum %= 97; } - }, - "json" - ); - - - return false; - } - - $('#addressForm').submit(function(e) { - $("#error").hide(); - $("#bank-error").hide(); - - if($('#billing_type').val() == "sepa") { - console.log("bankdata_valid (1): " + bankdata_valid); - if(bankdata_valid) { - return true; - } - - if(!validateIbanFormat($("#bank_account_iban").val())) { - $("#error").show(); - console.log("nope"); - } - - console.log("bankdata_valid: " + bankdata_valid); - if($("#bank_account_iban").val() != "bank_account_iban?>" || $("#bank_account_bic").val() != "bank_account_bic?>") { - validateIbanBic($("#bank_account_iban").val(), $("#bank_account_bic").val()); - } else { - return true; - } - e.preventDefault(); - return false; + if(98 - checksum == check) { + return true; + } else { + return false; + } } - }); - - - - - - /* - * link autocomplete - */ - - $('.link-autocomplete').autoComplete(); - $('.link-autocomplete').keydown(function() { - if(event.keyCode == 13) { - event.preventDefault(); - return false; - } - }); - /* - * Links autocomplete - */ - $('.link-autocomplete').on("autocomplete.select", function(evt, item) { - autocompleteSelect(evt,item); - }); - - function autocompleteSelect(evt, item) { - if(item && item.value === 0) { - $('.link-autocomplete').autoComplete('set', null); - return; + function validateIbanBic(iban, bic) { + if(!iban) return false; + iban = iban.toUpperCase().replace(/\s+/, ''); + + $.post("", { + do: "validateIbanBic", + iban: iban, + bic: bic + }, + function(success) { + if(success.status == "OK") { + var data = success.result; + $("#bank-error").hide(); + $("#bank-error").text(""); + + if(data.iban_correct && data.bic_correct && (!data.iban_sus || data.iban_sus === "www")) { + bankdata_valid = true; + $('#addressForm').submit(); + return; + } + + var bank_error = []; + + if(!data.iban_correct) { + $("#bank_account_iban").addClass("invalid"); + bank_error.push("Ungültige IBAN!"); + } + if(data.iban_sus && data.iban_sus !== "www") { + $("#bank_account_iban").addClass("invalid"); + bank_error.push("IBAN verdächtig (" + data.iban_sus + ")!"); + } + if(!data.bic_correct) { + $("#bank_account_bic").addClass("invalid"); + bank_error.push("Ungültige BIC!"); + if(Array.isArray(data.bic)) { + bank_error.push(" Mögliche korrekte BIC: " + data.bic.join(", ")); + } + } + + $("#bank-error").html(bank_error.join("
\n")); + $("#bank-error").show(); + $('html, body').animate( {scrollTop: $('#billing-data').offset().top - 230}, 200); + + + + } else { + $("#bank-error").text("Beim Validieren der Bankdaten ist ein Fehler aufgetreten."); + } + }, + "json" + ); + + + return false; } - - var match = evt.currentTarget.id.match(/links_(\d+)_address_id/); - var link_num = match[1]; - if(!link_num) { - console.log("Couldn't find selected Address"); + + function formatIBAN(input) { + let iban = input.value.replace(/\s/g, ''); + + let formattedIBAN = ''; + for (let i = 0; i < iban.length; i++) { + if (i > 0 && i % 4 === 0) { + formattedIBAN += ' '; + } + formattedIBAN += iban[i]; + } + + input.value = formattedIBAN; } - addLink(Number(link_num) + 1); - } - - function addLink(linknum) { - if(!linknum) { - console.log("no linknum"); - return false; + + $("#bank_account_iban").on("input", function () { + formatIBAN(this); + }); + formatIBAN(document.getElementById('bank_account_iban')); + + + $('#addressForm').submit(function(e) { + $("#error").hide(); + $("#bank-error").hide(); + $("#bank_account_iban").val($("#bank_account_iban").val().replaceAll(/\s/g, '')); + + if($('#billing_type').val() == "sepa") { + console.log("bankdata_valid (1): " + bankdata_valid); + if(bankdata_valid) { + return true; + } + + if(!validateIbanFormat($("#bank_account_iban").val())) { + $("#error").show(); + console.log("nope"); + } + + console.log("bankdata_valid: " + bankdata_valid); + if($("#bank_account_iban").val() != "bank_account_iban?>" || $("#bank_account_bic").val() != "bank_account_bic?>") { + validateIbanBic($("#bank_account_iban").val(), $("#bank_account_bic").val()); + } else { + return true; + } + + e.preventDefault(); + return false; + } + }); + + + + + + /* + * link autocomplete + */ + + $('.link-autocomplete').autoComplete(); + $('.link-autocomplete').keydown(function() { + if(event.keyCode == 13) { + event.preventDefault(); + return false; + } + }); + + /* + * Links autocomplete + */ + $('.link-autocomplete').on("autocomplete.select", function(evt, item) { + autocompleteSelect(evt,item); + }); + + function autocompleteSelect(evt, item) { + if(item && item.value === 0) { + $('.link-autocomplete').autoComplete('set', null); + return; + } + + var match = evt.currentTarget.id.match(/links_(\d+)_address_id/); + var link_num = match[1]; + if(!link_num) { + console.log("Couldn't find selected Address"); + } + addLink(Number(link_num) + 1); } - - if($("#links_" + linknum + "_address_id").length) { - console.log("gibs scho"); - return false; - } - - var new_link = ' + + + + + + + + \ No newline at end of file diff --git a/Layout/default/TimerecordingBilling/Index.php b/Layout/default/TimerecordingBilling/Index.php new file mode 100644 index 000000000..a6e85d515 --- /dev/null +++ b/Layout/default/TimerecordingBilling/Index.php @@ -0,0 +1,94 @@ + + + +
+
+
+
+ +
+

Zeiterfassung Verrechnung/Abrechnung

+
+
+
+ + + +
+
+
+
+
+

Liste aller Abrechnungsmonate

+
+
+
+ + + + + + + + + + + + + + + + + closetime; + $closetime = date("d.m.Y H:i", $closetime); + $closer = $timerecordingbillings[ltrim($month, "0")]->creator->name; + $closed = "Ja"; + + } else { + $closetime = ""; + $closer = ""; + $closed = "Nein"; + } + ?> + + + + + + + + +
MonatAbgeschlossenAbgeschlossen amAbgeschlossen von
$month]) ?>"> +
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/Layout/default/TimerecordingCar/Detail.php b/Layout/default/TimerecordingCar/Detail.php new file mode 100644 index 000000000..1c147c8ee --- /dev/null +++ b/Layout/default/TimerecordingCar/Detail.php @@ -0,0 +1,204 @@ +initial_approval); +$initialApprovalMonth = date("m", $timerecordingcar->initial_approval); +$firstApproval = strtotime('+' . $timerecordingcar->first_approval . 'years', strtotime($initialApproval)); +if ($firstApproval < time()) { + $firstApproval = strtotime(date("Y-$initialApprovalMonth-01", time())); + if ($firstApproval < time()) { + $firstApproval = strtotime(date("Y-$initialApprovalMonth-01", strtotime('+1 year'))); + } +} +$approval = date("m/Y", $firstApproval); +?> + + + +
+
+
+
+ +
+

brand . "/" . $timerecordingcar->model . " (" . $timerecordingcar->number_plate . ")" ?> + Detail + + $timerecordingcar->id, 'returnto' => "detail"]) ?>"> + + + +

+
+
+
+ + +
+
+
+
+
+

Fahrzeug Informationen

+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
Markebrand ?>
Model/Typmodel ?>
Erste §57a nachfirst_approval) ? $timerecordingcar->first_approval . " Jahr(en)" : "-" ?>
Fahrzeugverwalteruser_id) ? $timerecordingcar->user->name : "-" ?>
+
+ + +
+
+
+

 

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
Fahrtenbuchtimerecording) ? "Ja" : "Nein" ?>
Erstzulassunginitial_approval) ? date("m/Y", $timerecordingcar->initial_approval) : "-" ?>
Nächste $57ainitial_approval) ? $approval : "-" ?>
Kilometerstandmileage_now) ? $timerecordingcar->mileage_now . " KM" : "-" ?>
+
+ + +
+
+
+
+ + +
+
+
+
+
+

Fahrtenbuch

+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StartkilometerEndkilometerKilometerFahrerDatumZeitOrt
mileage_start ?> KMmileage_end ?> KMmileage_end - $timerecording->mileage_start ?>KM + user->name ?>start) ?>start) . " - " . date("H:i", $timerecording->end) ?>businesstrip_info ?> + + $timerecordingcar->id]) ?> + + + $timerecordingcar->id]) ?> + + +
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/Layout/default/TimerecordingCar/Form.php b/Layout/default/TimerecordingCar/Form.php new file mode 100644 index 000000000..bc8f624f6 --- /dev/null +++ b/Layout/default/TimerecordingCar/Form.php @@ -0,0 +1,169 @@ + $timerecordingcars->id]); +} else { + $cancelUrl = self::getUrl("TimerecordingCar"); +} +foreach ($timerecordingusers as $timerecordinguser) { + $timerecordingUsers[$timerecordinguser->name] = $timerecordinguser->id; +} +ksort($timerecordingUsers); +?> + + +
+
+
+
+ +
+

id) ? "Fahrzeug bearbeiten" : "Neues Fahrzeug" ?>

+
+
+
+ +
+
+ +
+
+

id) ? "Fahrzeug bearbeiten" : "Neues Fahrzeug" ?>

+ +
$_GET["returnto"]]) ?>"> +
+
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ "/> +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ timerecording) ? 'checked="checked"' : '' ?> + type="checkbox" name="timerecording" value="1"/> +
+
+
+
+
+
+ +
+ + + + +
+
+ + +
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/Layout/default/TimerecordingCar/Index.php b/Layout/default/TimerecordingCar/Index.php new file mode 100644 index 000000000..31c0e5bbb --- /dev/null +++ b/Layout/default/TimerecordingCar/Index.php @@ -0,0 +1,123 @@ + + + + +
+
+
+
+ +
+

Fahrzeuge

+
+
+
+ + + +
+
+
+
+
+

Liste aller Fahrzeuge

+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + initial_approval); + $initialApprovalMonth = date("m", $timerecordingcar->initial_approval); + $firstApproval = strtotime('+' . $timerecordingcar->first_approval . 'years', strtotime($initialApproval)); + if ($firstApproval < time()) { + $firstApproval = strtotime(date("Y-$initialApprovalMonth-01", time())); + if ($firstApproval < time()) { + $firstApproval = strtotime(date("Y-$initialApprovalMonth-01", strtotime('+1 year'))); + } + } + $approval = date("m/Y", $firstApproval); + + ?> + + + + + + + + + + + + + +
KennzeichenFahrzeugverwalterMarkeModel/TypErstzulassssung$57aFahrtenbuchKilometerstand
+ $timerecordingcar->id]) ?>"> number_plate ?> + user_id) ? $timerecordingcar->user->name : "-" ?>brand ?>model ?>initial_approval) ? date("m/Y", $timerecordingcar->initial_approval) : "-" ?>initial_approval) ? $approval : "-" ?>timerecording) ? "Ja" : "Nein" ?>mileage_now) ? number_format($timerecordingcar->mileage_now, 0, ',', '.')." KM" : "-" ?> + + $timerecordingcar->id]) ?>"> + $timerecordingcar->id]) ?>" + onclick="if(!confirm('Fahrzeug wirklich löschen?')) return false;" class="text-danger" + title="Löschen"> +
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/Layout/default/TimerecordingCategories/Form.php b/Layout/default/TimerecordingCategories/Form.php index 6e21f051f..96072b0fe 100644 --- a/Layout/default/TimerecordingCategories/Form.php +++ b/Layout/default/TimerecordingCategories/Form.php @@ -93,6 +93,17 @@ +
+ +
+
+ unpaid) echo 'checked="checked"'; ?> + type="checkbox" name="unpaid" value="1"> +
+
+
diff --git a/Layout/default/TimerecordingEmployee/Form.php b/Layout/default/TimerecordingEmployee/Form.php index 7cf2ddf2d..509d4e408 100644 --- a/Layout/default/TimerecordingEmployee/Form.php +++ b/Layout/default/TimerecordingEmployee/Form.php @@ -61,6 +61,17 @@ $daysSelect .= "";
+
+ +
+
+ bmd_active) echo 'checked="checked"'; ?> + type="checkbox" name="bmd_active" value="1"/> +
+
+
@@ -89,6 +100,15 @@ $daysSelect .= ""; value="startdate) ? date('Y-m-d', $timerecordingemployees->startdate): "" ?>"/>
+
+ +
+ "/> +
+
diff --git a/Layout/default/TimerecordingEmployee/Index.php b/Layout/default/TimerecordingEmployee/Index.php index 6aa293165..618fa546c 100644 --- a/Layout/default/TimerecordingEmployee/Index.php +++ b/Layout/default/TimerecordingEmployee/Index.php @@ -9,9 +9,14 @@ $type[3] = "Lehrling"; .border-dark { border-color: #cbcbcb !important; } + .border-bottom { border-bottom: 1px dotted #adadad !important; } + + .inactive_empoyee { + background-color: #ff75756e !important; + }
@@ -52,6 +57,9 @@ $type[3] = "Lehrling"; Sollstunden Mehrstunden Überstunden + superexpertEnabled()): ?> + Black P. Stunden + Offene Urlaube Schnellbuchung @@ -62,6 +70,9 @@ $type[3] = "Lehrling"; + superexpertEnabled()): ?> + + @@ -97,7 +108,7 @@ $type[3] = "Lehrling"; } ?> - + "> name ?> id]['type']] ?> id]['startdate']) ? date("d.m.Y", $timerecordingemployees[$timerecordinguser->id]['startdate']) : "-" ?> @@ -105,8 +116,14 @@ $type[3] = "Lehrling"; - - id]['holidays_now']) ? $timerecordingemployees[$timerecordinguser->id]['holidays_now'] . ' Tage' : '' ?> + + superexpertEnabled()): ?> + id]['bpa_hours'] / 3600), floor($timerecordingemployees[$timerecordinguser->id]['bpa_hours'] / 60 % 60)) ?> + + id]['holidays_now']) ? $timerecordingemployees[$timerecordinguser->id]['holidays_now'] . ' Tage' : '' ?> id]['auto_workinghours'] == '1') ? 'Ja' : 'Nein' ?> $timerecordingemployees[$timerecordinguser->id]['id'], "userid" => $timerecordinguser->id]) ?>"> var hidesearch = [3, 4, 5, 6, 7, 9]; - + superexpertEnabled()): ?> + hidesearch = [3, 4, 5, 6, 7,8 ,10]; + $(document).ready(function () { }); diff --git a/Layout/default/TimerecordingReport/Index.php b/Layout/default/TimerecordingReport/Index.php index 1e782aa51..195fa48a7 100644 --- a/Layout/default/TimerecordingReport/Index.php +++ b/Layout/default/TimerecordingReport/Index.php @@ -121,7 +121,7 @@ $years[time() - 31536000] = date('Y', time() - 31536000);
- +
-
+ + + +
@@ -245,16 +269,17 @@ $years[time() - 31536000] = date('Y', time() - 31536000);
-
-
+
+ +
+
-
-
- + +
@@ -292,7 +317,7 @@ $years[time() - 31536000] = date('Y', time() - 31536000);
diff --git a/Layout/default/VoiceCallActive/Index.php b/Layout/default/VoiceCallActive/Index.php new file mode 100644 index 000000000..c6049f561 --- /dev/null +++ b/Layout/default/VoiceCallActive/Index.php @@ -0,0 +1,160 @@ + self::getUrl("VoiceCallActive"), + "DASHBOARD_URL" => self::getUrl("Dashboard"), + "MFAPPNAME" => MFAPPNAME_SLUG, + "PAGE_TITLE" => "Active Voice Calls", + "PATH" => [ + ["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")], + ["text" => "Active Voice Calls", "href" => self::getUrl("VoiceCallActive")] + ], + "VOICE_CALL_ACTIVE_API_URL" => self::getUrl("VoiceCallActive/api"), +]; + +$additionalJS = ["plugins/vue/vue.js", + "plugins/axios/axios.min.js", + "plugins/vue/tt-components/tt-page-title.js", + "plugins/vue/tt-components/tt-table.js", +]; +$additionalCSS = [ + 'plugins/vue/tt-components/css/tt-table.css', +]; + +include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/header.php"); ?> + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + diff --git a/Layout/default/VoiceCallHistory/Index.php b/Layout/default/VoiceCallHistory/Index.php new file mode 100644 index 000000000..44d205a23 --- /dev/null +++ b/Layout/default/VoiceCallHistory/Index.php @@ -0,0 +1,89 @@ + self::getUrl("Domain"), + "DASHBOARD_URL" => self::getUrl("Dashboard"), + "MFAPPNAME" => MFAPPNAME_SLUG, + "PAGE_TITLE" => "Domains", + "PATH" => [ + ["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")], + ["text" => "Voice Calls History", "href" => self::getUrl("VoiceCallHistory")] + ], + "VOICE_CALL_HISTORY_API_URL" => self::getUrl("VoiceCallHistory/api"), +]; + +$additionalJS = ["plugins/vue/vue.js", + "plugins/axios/axios.min.js", + "plugins/vue/tt-components/tt-page-title.js", + "plugins/vue/tt-components/tt-table.js", +]; +$additionalCSS = [ + 'plugins/vue/tt-components/css/tt-table.css', +]; + +include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/header.php"); ?> + +
+ + + + + +
+ + + + + + + + + + + diff --git a/Layout/default/menu.php b/Layout/default/menu.php index eb9cd226f..19efe9e0a 100644 --- a/Layout/default/menu.php +++ b/Layout/default/menu.php @@ -40,9 +40,11 @@ can('Fibu')): ?>
  • "> Freigaben
  • "> Auswertung/Korrektur
  • +
  • "> Verrechnung
  • "> Buchungsarten
  • "> Feiertage
  • "> Personaladministration
  • +
  • "> Fahrzeugverwaltung
  • @@ -75,6 +77,7 @@ is(["Admin"])): ?>
  • "> Open Access IDs
  • "> Technologien
  • +
  • "> Historische Tickets
  • can("Fibu")): ?>
  • "> Steuersätze
  • @@ -95,6 +98,9 @@ is(["Admin","netowner","lineplanner","lineworker"]) && $me->can("Linework")): ?>
  • "> Leitungsbau
  • is(["Admin","netowner","netoperator","lineworker"]) && $me->can("Patching")): ?>
  • "> Patchungen
  • is(["Admin","netowner","pipeplanner","lineplanner","pipeworker","netoperator","lineworker"]) && $me->can("Filestore")): ?>
  • "> Dateiablage
  • + is(["Admin","netowner","pipeplanner","pipeplanner"]) && $me->is("employee")): ?>
  • "> Verteiler und Schächte
  • + is(["Admin","netowner","lineplanner","lineworker"]) && $me->is("employee")): ?>
  • "> Rohrverzeichnis
  • +is(["Admin","netowner","lineplanner","lineworker"]) && $me->is("employee")): ?> @@ -107,6 +113,7 @@ @@ -117,8 +124,10 @@ Telefonie
    @@ -163,4 +172,4 @@
    - \ No newline at end of file + diff --git a/application/Device/DeviceController.php b/application/Device/DeviceController.php index 35b43e57f..f5d8e5ae5 100644 --- a/application/Device/DeviceController.php +++ b/application/Device/DeviceController.php @@ -43,6 +43,7 @@ class DeviceController extends mfBaseController $this->layout()->setTemplate("Device/Detail"); $devicesconfig = DeviceModel::getconifg($id); $devices = DeviceModel::getOne($id); + $devicesall= DeviceModel::getAll(); if ($devices->devicetype->olt == "1") { $customer = DeviceModel::getOltCustomer($device->ip); @@ -52,6 +53,7 @@ class DeviceController extends mfBaseController $this->layout()->set("devicesconfig", $devicesconfig); $this->layout()->set("devices", $devices); + $this->layout()->set("devicesall", $devicesall); $this->layout()->set("customer", $customer); } @@ -61,6 +63,7 @@ class DeviceController extends mfBaseController $this->layout()->setTemplate("Device/Form"); $this->layout()->set("devicetypes", DevicetypeModel::getAll()); $this->layout()->set("pops", PopModel::getAll()); + $this->layout()->set("devices", DeviceModel::getAll()); } @@ -102,6 +105,7 @@ class DeviceController extends mfBaseController $data = []; $data['name'] = trim($r->name); $data['devicetype_id'] = $r->devicetype_id; + $data['parent_id'] = $r->parent_id; $data['autobackup'] = trim($r->autobackup); if (trim($r->pop_id) == "0") { @@ -132,6 +136,9 @@ class DeviceController extends mfBaseController if ($data['autobackup'] != "1") { $data['autobackup'] = "0"; } + if (!$data['parent_id']) { + $data['parent_id'] = NULL; + } $data['ip'] = $r->ip; $data['mac'] = $r->mac; $data['serial'] = $r->serial; diff --git a/application/Device/DeviceModel.php b/application/Device/DeviceModel.php index 05a0d9bb6..feae145ed 100644 --- a/application/Device/DeviceModel.php +++ b/application/Device/DeviceModel.php @@ -8,6 +8,7 @@ class DeviceModel public $serial = null; public $comment = null; public $devicetype_id = null; + public $parent_id = null; public $pop_id = null; public $addr_street = null; public $addr_number = null; diff --git a/application/Domain/Domain.php b/application/Domain/Domain.php new file mode 100644 index 000000000..bff2e8496 --- /dev/null +++ b/application/Domain/Domain.php @@ -0,0 +1,9 @@ +loadMe(); + $this->layout()->set("me", $me); + $this->me = $me; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + $this->inwx = new Inwx($this->INWX_USER, $this->INWX_PASS); + $this->plesk = new Plesk($this->PLESK_USER, $this->PLESK_AUTH); + } + + protected function indexAction(): void { + $this->layout()->setTemplate("Domain/Index"); + } + + protected function apiAction() { + $do = $this->request->do; + + if ($do !== "getConfig" && !$this->me->is("employee")) { + $this->redirect("dashboard"); + } + switch ($do) { + case "importAllDomains": + $return = $this->importAllDomains(); + break; + case "getDomains": + $return = $this->getAllDomains(); + break; + case "getDomainContacts": + $return = $this->getDomainContacts(); + break; + case "getDnsRecords": + $return = $this->getDnsRecords(); + break; + case "checkDomain": + $return = $this->checkDomain(); + break; + default: + $return = false; + break; + } + + if (!$return) { + $return = [ + "status" => "error", + "message" => "Invalid request." + ]; + } + + die(json_encode($return)); + } + + protected function importDomain(): void { + // use plesk api to get all domains + + + } + + protected function importAllDomains(): array { + + try { + $inwxContact = $this->inwx->contactList(); + $pleskDomains = $this->plesk->getAllDomains(); + $inwxDomains = $this->inwx->domainList(); + + $domains = []; + $pleskDomainsArray = []; + + foreach ($pleskDomains as $pleskDomain) { + $pleskDomainsArray[$pleskDomain['name']] = $pleskDomain; + } + + foreach ($inwxDomains as $inwxDomain) { + if (isset($pleskDomainsArray[$inwxDomain['domain']])) { + $inwxDomain['plesk'] = [ + "id" => $pleskDomainsArray[$inwxDomain['domain']]['id'], + "hosting_type" => $pleskDomainsArray[$inwxDomain['domain']]['hosting_type'], + "created" => strtotime($pleskDomainsArray[$inwxDomain['domain']]['created']) + ]; + } + + $domains[] = $inwxDomain; + } + + $domainsImport = DomainModel::importDomains($domains); + $contactsImport = DomainContactModel::importDomainContacts($inwxContact); + + return [ + "status" => "success", + "importMessages" => [ + $domainsImport['message'], + $contactsImport['message'] + ], + ]; + } catch (Exception $e) { + $this->log->error("Error while importing domains: " . $e->getMessage()); + return [ + "status" => "error", + "message" => "Error while importing domains: " . $e->getMessage() + ]; + } + + } + + private function getAllDomains(): array { + + $json = json_decode(file_get_contents('php://input'), true); + + $filters = $json['filters'] ?? []; + $page = $json['pagination']['page'] ?? 1; + $perPage = $json['pagination']['per_page'] ?? 10; + + $domains = DomainModel::getAllDomains($filters, $perPage, $perPage * $page - $perPage); + $totalRows = DomainModel::countDomains($filters); + + return [ + "rows" => $domains, + "pagination" => [ + "page" => $page, + "total_pages" => ceil($totalRows / $perPage), + "per_page" => $perPage, + "total_rows" => intval($totalRows) + ] + ]; + + } + + private function getDnsRecords() { + if (!empty($this->request->domain)) { + return ["status" => "error", "message" => "No domain specified."]; + } + + $domain = $this->request->domain; + return array_merge( + dns_get_record($domain, DNS_TXT), + dns_get_record($domain, DNS_A), + dns_get_record($domain, DNS_CNAME), + dns_get_record($domain, DNS_MX), + dns_get_record($domain, DNS_NS), + dns_get_record($domain, DNS_SOA), + dns_get_record($domain, DNS_SRV), + dns_get_record($domain, DNS_AAAA), + + ); + } + + private function getDomainContacts(): array { + $domainContacts = []; + $dbDomainContacts = DomainContactModel::getAllDomainContacts(); + + foreach ($dbDomainContacts as $dbDomainContact) { + $domainContacts[$dbDomainContact['inwxRoId']] = $dbDomainContact; + } + + return $domainContacts; + } + + private function checkDomain(): array { + $domain = $this->request->domain; + + if(empty($domain)) { + return ["status" => "error", "message" => "No domain or tld specified."]; + } + + try { + $domainCheck = $this->inwx->domainCheck($domain); + + if($domainCheck['domain'][0]['status'] === "free") { + $domainPrice = $this->inwx->domainGetDomainPrice($domain, "reg"); + } else { + $domainPrice = $this->inwx->domainGetDomainPrice($domain, "transfer"); + } + + $domainCheck['domain'][0]['price'] = $domainPrice; + + return $domainCheck['domain'][0]; + } catch (Exception $e) { + $this->log->error("Error while checking domain: " . $e->getMessage()); + return ["status" => "error", "message" => "Error while checking domain: " . $e->getMessage()]; + } + } + + +} \ No newline at end of file diff --git a/application/Domain/DomainModel.php b/application/Domain/DomainModel.php new file mode 100644 index 000000000..47c5b330f --- /dev/null +++ b/application/Domain/DomainModel.php @@ -0,0 +1,133 @@ + $value) { + if (property_exists(get_called_class(), $field)) { + $this->$field = $value; + } + } + } + + public static function importDomains($domains): array { + $db = FronkDB::singleton(); + + $db->query("TRUNCATE TABLE `Domain`"); + + $sql = /** @lang text */ + "INSERT INTO `Domain` (`inwxRoId`, `domain`, `period`, `crDate`, `exDate`, `reDate`, `upDate`, `transferLock`, `status`, `authCode`, `registrant`, `admin`, `tech`, `billing`, `ns`, `pleskId`, `pleskHostingType`, `pleskCreated`) VALUES "; + $values = []; + foreach ($domains as $domain) { + $valueStr = "(" . + $domain['roId'] . ", '" . + $domain['domain'] . "', '" . + $domain['period'] . "', " . + $domain['crDate']['timestamp'] . ", " . + (isset($domain['reDate']) ? $domain['reDate']['timestamp'] : "NULL") . ", " . + (isset($domain['reDate']) ? $domain['reDate']['timestamp'] : "NULL") . ", " . + $domain['upDate']['timestamp'] . ", " . + ($domain['transferLock'] ? 1 : 0) . ", '" . + $domain['status'] . "', '" . + $domain['authCode'] . "', " . + $domain['registrant'] . ", " . + $domain['admin'] . ", " . + $domain['tech'] . ", " . + $domain['billing'] . ", '" . + implode(", ", $domain['ns']) . "', "; + + // Check if 'pleskId' is set + if (isset($domain['plesk']) && is_array($domain['plesk'])) { + $valueStr .= $domain['plesk']['id'] . ", "; + $valueStr .= "'" . $domain['plesk']['hosting_type'] . "', "; + $valueStr .= $domain['plesk']['created']; + } else { + $valueStr .= "NULL, NULL, NULL"; + } + + $values[] = $valueStr . ")"; + } + $sql .= implode(", ", $values); + $db->query($sql); + return [ + "message" => "Imported " . count($domains) . " domains." + ]; + } + + /** + * Generate SQL Filter condition (space separated) for a given column. + * + * @param string|null $filterValue The filter value to match against. + * @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(?string $filterValue, string $columnName): string { + $sql = ""; + if (!empty($filterValue)) { + $filterItems = explode(" ", $filterValue); + foreach ($filterItems as $item) { + $sql .= " AND `$columnName` LIKE '%" . $item . "%'"; + } + } + + return $sql; + } + + public static function getSqlFilter($filters): string { + $sql = isset($filters['domain']) ? self::generateFilterCondition($filters['domain'], "domain") : ""; + $sql .= isset($filters['crDate']) ? " AND `crDate` = " . $filters['crDate'] : ""; + $sql .= isset($filters['exDate']) ? " AND `exDate` = " . $filters['exDate'] : ""; + $sql .= isset($filters['reDate']) ? " AND `reDate` = " . $filters['reDate'] : ""; + $sql .= isset($filters['upDate']) ? " AND `upDate` = " . $filters['upDate'] : ""; + $sql .= isset($filters['status']) ? " AND `status` = '" . $filters['status'] . "'" : ""; + $sql .= isset($filters['transferLock']) && $filters['transferLock'] == 1 ? " AND `transferLock` = true" : ""; + $sql .= isset($filters['authCode']) ? self::generateFilterCondition($filters['authCode'], "authCode") : ""; + $sql .= isset($filters['registrant']) && $filters['registrant'] !== 'all' ? " AND `registrant` = " . $filters['registrant'] : ""; + $sql .= isset($filters['admin']) && $filters['admin'] !== 'all' ? " AND `admin` = " . $filters['admin'] : ""; + $sql .= isset($filters['tech']) && $filters['tech'] !== 'all' ? " AND `tech` = " . $filters['tech'] : ""; + $sql .= isset($filters['billing']) && $filters['billing'] !== 'all' ? " AND `billing` = " . $filters['billing'] : ""; + $sql .= isset($filters['ns']) ? self::generateFilterCondition($filters['ns'], "ns") : ""; + return $sql; + + } + + public static function getAllDomains($filters, $limit = null, $offset = 0): array { + $db = FronkDB::singleton(); + $sql = "SELECT * FROM `Domain` WHERE 1 " . self::getSqlFilter($filters); + $sql .= $limit === null ? "" : " LIMIT " . $limit . " OFFSET " . $offset; + + $result = $db->query($sql); + $rows = []; + while ($row = $result->fetch_assoc()) { + $rows[] = new DomainModel($row); + } + + return $rows; + } + + public static function countDomains($filters) { + $db = FronkDB::singleton(); + $sql = "SELECT COUNT(*) as `total_rows` FROM `Domain` WHERE 1 " . self::getSqlFilter($filters); + $result = $db->query($sql); + return $result->fetch_assoc()['total_rows']; + } +} \ No newline at end of file diff --git a/application/DomainContact/DomainContact.php b/application/DomainContact/DomainContact.php new file mode 100644 index 000000000..19f738f64 --- /dev/null +++ b/application/DomainContact/DomainContact.php @@ -0,0 +1,8 @@ + $value) { + if (property_exists(get_called_class(), $field)) { + $this->$field = $value; + } + } + } + + public static function importDomainContacts($domainContacts): array { + $db = FronkDB::singleton(); + + $db->query("TRUNCATE TABLE `DomainContact`"); + + $sql = /** @lang text */ + "INSERT INTO `DomainContact` (`inwxRoId`, `type`, `name`, `street`, `city`, `pc`, `cc`, `voice`, `email`, `protection`, `verificationStatus`, `usedCount`) VALUES "; + $values = []; + + foreach ($domainContacts as $domainContact) { + $valueStr = "(" . + $domainContact['roId'] . ", '" . + $domainContact['type'] . "', '" . + $domainContact['name'] . "', '" . + $domainContact['street'] . "', '" . + $domainContact['city'] . "', '" . + $domainContact['pc'] . "', '" . + $domainContact['cc'] . "', '" . + $domainContact['voice'] . "', '" . + $domainContact['email'] . "', " . + ($domainContact['protection'] ? 1 : 0) . ", '" . + $domainContact['verificationStatus'] . "', "; + + $valueStr .= $domainContact['usedCount'] ?? "NULL"; + $valueStr .= ")"; + + $values[] = $valueStr; + } + + $sql .= implode(", ", $values); + $db->query($sql); + return [ + "message" => "Imported " . count($domainContacts) . " domain contacts." + ]; + } + + /** + * Generate SQL Filter condition (space separated) for a given column. + * + * @param string|null $filterValue The filter value to match against. + * @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(?string $filterValue, string $columnName): string { + $sql = ""; + if (!empty($filterValue)) { + $filterItems = explode(" ", $filterValue); + foreach ($filterItems as $item) { + $sql .= " AND `$columnName` LIKE '%" . $item . "%'"; + } + } + + return $sql; + } + + public static function getSqlFilter($filters): string { + $sql = isset($filters['roId']) ? " AND `inwxRoId` = " . $filters['roId'] : ""; + $sql .= isset($filters['type']) ? " AND `type` = '" . $filters['type'] . "'" : ""; + $sql .= isset($filters['name']) ? self::generateFilterCondition($filters['name'], "name") : ""; + $sql .= isset($filters['street']) ? self::generateFilterCondition($filters['street'], "street") : ""; + $sql .= isset($filters['city']) ? self::generateFilterCondition($filters['city'], "city") : ""; + $sql .= isset($filters['pc']) ? " AND `pc` = " . $filters['pc'] : ""; + $sql .= isset($filters['cc']) ? " AND `cc` = " . $filters['cc'] : ""; + $sql .= isset($filters['voice']) ? " AND `voice` = " . $filters['voice'] : ""; + $sql .= isset($filters['email']) ? self::generateFilterCondition($filters['email'], "email") : ""; + $sql .= isset($filters['protection']) ? " AND `protection` = " . $filters['protection'] : ""; + $sql .= isset($filters['usedCount']) ? " AND `usedCount` = " . $filters['usedCount'] : ""; + $sql .= isset($filters['verificationStatus']) ? " AND `verificationStatus` = '" . $filters['verificationStatus'] . "'" : ""; + return $sql; + + } + + public static function getAllDomainContacts($filters = null, $limit = null, $offset = 0, $raw_array = true): array { + $db = FronkDB::singleton(); + $sql = "SELECT * FROM `DomainContact` WHERE 1 "; + $sql .= $filters === null ? "" : self::getSqlFilter($filters); + $sql .= $limit === null ? "" : " LIMIT " . $limit . " OFFSET " . $offset; + + $result = $db->query($sql); + $rows = []; + while ($row = $result->fetch_assoc()) { + $rows[] = $raw_array ? $row : new DomainContactModel($row); + } + + return $rows; + } + + public static function countDomainContacts($filters) { + $db = FronkDB::singleton(); + $sql = "SELECT COUNT(*) as `total_rows` FROM `DomainContact` WHERE 1 " . self::getSqlFilter($filters); + $result = $db->query($sql); + return $result->fetch_assoc()['total_rows']; + } +} \ No newline at end of file diff --git a/application/FiberPlanDispatcher/FiberPlanDispatcher.php b/application/FiberPlanDispatcher/FiberPlanDispatcher.php new file mode 100644 index 000000000..2df4ff4b9 --- /dev/null +++ b/application/FiberPlanDispatcher/FiberPlanDispatcher.php @@ -0,0 +1,59 @@ +$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/FiberPlanDispatcher/FiberPlanDispatcherController.php b/application/FiberPlanDispatcher/FiberPlanDispatcherController.php new file mode 100644 index 000000000..acf22c583 --- /dev/null +++ b/application/FiberPlanDispatcher/FiberPlanDispatcherController.php @@ -0,0 +1,182 @@ +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("FiberPlanDispatcher/Index"); + $fiberplandispatchers = FiberPlanDispatcherModel::getAll(); + $this->layout()->set("fiberplandispatchers", $fiberplandispatchers); + + } + + protected function addAction() + { + $this->layout()->setTemplate("FiberPlanDispatcher/Form"); + $networks = NetworkModel::getAll(); + $this->layout()->set("networks", $networks); + $networkaddresses = NetworkAddressModel::getAll(); + $this->layout()->set("networkaddresses", $networkaddresses); + + } + + protected function editAction() + { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("Verteiler/Schacht nicht gefunden", "error"); + $this->redirect("FiberPlanDispatcher"); + } + + $fiberplandispatchers = new FiberPlanDispatcher($id); + if ($fiberplandispatchers->id != $id) { + $this->layout()->setFlash("Verteiler/Schacht nicht gefunden", "error"); + $this->redirect("FiberPlanDispatcher"); + } + + $this->layout()->set("fiberplandispatchers", $fiberplandispatchers); + if ($fiberplandispatchers->object_type == "2") { + $sleeves = FiberPlanDispatchersleeveModel::getAllbyDispatcher($id); + $this->layout()->set("sleeves", $sleeves); + } + + 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"; + $fiberplandispatcher = new FiberPlanDispatcher($id); + if (!$fiberplandispatcher->id) { + $this->layout()->setFlash("Verteiler/Schacht nicht gefunden", "error"); + $this->redirect("FiberPlanDispatcher"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['network_id'] = trim($r->network_id); + $data['object_type'] = trim($r->object_type); + $data['description'] = trim($r->description); + if ($r->type) { + $data['type'] = trim($r->type); + } + if ($r->gps_lat) { + $data['gps_lat'] = trim($r->gps_lat); + } + if ($r->gps_long) { + $data['gps_long'] = trim($r->gps_long); + } + if ($r->comment) { + $data['comment'] = trim($r->comment); + } + + if (!$data['network_id']) { + $this->layout()->setFlash("Netzgebiet darf nicht leer sein", "error"); + $this->redirect("FiberPlanDispatcher"); + } + if (!$data['object_type']) { + $this->layout()->setFlash("Objekt Typ darf nicht leer sein", "error"); + $this->redirect("FiberPlanDispatcher"); + } + if (!$data['description']) { + $this->layout()->setFlash("Beschreibung darf nicht leer sein", "error"); + $this->redirect("FiberPlanDispatcher"); + } + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $fiberplandispatcher->update($data); + + } else { + $fiberplandispatcher = FiberPlanDispatcherModel::create($data); + + } +// var_dump($filestore); +// exit; + $id = $fiberplandispatcher->save(); + if ($mode == "edit") { + if ($data['object_type'] == "2") { + FiberPlanDispatchersleeveModel::deletebyDispatcher($id); + $sleeves = $r->sleeves; + $sleevedata = []; + if (is_array($sleeves)) { + foreach ($sleeves as $sleeve) { + $sleevedata['name'] = trim($sleeve); + $sleevedata['fiberPlanDispatcher_id'] = $id; + $fiberplandispatchersleeve = FiberPlanDispatchersleeveModel::create($sleevedata); + $fiberplandispatchersleeve->save(); + } + } + + } + } else { + if ($data['object_type'] == "2") { + $sleeves = $r->sleeves; + $sleevedata = []; + + if (is_array($sleeves)) { + foreach ($sleeves as $sleeve) { + $sleevedata['name'] = trim($sleeve); + $sleevedata['fiberPlanDispatcher_id'] = $id; + $fiberplandispatchersleeve = FiberPlanDispatchersleeveModel::create($sleevedata); + $fiberplandispatchersleeve->save(); + } + } + + } + } + + if (!$id) { + $this->layout()->setFlash("Verteiler/Schacht konnte nicht angelegt werden", "error"); + $this->redirect("FiberPlanDispatcher"); + } + + if ($mode == "edit") { + $this->layout()->setFlash("Verteiler/Schacht erfolgreich geändert", "success"); + } else if ($mode = "add") { + $this->layout()->setFlash("Verteiler/Schacht erfolgreich angelegt", "success"); + } + $this->redirect("FiberPlanDispatcher"); + } + + + protected function deleteAction() + { + $id = $this->request->id; + $fiberplandispatcher = new FiberPlanDispatcher($id); + if (!$fiberplandispatcher->id || $fiberplandispatcher->id != $id) { + $this->layout()->setFlash("Verteiler/Schacht nicht gefunden.", "error"); + $this->redirect("FiberPlanDispatcher"); + } + + $fiberplandispatcher->delete(); + $this->redirect("FiberPlanDispatcher"); + } + +} \ No newline at end of file diff --git a/application/FiberPlanDispatcher/FiberPlanDispatcherModel.php b/application/FiberPlanDispatcher/FiberPlanDispatcherModel.php new file mode 100644 index 000000000..c3cef2a10 --- /dev/null +++ b/application/FiberPlanDispatcher/FiberPlanDispatcherModel.php @@ -0,0 +1,137 @@ + $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("Devicetype", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new Devicetype($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("FiberPlanDispatcher", "*", "1=1 ORDER BY network_id"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanDispatcher($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("Devicetype", "*", "$where ORDER BY name, network_id"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new Devicetype($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("Devicetype", "*", "$where ORDER BY name, network_id"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new Devicetype($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("network_id", $filter)) { + $networkid = $filter['network_id']; + if (is_numeric($networkid)) { + $where .= " AND network_id=$networkid"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeve.php b/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeve.php new file mode 100644 index 000000000..e9cd1f7c4 --- /dev/null +++ b/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeve.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/FiberPlanDispatchersleeve/FiberPlanDispatchersleeveController.php b/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeveController.php new file mode 100644 index 000000000..98e93e443 --- /dev/null +++ b/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeveController.php @@ -0,0 +1,127 @@ +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("FiberPlanDispatchersleeve/Index"); + $fiberplandispatchersleeves = FiberPlanDispatchersleeveModel::getAll(); + $this->layout()->set("fiberplandispatchersleeves", $fiberplandispatchersleeves); + + } + + protected function addAction() + { + $fiberPlanDispatchers=FiberPlanDispatcherModel::getAll(); + $this->layout()->set("fiberPlanDispatchers", $fiberPlanDispatchers); + + $this->layout()->setTemplate("FiberPlanDispatchersleeve/Form"); + + } + + protected function editAction() + { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("Muffen nicht gefunden", "error"); + $this->redirect("FiberPlanDispatchersleeve"); + } + + $fiberplandispatchersleeves = new FiberPlanDispatchersleeve($id); + if ($fiberplandispatchersleeves->id != $id) { + $this->layout()->setFlash("Muffen nicht gefunden", "error"); + $this->redirect("FiberPlanDispatchersleeve"); + } + + $this->layout()->set("fiberplandispatchersleeves", $fiberplandispatchersleeves); + 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"; + $fiberplandispatchersleeves = new FiberPlanDispatchersleeve($id); + if (!$fiberplandispatchersleeves->id) { + $this->layout()->setFlash("Muffe nicht gefunden", "error"); + $this->redirect("FiberPlanDispatchersleeve"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['fiberPlanDispatcher_id'] = trim($r->fiberPlanDispatcher_id); + $data['name'] = trim($r->name); + + + if (!$data['fiberPlanDispatcher_id']) { + $data['fiberPlanDispatcher_id']=NULL; + } + if (!$data['name']) { + $data['name']=NULL; + } + + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $fiberplandispatchersleeves->update($data); + + } else { + $fiberplandispatchersleeves = FiberPlanDispatchersleeveModel::create($data); + } +// var_dump($filestore); +// exit; + $id = $fiberplandispatchersleeves->save(); + + if (!$id) { + $this->layout()->setFlash("Muffen konnte nicht angelegt werden", "error"); + $this->redirect("FiberPlanDispatchersleeve"); + } + + if ($mode == "edit") { + $this->layout()->setFlash("Muffen erfolgreich geändert", "success"); + } else if ($mode = "add") { + $this->layout()->setFlash("Muffen erfolgreich angelegt", "success"); + } + $this->redirect("FiberPlanDispatchersleeve"); + } + + + protected function deleteAction() + { + $id = $this->request->id; + $fiberplandispatchersleeves = new FiberPlanDispatchersleeve($id); + if (!$fiberplandispatchersleeves->id || $fiberplandispatchersleeves->id != $id) { + $this->layout()->setFlash("Muffen nicht gefunden.", "error"); + $this->redirect("FiberPlanDispatchersleeve"); + } + + $fiberplandispatchersleeves->delete(); + $this->redirect("FiberPlanDispatchersleeve"); + } + +} diff --git a/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeveModel.php b/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeveModel.php new file mode 100644 index 000000000..f24f5f701 --- /dev/null +++ b/application/FiberPlanDispatchersleeve/FiberPlanDispatchersleeveModel.php @@ -0,0 +1,153 @@ + $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("FiberPlanDispatchersleeve", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanDispatchersleeve($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("FiberPlanDispatchersleeve", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanDispatchersleeve($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("FiberPlanDispatchersleeve", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanDispatchersleeve($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("FiberPlanDispatchersleeve", "*", "$where"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanDispatchersleeve($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("network_id", $filter)) { + $networkid = $filter['network_id']; + if (is_numeric($networkid)) { + $where .= " AND network_id=$networkid"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + + public static function getAllbyDispatcher($dispatcher_id) + { + $items = []; + + $db = FronkDB::singleton(); + $sql = "SELECT `id`, `fiberPlanDispatcher_id`, `name` FROM `FiberPlanDispatchersleeve` + WHERE `fiberPlanDispatcher_id`='" . $dispatcher_id . "'"; + + $res = $db->query($sql); + if ($db->num_rows($res)) { + $oldrackid = ""; + $counter = -1; + while ($data = $db->fetch_array($res)) { + $items[] = $data; + } + return $items; + } + } + + public static function deletebyDispatcher($dispatcher_id) + { + $db = FronkDB::singleton(); + $sql = "DELETE FROM `FiberPlanDispatchersleeve` WHERE `fiberPlanDispatcher_id`='" . $dispatcher_id . "'"; + $db->query($sql); + } + + +} diff --git a/application/FiberPlanPipe/FiberPlanPipe.php b/application/FiberPlanPipe/FiberPlanPipe.php new file mode 100644 index 000000000..8aefdd859 --- /dev/null +++ b/application/FiberPlanPipe/FiberPlanPipe.php @@ -0,0 +1,62 @@ +$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/FiberPlanPipe/FiberPlanPipeController.php b/application/FiberPlanPipe/FiberPlanPipeController.php new file mode 100644 index 000000000..e6bcd569a --- /dev/null +++ b/application/FiberPlanPipe/FiberPlanPipeController.php @@ -0,0 +1,281 @@ +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() + { + $networks = NetworkModel::getAll(); + $this->layout()->setTemplate("FiberPlanPipe/Index"); + $fiberplanpipes = FiberPlanPipeModel::getAll(); + $pipworkeraddresses = FiberPlanPipeModel::getPipeworkerAddresses(); + $buildings = FiberPlanPipeModel::getBuildingInfoAll(); + $this->layout()->set("networks", $networks); + $this->layout()->set("buildings", $buildings); + $this->layout()->set("pipworkeraddresses", $pipworkeraddresses); + $this->layout()->set("fiberplanpipes", $fiberplanpipes); + + } + + protected function addAction() + { + $networks = NetworkModel::getAll(); + $fiberplanpipetemplates = FiberPlanPipeModel::getTemplates(); + $pipworkeraddresses = FiberPlanPipeModel::getPipeworkerAddresses(); + $this->layout()->set("networks", $networks); + $this->layout()->set("pipworkeraddresses", $pipworkeraddresses); + $this->layout()->set("fiberplanpipetemplates", $fiberplanpipetemplates); + + $this->layout()->setTemplate("FiberPlanPipe/Form"); + + } + + protected function apiAction() + { + $do = $this->request->do; + $network = $this->request->network_id; + $bdtype = $this->request->bdtype; + + + switch ($do) { + case "getBuildingInfo": + $return = $this->getBuildingInfo($network, $bdtype); + break; + case "getPops": + $return = $this->getPops($network); + break; + default: + $return = false; + } + + } + + protected function detailAction() + { + $id = $this->request->id; + $networks = NetworkModel::getAll(); + $this->layout()->setTemplate("FiberPlanPipe/Detail"); + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("Rohrverzeichnis nicht gefunden", "error"); + $this->redirect("FiberPlanPipe"); + } + $fiberplanpipes = new FiberPlanPipe($id); + if ($fiberplanpipes->id != $id) { + $this->layout()->setFlash("Rohrverzeichnis nicht gefunden", "error"); + $this->redirect("FiberPlanPipe"); + } + $this->layout()->set("fiberplanpipes", $fiberplanpipes); + $pipworkeraddresses = FiberPlanPipeModel::getPipeworkerAddresses(); + $buildings = FiberPlanPipeModel::getBuildingInfoAll(); + $fiberplanpipeendpoints = FiberPlanPipeEndpointModel::search(['fiberPlanPipe_id' => $id]); + $this->layout()->set("networks", $networks); + $this->layout()->set("buildings", $buildings); + $this->layout()->set("pipworkeraddresses", $pipworkeraddresses); + $this->layout()->set("fiberplanpipeendpoints", $fiberplanpipeendpoints); + } + + protected function editAction() + { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("Rohrverzeichnis nicht gefunden", "error"); + $this->redirect("FiberPlanPipe"); + } + + $fiberplanpipes = new FiberPlanPipe($id); + if ($fiberplanpipes->id != $id) { + $this->layout()->setFlash("Rohrverzeichnis nicht gefunden", "error"); + $this->redirect("FiberPlanPipe"); + } + $fiberplanpipeendpoints = FiberPlanPipeEndpointModel::search(['fiberPlanPipe_id' => $id]); + $this->layout()->set("fiberplanpipeendpoints", $fiberplanpipeendpoints); + $this->layout()->set("fiberplanpipes", $fiberplanpipes); + return $this->addAction(); + } + + protected function saveAction() + { + $r = $this->request; + $id = $r->id; + var_dump($r->get()); + die(); + if (is_numeric($id) && $id > 0) { + $mode = "edit"; + $fiberplanpipes = new FiberPlanPipe($id); + if (!$fiberplanpipes->id) { + $this->layout()->setFlash("Rohrverzeichnisse nicht gefunden", "error"); + $this->redirect("FiberPlanPipe"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['description'] = trim($r->description); + $data['gisid'] = trim($r->gisid); + $data['type'] = trim($r->type); + $data['type_description'] = trim($r->type_description); + $data['fiberplanpipetemplate_id'] = trim($r->fiberplanpipetemplate_id); + $data['length'] = trim($r->length); + $data['status'] = trim($r->status); + $data['responsible'] = trim($r->responsible); + $data['responsible_text'] = trim($r->responsible_text); + $data['address_id'] = trim($r->address_id); + $data['comment'] = trim($r->comment); + + $returnUrl = "FiberPlanPipe"; + $returnAction = "Index"; + $returnVariables = array(); + $returnAnker = ""; + if ($this->request->returnto) { + + if (strpos($this->request->returnto, "-") !== false) { + $urls = explode('-', $this->request->returnto); + $urlCounter = 0; + $returnUrlGen = ""; + foreach ($urls as $url) { + if ($urlCounter > 0) { + $returnUrlGen .= "/"; + $returnUrlGen .= ucfirst($url); + } else { + $returnUrlGen .= 'FiberPlanPipe'; + } + $urlCounter++; + } + $returnAction = ""; + $returnVariables['id'] = $id; + $returnUrl = $returnUrlGen; + } else { + $returnUrl = ucfirst($this->request->returnto); + + } + } + if (!$data['description']) { + $this->layout()->setFlash("Bezeichnung darf nicht leer sein", "error"); + $this->redirect("FiberPlanPipe"); + } + if (!$data['type']) { + $data['type'] = NULL; + } + if (!$data['gisid']) { + $data['gisid'] = NULL; + } + if (!$data['responsible_text']) { + $data['responsible_text'] = NULL; + } + if (!$data['address_id']) { + $data['address_id'] = NULL; + } + if (!$data['type_description']) { + $data['type_description'] = NULL; + } + if (!$data['fiberplanpipetemplate_id']) { + $data['fiberplanpipetemplate_id'] = NULL; + } + if (!$data['length']) { + $data['length'] = NULL; + } + if (!$data['startpoint']) { + $data['startpoint'] = NULL; + } + if (!$data['endpoint']) { + $data['endpoint'] = NULL; + } + if (!$data['status']) { + $data['status'] = NULL; + } + if (!$data['responsible']) { + $data['responsible'] = NULL; + } + if (!$data['comment']) { + $data['comment'] = NULL; + } + + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $fiberplanpipes->update($data); + + } else { + $fiberplanpipes = FiberPlanPipeModel::create($data); + } +// var_dump($filestore); +// exit; + $id = $fiberplanpipes->save(); + + $endpoint_id = $r->endpointid; + $endpoint_type = $r->endpoint_type; + $endpoint = $r->endpoint; + + if (!empty($endpoint)) { + $counter = 1; + foreach ($endpoint as $key => $Endpoint) { + if ($endpoint_type[$key] == 4) { + $endpointarray['fiberPlanDispatcher_id'] = $Endpoint; + } else if ($endpoint_type[$key] == 2) { + $endpointarray['pop_id'] = $Endpoint; + } + $endpointarray['fiberPlanPipe_id'] = $id; + $endpointarray['sort'] = $counter; + if ($endpoint_id[$key]) { + $fiberplanpipeendpoint = new FiberPlanPipeEndpoint($id); + $fiberplanpipeendpoint->update($endpointarray); + } else { + $fiberplanpipeendpoint = FiberPlanPipeEndpointModel::create($endpointarray); + } + $fiberplanpipeendpoint->save(); + $counter++; + } + } + + + if (!$id) { + $this->layout()->setFlash("Rohrverzeichnis konnte nicht angelegt werden", "error"); + $this->redirect($returnUrl, $returnAction, $returnVariables, $returnAnker); + } + + if ($mode == "edit") { + $this->layout()->setFlash("Rohrverzeichnis erfolgreich geändert", "success"); + } else if ($mode = "add") { + $this->layout()->setFlash("Rohrverzeichnis erfolgreich angelegt", "success"); + } + $this->redirect($returnUrl, $returnAction, $returnVariables, $returnAnker); + } + + + protected function deleteAction() + { + $id = $this->request->id; + $fiberplanpipes = new FiberPlanPipe($id); + if (!$fiberplanpipes->id || $fiberplanpipes->id != $id) { + $this->layout()->setFlash("Rohrverzeichnis nicht gefunden.", "error"); + $this->redirect("FiberPlanPipe"); + } + + $fiberplanpipes->delete(); + $this->redirect("FiberPlanPipe"); + } + + protected function getBuildingInfo($network, $bdtype) + { + FiberPlanPipeModel::getBuildingInfo($network, $bdtype); + } +} diff --git a/application/FiberPlanPipe/FiberPlanPipeModel.php b/application/FiberPlanPipe/FiberPlanPipeModel.php new file mode 100644 index 000000000..42736fb78 --- /dev/null +++ b/application/FiberPlanPipe/FiberPlanPipeModel.php @@ -0,0 +1,376 @@ + "MR7", 2 => "MR14", 3 => "MR16", 4 => "MR20", 5 => "PE32", 6 => "PE40", 7 => "PE50", 8 => "KSR50", 9 => "KSR80", 10 => "KSR100"); + public static $type_definition = array(1 => "Enzel", 2 => "Schutzrohr", 3 => "Verband"); + + public static function find($data) + { + + } + + public static function create(array $data) + { + $model = new FiberPlanPipe(); + + foreach ($data as $field => $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("FiberPlanPipe", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipe($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("FiberPlanPipe", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipe($data); + } + } + return $items; + + } + + public static function getAllPipeManufacturer() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("FiberPlanPipeManufacturer", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipe($data); + } + } + return $items; + + } + + public static function getAllPipe() + { + $items = []; + $db = FronkDB::singleton(); + $sql = "SELECT `FiberPlanPipe`.`id`,`FiberPlanPipe`.`description`,`FiberPlanPipe`.`type`,`FiberPlanPipe`.`type_description`,`FiberPlanPipe`.`startpoint_network_id`, `FiberPlanPipe`.`endpoint_network_id`,`FiberPlanPipeTemplate`. `fiberPlanPipeManufacturer_id`,`FiberPlanPipeTemplate`.`pipe7x4`,`FiberPlanPipeTemplate`.`pipe14x10` FROM `FiberPlanPipe` +LEFT JOIN `FiberPlanPipeTemplate` ON `FiberPlanPipe`.`fiberPlanPipeTemplate_id`=`FiberPlanPipeTemplate`.id"; + $res = $db->query($sql); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipe($data); + } + } + return $items; + + + } + + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("FiberPlanPipe", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipe($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("FiberPlanPipe", "*", "$where"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipe($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("network_id", $filter)) { + $networkid = $filter['network_id']; + if (is_numeric($networkid)) { + $where .= " AND network_id=$networkid"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + + public static function getTemplates() + { + $items = []; + $db = FronkDB::singleton(); + $sql = "SELECT `FiberPlanPipeTemplate`.id,FiberPlanPipeTemplate.pipe7x4,FiberPlanPipeTemplate.pipe14x10,FiberPlanPipeManufacturer.name FROM `FiberPlanPipeTemplate` INNER JOIN FiberPlanPipeManufacturer ON FiberPlanPipeManufacturer.id=FiberPlanPipeTemplate.fiberPlanPipeManufacturer_id "; + $res = $db->query($sql); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipe($data); + } + } + return $items; + + } + + public static function getPipeworkerAddresses() + { + $items = []; + $db = FronkDB::singleton(); + $sql = "SELECT `Addresstype`.`id`,`Address`.`company` FROM `Addresstype` +INNER JOIN `Address` ON (`Address`.`id`=`Addresstype`.`address_id`) + WHERE `type` = 'pipeworker' ORDER by `Address`.`company` "; + $res = $db->query($sql); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipe($data); + } + } + return $items; + + } + + public static function getBuildingInfo($network, $bdtype, $api = 1) + { + $items = []; + $db = FronkDB::singleton(); + if ($bdtype == "1") { + $sql = "SELECT `id`,`description` `name` FROM `FiberPlanDispatcher` WHERE network_id='" . $network . "' AND `object_type`='3' "; + } else if ($bdtype == "2") { + $sql = "SELECT `Pop`.`id`,`Pop`.`name` FROM `PopNetwork` + INNER JOIN `Pop` ON (`Pop`.`id`=`PopNetwork`.`pop_id`) + WHERE `PopNetwork`.`network_id`='" . $network . "'"; + } else if ($bdtype == "3") { + $sql = "SELECT `id`,`code` ,`street`, `zip`, `city` name FROM Building WHERE network_id='" . $network . "' ORDER by street"; + } else if ($bdtype == "4") { + $sql = "SELECT `id`,`description` `name` FROM `FiberPlanDispatcher` WHERE network_id='" . $network . "' AND (`object_type`='1' OR `object_type`='2') "; + } + + $res = $db->query($sql); + + if ($db->num_rows($res)) { + $counter = 0; + while ($data = $db->fetch_array($res)) { + $items[$counter]['id'] = $data['id']; + if ($bdtype == "3") { + $items[$counter]['name'] = $data['street'] . " " . $data['zip'] . " " . $data['city']; + } else { + $items[$counter]['name'] = $data['name']; + } + $counter++; + } + } + if ($api === 1) { + echo json_encode($items); + exit; + } else { + return $items; + } + } + + public static function getBuildingInfoAll() + { + $items = []; + $db = FronkDB::singleton(); + $sql = "SELECT `id`, `fiberPlanDispatcher_id`, `name` FROM `FiberPlanDispatchersleeve` ORDER by id"; + $res = $db->query($sql); + if ($db->num_rows($res)) { + while ($data = $db->fetch_array($res)) { + $sleeves[$data['fiberPlanDispatcher_id']][$data['id']] = $data['name']; + } + } + + $sql = "SELECT '1' as `type`,'Greenfield' as `typename`,`id`,`description` as `name`,`gps_lat`,`gps_long` FROM `FiberPlanDispatcher` WHERE `object_type`='3' + UNION + SELECT '2' as `type`,'Pop' as `typename`,`id`,`name`,`gps_lat`,`gps_long` FROM `Pop` + UNION + SELECT '3' as `type`,'Building' as `typename`,`id`,CONCAT_WS(' ',`street`, `zip`, `city`) as name,`gps_lat`,`gps_long` FROM Building + UNION + SELECT '4' as `type`,'Schacht-Verteiler' as `typename`,`id`,`description` as `name`,`gps_lat`,`gps_long` FROM `FiberPlanDispatcher` WHERE (`object_type`='1' OR `object_type`='2')"; + $res = $db->query($sql); + if ($db->num_rows($res)) { + while ($data = $db->fetch_array($res)) { + $items[$data['type']][$data['id']] = $data; + if ($data['type'] == 4) { + $items[$data['type']][$data['id']]['sleeves'] = $sleeves[$data['id']]; + } + } + } + return $items; + + } + + public static function generateEndpoints($endpoints, $networks) + { + + foreach ($networks as $network) { + $Network[$network->id] = $network->name; + } + $counter = 1; + $endpointuparrow = ""; + $typeArray[1] = 'Greenfield'; + $typeArray[2] = 'POP'; + $typeArray[3] = 'Building'; + $typeArray[4] = 'Schacht-Verteiler'; + +// print_r($buildings); + $counter = 1; + foreach ($endpoints as $Endpoint) { + + if ($Endpoint->pop_id) { + $networkid = $Endpoint->pop->network_id; + $endpointid = $Endpoint->pop->id; + $endpointtype = 2; + } else if ($Endpoint->fiberPlanDispatcher_id) { + $networkid = $Endpoint->fiberPlanDispatcher->network_id; + $endpointid = $Endpoint->fiberPlanDispatcher->id; + if ($Endpoint->fiberPlanDispatcher->object_type == 3) { + $endpointtype = 1; + } else { + $endpointtype = 4; + } + } else if ($Endpoint->building_id) { + $networkid = $Endpoint->building->network_id; + $endpointid = $Endpoint->building->id; + $endpointtype = 3; + } + $randid = rand(1000, 10000); + if ($counter > 1) { + $Endpointuparrow = ''; + } + if ($counter == 1) { + $endpointType = "Startpunkt"; + $endpointsymbol = ''; + } + else if (count($endpoints)==2) + { + $endpointcount = $counter - 1; + $endpointType = "Standort " . $endpointcount; + $endpointsymbol=''; + } + else { + $endpointcount = $counter - 1; + $endpointType = "Standort " . $endpointcount; + $endpointsymbol = ''; + } + $html = '
    + +
    +
    +
    +
    +
    '; + echo $html; + $counter++; + } + + } + +} diff --git a/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpoint.php b/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpoint.php new file mode 100644 index 000000000..7229b9b7b --- /dev/null +++ b/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpoint.php @@ -0,0 +1,64 @@ +$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/FiberPlanPipeEndpoint/FiberPlanPipeEndpointController.php b/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpointController.php new file mode 100644 index 000000000..a72e4d5bf --- /dev/null +++ b/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpointController.php @@ -0,0 +1,145 @@ +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("FiberPlanPipeEndpoint/Index"); + $fiberplanpipeendpoints = FiberPlanPipeEndpointModel::getAll(); + $this->layout()->set("fiberplanpipeendpoints", $fiberplanpipeendpoints); + + } + + protected function addAction() + { + $fiberPlanPipes=FiberPlanPipeModel::getAll(); + $this->layout()->set("fiberPlanPipes", $fiberPlanPipes); + $pops=PopModel::getAll(); + $this->layout()->set("pops", $pops); + $fiberPlanDispatchers=FiberPlanDispatcherModel::getAll(); + $this->layout()->set("fiberPlanDispatchers", $fiberPlanDispatchers); + $buildings=BuildingModel::getAll(); + $this->layout()->set("buildings", $buildings); + + $this->layout()->setTemplate("FiberPlanPipeEndpoint/Form"); + + } + + protected function editAction() + { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("dfsdf nicht gefunden", "error"); + $this->redirect("FiberPlanPipeEndpoint"); + } + + $fiberplanpipeendpoints = new FiberPlanPipeEndpoint($id); + if ($fiberplanpipeendpoints->id != $id) { + $this->layout()->setFlash("dfsdf nicht gefunden", "error"); + $this->redirect("FiberPlanPipeEndpoint"); + } + + $this->layout()->set("fiberplanpipeendpoints", $fiberplanpipeendpoints); + 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"; + $fiberplanpipeendpoints = new FiberPlanPipeEndpoint($id); + if (!$fiberplanpipeendpoints->id) { + $this->layout()->setFlash("sdfsdf nicht gefunden", "error"); + $this->redirect("FiberPlanPipeEndpoint"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['fiberPlanPipe_id'] = trim($r->fiberPlanPipe_id); + $data['pop_id'] = trim($r->pop_id); + $data['fiberPlanDispatcher_id'] = trim($r->fiberPlanDispatcher_id); + $data['building_id'] = trim($r->building_id); + $data['sort'] = trim($r->sort); + + + if (!$data['fiberPlanPipe_id']) { + $data['fiberPlanPipe_id']=NULL; + } + if (!$data['pop_id']) { + $data['pop_id']=NULL; + } + if (!$data['fiberPlanDispatcher_id']) { + $data['fiberPlanDispatcher_id']=NULL; + } + if (!$data['building_id']) { + $data['building_id']=NULL; + } + if (!$data['sort']) { + $data['sort']=NULL; + } + + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $fiberplanpipeendpoints->update($data); + + } else { + $fiberplanpipeendpoints = FiberPlanPipeEndpointModel::create($data); + } +// var_dump($filestore); +// exit; + $id = $fiberplanpipeendpoints->save(); + + if (!$id) { + $this->layout()->setFlash("dfsdf konnte nicht angelegt werden", "error"); + $this->redirect("FiberPlanPipeEndpoint"); + } + + if ($mode == "edit") { + $this->layout()->setFlash("dfsdf erfolgreich geändert", "success"); + } else if ($mode = "add") { + $this->layout()->setFlash("dfsdf erfolgreich angelegt", "success"); + } + $this->redirect("FiberPlanPipeEndpoint"); + } + + + protected function deleteAction() + { + $id = $this->request->id; + $fiberplanpipeendpoints = new FiberPlanPipeEndpoint($id); + if (!$fiberplanpipeendpoints->id || $fiberplanpipeendpoints->id != $id) { + $this->layout()->setFlash("dfsdf nicht gefunden.", "error"); + $this->redirect("FiberPlanPipeEndpoint"); + } + + $fiberplanpipeendpoints->delete(); + $this->redirect("FiberPlanPipeEndpoint"); + } + +} diff --git a/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpointModel.php b/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpointModel.php new file mode 100644 index 000000000..7cfee1593 --- /dev/null +++ b/application/FiberPlanPipeEndpoint/FiberPlanPipeEndpointModel.php @@ -0,0 +1,129 @@ + $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("FiberPlanPipeEndpoint", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipeEndpoint($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("FiberPlanPipeEndpoint", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipeEndpoint($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("FiberPlanPipeEndpoint", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipeEndpoint($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("FiberPlanPipeEndpoint", "*", "$where ORDER by sort"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipeEndpoint($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("fiberPlanPipe_id", $filter)) { + $fiberPlanPipe_id = $filter['fiberPlanPipe_id']; + if (is_numeric($fiberPlanPipe_id)) { + $where .= " AND fiberPlanPipe_id=$fiberPlanPipe_id"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/FiberPlanPipeManufacturer/FiberPlanPipeManufacturer.php b/application/FiberPlanPipeManufacturer/FiberPlanPipeManufacturer.php new file mode 100644 index 000000000..83cdb68e6 --- /dev/null +++ b/application/FiberPlanPipeManufacturer/FiberPlanPipeManufacturer.php @@ -0,0 +1,42 @@ +$name == null) { + + if (!$this->id) { + return null; + } + + if ($name == "creator") { + $this->creator = new User($this->create_by); + return $this->creator; + } + + if ($name == "editor") { + $this->editor = new User($this->edit_by); + return $this->editor; + } + + $classname = ucfirst($name); + $idfield = $name . "_id"; + $this->$name = new $classname($this->$idfield); + + if ($this->$name->id) { + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } + +} \ No newline at end of file diff --git a/application/FiberPlanPipeManufacturer/FiberPlanPipeManufacturerModel.php b/application/FiberPlanPipeManufacturer/FiberPlanPipeManufacturerModel.php new file mode 100644 index 000000000..09556f05f --- /dev/null +++ b/application/FiberPlanPipeManufacturer/FiberPlanPipeManufacturerModel.php @@ -0,0 +1,126 @@ + $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("FiberPlanPipeManufacturer", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipeManufacturer($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("FiberPlanPipeManufacturer", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipeManufacturer($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("FiberPlanPipeManufacturer", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipeManufacturer($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("FiberPlanPipeManufacturer", "*", "$where"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipeManufacturer($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("network_id", $filter)) { + $networkid = $filter['network_id']; + if (is_numeric($networkid)) { + $where .= " AND network_id=$networkid"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/FiberPlanPipeTemplate/FiberPlanPipeTemplate.php b/application/FiberPlanPipeTemplate/FiberPlanPipeTemplate.php new file mode 100644 index 000000000..d85308607 --- /dev/null +++ b/application/FiberPlanPipeTemplate/FiberPlanPipeTemplate.php @@ -0,0 +1,43 @@ +$name == null) { + + if (!$this->id) { + return null; + } + + if ($name == "creator") { + $this->creator = new User($this->create_by); + return $this->creator; + } + + if ($name == "editor") { + $this->editor = new User($this->edit_by); + return $this->editor; + } + + $classname = ucfirst($name); + $idfield = $name . "_id"; + $this->$name = new $classname($this->$idfield); + + if ($this->$name->id) { + return $this->$name; + } else { + return null; + } + } + + return $this->$name; + } + +} \ No newline at end of file diff --git a/application/FiberPlanPipeTemplate/FiberPlanPipeTemplateModel.php b/application/FiberPlanPipeTemplate/FiberPlanPipeTemplateModel.php new file mode 100644 index 000000000..fec7e6ae4 --- /dev/null +++ b/application/FiberPlanPipeTemplate/FiberPlanPipeTemplateModel.php @@ -0,0 +1,127 @@ + $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("FiberPlanPipeTemplate", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipeTemplate($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("FiberPlanPipeTemplate", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipeTemplate($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("FiberPlanPipeTemplate", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new FiberPlanPipeTemplate($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("FiberPlanPipeTemplate", "*", "$where"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new FiberPlanPipeTemplate($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("network_id", $filter)) { + $networkid = $filter['network_id']; + if (is_numeric($networkid)) { + $where .= " AND network_id=$networkid"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/HistoricTicket/HistoricTicket.php b/application/HistoricTicket/HistoricTicket.php new file mode 100644 index 000000000..ad3fb26f3 --- /dev/null +++ b/application/HistoricTicket/HistoricTicket.php @@ -0,0 +1,9 @@ +loadMe(); + $this->layout()->set("me", $me); + $this->me = $me; + } + + protected function indexAction(): void { + if (!$this->me->is("employee")) { + $this->redirect("dashboard"); + } + $this->layout()->setTemplate("HistoricTicket/Index"); + } + + protected function apiAction() { + $do = $this->request->do; + + if ($do !== "getConfig" && !$this->me->is("employee")) { + $this->redirect("dashboard"); + } + + switch ($do) { + case "getHistoricTickets": + $return = $this->getHistoricTickets(); + break; + case "getHistoricTicketMessages": + $return = $this->getHistoricTicketMessages(); + break; + case "findHistoricTicket": + $return = $this->findHistoricTicket(); + break; + default: + $return = false; + break; + } + + if (!$return) { + $return = [ + "status" => "error", + "message" => "Invalid request." + ]; + } + + die(json_encode($return)); + } + + private function getHistoricTickets(): array { + $json = json_decode(file_get_contents('php://input'), true); + + $filters = $json['filters'] ?? []; + $page = $json['pagination']['page'] ?? 1; + $perPage = $json['pagination']['per_page'] ?? 10; + + $historicTickets = HistoricTicketModel::getAllHistoricTickets($filters, $perPage, ($page - 1) * $perPage); + $total = HistoricTicketModel::countHistoricTickets($filters); + + return [ + "rows" => $historicTickets, + "pagination" => [ + "page" => $page, + "total_pages" => ceil($total / $perPage), + "per_page" => $perPage, + "total_rows" => intval($total) + ] + ]; + } + + private function getHistoricTicketMessages(): array { + $json = json_decode(file_get_contents('php://input'), true); + $ticketNumber = $json['ticketNumber']; + + return HistoricTicketModel::findHistoricTicket($ticketNumber); + } + + private function findHistoricTicket(): array { + $query = $this->request->query; + + if (empty($query)) { + return [ + "status" => "error", + "message" => "No query provided." + ]; + } + + $rows = HistoricTicketModel::findTicket($query); + + return [ + "rows" => $rows, + "pagination" => [ + "page" => 1, + "total_pages" => 1, + "per_page" => count($rows), + "total_rows" => count($rows) + ] + ]; + } +} \ No newline at end of file diff --git a/application/HistoricTicket/HistoricTicketModel.php b/application/HistoricTicket/HistoricTicketModel.php new file mode 100644 index 000000000..8f5fb6c32 --- /dev/null +++ b/application/HistoricTicket/HistoricTicketModel.php @@ -0,0 +1,183 @@ + $value) { + if (property_exists(get_called_class(), $field)) { + $this->$field = $value; + } + } + } + + public static function generateFilterCondition(?string $filterValue, string $columnName): string { + $sql = ""; + if (!empty($filterValue)) { + $filterItems = explode(" ", $filterValue); + foreach ($filterItems as $item) { + $sql .= " AND `$columnName` LIKE '%" . $item . "%'"; + } + } + + return $sql; + } + + public static function getSqlFilter($filters): string { + $sql = isset($filters['subject']) ? self::generateFilterCondition($filters['subject'], "subject") : ""; + $sql .= isset($filters['ticket_number']) ? self::generateFilterCondition($filters['ticket_number'], "ticket_number") : ""; + $sql .= isset($filters['priority']) ? " AND `priority` = " . $filters['priority'] : ""; + $sql .= isset($filters['status']) ? self::generateFilterCondition($filters['status'], "status") : ""; + $sql .= isset($filters['status_id']) ? " AND `status_id` = " . $filters['status_id'] : ""; + $sql .= isset($filters['type']) ? self::generateFilterCondition($filters['type'], "type") : ""; + $sql .= isset($filters['type_id']) ? " AND `type_id` = " . $filters['type_id'] : ""; + $sql .= isset($filters['user_id']) ? " AND `user_id` = " . $filters['user_id'] : ""; + $sql .= isset($filters['agent_id']) ? " AND `agent_id` = " . $filters['agent_id'] : ""; + $sql .= isset($filters['contact_id']) ? " AND `contact_id` = " . $filters['contact_id'] : ""; + $sql .= isset($filters['company']) ? self::generateFilterCondition($filters['company'], "company") : ""; + $sql .= isset($filters['company_id']) ? " AND `company_id` = " . $filters['company_id'] : ""; + $sql .= isset($filters['middle_name']) ? self::generateFilterCondition($filters['middle_name'], "middle_name") : ""; + $sql .= isset($filters['last_name']) ? self::generateFilterCondition($filters['last_name'], "last_name") : ""; + $sql .= isset($filters['email']) ? " AND `email` LIKE '%" . $filters['email'] . "%'" : ""; + $sql .= isset($filters['phone']) ? " AND `phone` LIKE '%" . $filters['phone'] . "%'" : ""; + $sql .= isset($filters['ctime']) ? " AND `ctime` = " . $filters['ctime'] : ""; + $sql .= isset($filters['mtime']) ? " AND `mtime` = " . $filters['mtime'] : ""; + $sql .= isset($filters['muser_id']) ? " AND `muser_id` = " . $filters['muser_id'] : ""; + $sql .= isset($filters['files_folder_id']) ? " AND `files_folder_id` = " . $filters['files_folder_id'] : ""; + $sql .= isset($filters['unseen']) ? " AND `unseen` = " . $filters['unseen'] : ""; + $sql .= isset($filters['group_id']) ? " AND `group_id` = " . $filters['group_id'] : ""; + $sql .= isset($filters['order_id']) ? " AND `order_id` = " . $filters['order_id'] : ""; + $sql .= isset($filters['last_response_time']) ? " AND `last_response_time` = " . $filters['last_response_time'] : ""; + $sql .= isset($filters['cc_addresses']) ? self::generateFilterCondition($filters['cc_addresses'], "cc_addresses") : ""; + + if (isset($filters['first_name'])) { + $filterItems = explode(" ", $filters['first_name']); + foreach ($filterItems as $item) { + $sql .= " AND (`first_name` LIKE '%" . $item . "%' OR `middle_name` LIKE '%" . $item . "%' OR `last_name` LIKE '%" . $item . "%')"; + } + } + + return $sql; + } + + public static function getAllHistoricTickets($filters, $limit = null, $offset = 0): array { + $db = FronkDB::singleton(); + $sql = "SELECT * FROM `HistoricTicket` WHERE 1 " . self::getSqlFilter($filters) . " ORDER BY `ticket_number` DESC"; + $sql .= $limit === null ? "" : " LIMIT " . $limit . " OFFSET " . $offset; + + $result = $db->query($sql); + $rows = []; + while ($row = $result->fetch_assoc()) { + $rows[] = $row; + } + + return $rows; + } + + public static function countHistoricTickets($filters) { + $db = FronkDB::singleton(); + $sql = "SELECT COUNT(*) as `total_rows` FROM `HistoricTicket` WHERE 1 " . self::getSqlFilter($filters); + $result = $db->query($sql); + return $result->fetch_assoc()['total_rows']; + } + + public static function findHistoricTicket($ticketNumber): array { + $db = FronkDB::singleton(); + + $ticketSql = "SELECT * FROM `HistoricTicket` WHERE `ticket_number` = " . $ticketNumber; + $ticketResult = $db->query($ticketSql); + $ticket = $ticketResult->fetch_assoc(); + + $messagesSql = "SELECT * FROM `HistoricTicketMessage` WHERE `ticket_id` = " . $ticket["id"]; + $messagesResult = $db->query($messagesSql); + $messages = []; + while ($message = $messagesResult->fetch_assoc()) { + $messages[] = $message; + } + + return [ + "ticket" => $ticket, + "messages" => $messages + ]; + } + + public static function findTicket($query): array { + $db = FronkDB::singleton(); + $ticketSql = "SELECT * FROM `HistoricTicket` WHERE `ticket_number` LIKE '%" . $query . "%' OR `subject` LIKE '%" . $query . "%' OR `first_name` LIKE '%" . $query . "%' OR `last_name` LIKE '%" . $query . "%'"; + $ticketResult = $db->query($ticketSql); + $tickets = []; + while ($ticket = $ticketResult->fetch_assoc()) { + $tickets[] = $ticket; + } + + //explore $query by space and add each word to the sql query with and + $query = explode(" ", $query); + + $whereStr = ""; + foreach ($query as $word) { + $whereStr .= " AND `content` LIKE '%" . $word . "%'"; + } + + $messagesSql = "SELECT * FROM `HistoricTicketMessage` + LEFT JOIN `HistoricTicket` ON `HistoricTicket`.`id` = `HistoricTicketMessage`.`ticket_id` + WHERE 1 AND `content` " . $whereStr; + $messagesResult = $db->query($messagesSql); + $messages = []; + while ($message = $messagesResult->fetch_assoc()) { + $messages[] = $message; + } + + $return = []; + + foreach ($tickets as $ticket) { + $return[] = [ + "table_entry" => "ticket", + "ticket_id" => $ticket["id"], + "ticket_number" => $ticket["ticket_number"], + "ctime" => $ticket["ctime"], + "ticket_subject" => $ticket["subject"], + ]; + } + + foreach ($messages as $message) { + $return[] = [ + "table_entry" => "message", + "ticket_id" => $message["ticket_id"], + "ticket_number" => $message["ticket_number"], + "ticket_subject" => $message["subject"], + "ctime" => $message["ctime"], + "ticket_message" => $message["content"], + ]; + } + + return $return; + } +} \ No newline at end of file diff --git a/application/Timerecording/Timerecording.php b/application/Timerecording/Timerecording.php index 86c9aeade..e6cfdbb8e 100644 --- a/application/Timerecording/Timerecording.php +++ b/application/Timerecording/Timerecording.php @@ -6,7 +6,8 @@ class Timerecording extends mfBaseModel private $creator; private $user; private $timerecordingCategory; - + private $timerecordingCar; + public function getProperty($name) diff --git a/application/Timerecording/TimerecordingController.php b/application/Timerecording/TimerecordingController.php index 187a0c421..20b4889a0 100644 --- a/application/Timerecording/TimerecordingController.php +++ b/application/Timerecording/TimerecordingController.php @@ -22,7 +22,9 @@ class TimerecordingController extends mfBaseController $this->updateHolidays($this->me->id); $timerecordingCategoriess = TimerecordingCategoryModel::getAll(); + $timerecordingCars = TimerecordingCarModel::search(['timerecording' => 1]); $this->layout()->set("timerecordingCategoriess", $timerecordingCategoriess); + $this->layout()->set("timerecordingCars", $timerecordingCars); $this->layout()->setTemplate("Timerecording/Index"); } @@ -206,13 +208,12 @@ class TimerecordingController extends mfBaseController $employee = TimerecordingEmployeeModel::search(['user_id' => $userid]); $plushours = $employee[0]->plushours_now * 1.25; - $overtime = $employee[0]->overtime * 1.5; + $overtime = $employee[0]->overtime_now * 1.5; $overtimesum = $plushours + $overtime; if ($overtimesum < $isTime) { if ($overtimesum < 0) { $overtimesum = 0; } - $result['state'] = "error"; $result['error'] = "Maximal verfügbarer ZA: " . sprintf('%02dh:%02dm', floor($overtimesum / 3600), floor($overtimesum / 60 % 60)) . "."; echo json_encode($result); @@ -221,7 +222,7 @@ class TimerecordingController extends mfBaseController if ($plushours >= $isTime) { $isTime = $isTime * 0.8; $return['hours'] = $isTime; - } elseif ($plushours <= 0) { + } elseif ($plushours == 0) { $isTime = $isTime * 0.66666666666666666666666666666667; $return ['hours_overtime'] = $isTime; } else { @@ -265,7 +266,7 @@ class TimerecordingController extends mfBaseController $this->updateOpenTimerecording(); } $data = []; - if ($hourday == 1 || $hourday == 6) { + if ($hourday == 1 || $hourday == 6 || $hourday == 7) { $starttime = strtotime($r->date . " " . $r->start . ":00"); $endtime = strtotime($r->date . " " . $r->end . ":00"); if ($hourday == 6) { @@ -282,7 +283,7 @@ class TimerecordingController extends mfBaseController $endtime = strtotime($r->date . " 23:59:00"); } - if ($hourday != 5) { + if ($hourday != 5 && $hourday != 7) { $result = $this->checkTimerecording($starttime, $endtime, $id); } if ($result['state'] == "error") { @@ -321,6 +322,19 @@ class TimerecordingController extends mfBaseController $data['businesstrip_info'] = $r->businesstrip_info; $data['homeoffice'] = $r->homeoffice; $data['days'] = $r->days; + $data['timerecordingCar_id'] = $r->timerecordingCar_id; + $data['mileage_start'] = $r->mileage_start; + $data['mileage_end'] = $r->mileage_end; + + if (!$data['timerecordingCar_id']) { + $data['timerecordingCar_id'] = NULL; + } + if (!$data['mileage_start']) { + $data['mileage_start'] = NULL; + } + if (!$data['mileage_end']) { + $data['mileage_end'] = NULL; + } if (!$data['businesstrip'] || $data['businesstrip'] == "false") { $data['businesstrip'] = 0; @@ -436,6 +450,7 @@ class TimerecordingController extends mfBaseController $this->updateHolidays($data['user_id']); } $this->updatePlushours($data['user_id']); + TimerecordingCarModel::calcMileage(); } if ($mode == "edit") { @@ -828,6 +843,16 @@ class TimerecordingController extends mfBaseController $sum = "-" . sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); $day = $daysgerm[date("w", $timerecording->start)]; $isSeconds = $isSeconds + $seconds; + } else if ($timerecording->timerecordingCategory->hourday == 7) { + $date = date("d.m.Y", $timerecording->start); + $datadate = date("Y-m-d", $timerecording->start); + $start = date("H:i", $timerecording->start); + $end = date("H:i", $timerecording->end); + $seconds = $timerecording->end - $timerecording->start; + $minutes = floor(($seconds % 3600) / 60); + $hours = floor($seconds / 3600); + $sum = sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); + $day = $daysgerm[date("w", $timerecording->start)]; } if ($timerecording->timerecordingCategory->approval == 1 && $timerecording->approved == 0) { @@ -836,8 +861,17 @@ class TimerecordingController extends mfBaseController $state = ''; } $edit = ""; - if ($timerecording->businesstrip == 1) { - $category = "" . $timerecording->timerecordingCategory->name . " (Dienstreise: " . $timerecording->businesstrip_info . ")"; + if ($timerecording->timerecordingCategory->hourday == 7) { + $distance = $timerecording->mileage_end - $timerecording->mileage_start; + $category = "" . $timerecording->timerecordingCategory->name . "(" . $timerecording->timerecordingCar->number_plate . " " . $distance . "KM) (Zielort: " . $timerecording->businesstrip_info . ")"; + } else if ($timerecording->businesstrip == 1) { + if ($timerecording->timerecordingCar) { + $distance = $timerecording->mileage_end - $timerecording->mileage_start; + $car = " (" . $timerecording->timerecordingCar->number_plate . " " . $distance . "KM)"; + } else { + $car = ""; + } + $category = "" . $timerecording->timerecordingCategory->name . "$car (Dienstreise: " . $timerecording->businesstrip_info . ")"; } else if ($timerecording->homeoffice == 1) { $category = "" . $timerecording->timerecordingCategory->name . " (Homeoffice)"; } else { @@ -860,13 +894,16 @@ class TimerecordingController extends mfBaseController data-businesstrip="' . $timerecording->businesstrip . '" data-businesstripinfo="' . $timerecording->businesstrip_info . '" data-homeoffice="' . $timerecording->homeoffice . '" + data-car="' . $timerecording->timerecordingCar_id . '" + data-mileagestart="' . $timerecording->mileage_start . '" + data-mileageend="' . $timerecording->mileage_end . '" title="Bearbeiten">
    '; else : $edit .= '
    '; endif; $edit .= ''; endif; - if ($datatype == 3 && $timerecording->timerecordingCategory->hourday == 1) { + if ($datatype == 3 && ($timerecording->timerecordingCategory->hourday == 1 || $timerecording->timerecordingCategory->hourday == 7 || $timerecording->timerecordingCategory->hourday == 5)) { } else { $rows[] = array( 'date' => array('date' => $state . $day . " " . $date, 'order' => $orderdate), diff --git a/application/Timerecording/TimerecordingModel.php b/application/Timerecording/TimerecordingModel.php index a777b5c9f..e90456ed6 100644 --- a/application/Timerecording/TimerecordingModel.php +++ b/application/Timerecording/TimerecordingModel.php @@ -11,6 +11,10 @@ class TimerecordingModel private $timerecordingCategory_id; private $businesstrip; private $businesstrip_info; + private $timerecordingCar_id; + private $mileage_start; + private $mileage_end; + private $homeoffice; private $comment; private $approved; @@ -151,7 +155,7 @@ class TimerecordingModel $start = $filter['start']; $end = $filter['end']; if (is_numeric($start) && is_numeric($end)) { - $where .= " AND ((`start` >= $start AND `start` <= $end) OR (`end` >= $start AND `end` <= $end) OR `end` is NULL) ORDER by user_id ASC"; + $where .= " AND ((`start` >= $start AND `start` <= $end) OR (`end` >= $start AND `end` <= $end) OR `end` is NULL) ORDER by user_id,start ASC"; } } if (array_key_exists("start", $filter) && array_key_exists("timerecordingCategory_id", $filter)) { @@ -174,7 +178,20 @@ class TimerecordingModel $where .= " AND `start` >= $start AND `days` !=0 ORDER by start ASC"; } } + if (array_key_exists("timerecordingCar_id", $filter)) { + $timerecordingCar = $filter['timerecordingCar_id']; + if (is_numeric($timerecordingCar)) { + $where .= " AND `timerecordingCar_id` = $timerecordingCar ORDER by mileage_end DESC LIMIT 1"; + } + } + if (array_key_exists("timerecordingCar_id_all", $filter)) { + $timerecordingCar = $filter['timerecordingCar_id_all']; + + if (is_numeric($timerecordingCar)) { + $where .= " AND `timerecordingCar_id` = $timerecordingCar ORDER by mileage_start ASC"; + } + } if (array_key_exists("starttime", $filter) && array_key_exists("endtime", $filter)) { $starttime = $filter['starttime']; @@ -182,11 +199,11 @@ class TimerecordingModel $id = $filter['id']; if (is_numeric($starttime) && is_numeric($endtime)) { if ($id && is_numeric($id)) { - $where .= " AND `id` != $id"; + $where .= " AND `id` != $id "; } - $where .= " AND (((`start` <= $starttime AND `end` > $starttime ) OR (`start` > $endtime AND `end` < $endtime) OR (`start` > $starttime AND `end` > $starttime AND `start` <= $endtime AND `end` <= $endtime) OR (`start` > $starttime AND `end` > $starttime AND `start` < $endtime AND `end` > $endtime) OR (`start` = $starttime AND `end` = $endtime )) OR ( `start` <= $starttime AND `end` IS NULL)) ORDER by user_id ASC"; + $where .= " AND (((`start` <= $starttime AND `end` > $starttime ) OR (`start` > $endtime AND `end` < $endtime) OR (`start` > $starttime AND `end` > $starttime AND `start` <= $endtime AND `end` <= $endtime) OR (`start` > $starttime AND `end` > $starttime AND `start` < $endtime AND `end` > $endtime) OR (`start` = $starttime AND `end` = $endtime )) OR ( `start` <= $starttime AND `end` IS NULL)) AND `days` = 0 ORDER by user_id,start ASC"; -//var_dump($where);exit; +//echo ($where);die(); } } if (array_key_exists("type", $filter)) { diff --git a/application/TimerecordingBilling/TimerecordingBilling.php b/application/TimerecordingBilling/TimerecordingBilling.php new file mode 100644 index 000000000..16d8aa843 --- /dev/null +++ b/application/TimerecordingBilling/TimerecordingBilling.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/TimerecordingBilling/TimerecordingBillingController.php b/application/TimerecordingBilling/TimerecordingBillingController.php new file mode 100644 index 000000000..a5a6f5f22 --- /dev/null +++ b/application/TimerecordingBilling/TimerecordingBillingController.php @@ -0,0 +1,557 @@ +needlogin = true; + $me = new User(); + $me->loadMe(); + $this->me = $me; + $this->layout()->set("me", $me); + + if (!$me->can(["Fibu"])) { + $this->redirect("Dashboard"); + } + } + + protected function indexAction() + { + $startdate = 1709254800; + $today = time(); + $months = []; + $month = $startdate; + while ($month < $today) { + $months[] = date("m.Y", $month); + $month = strtotime("+1 month", $month); + } + $timerecordingBillings = TimerecordingBillingModel::getAll(); + + foreach ($timerecordingBillings as $timerecordingBilling) { + $timerecordingbillings[$timerecordingBilling->month] = $timerecordingBilling; + echo $timerecordingBilling->month; + } + + $this->layout()->set("months", $months); + $this->layout()->set("timerecordingbillings", $timerecordingbillings); + $this->layout()->setTemplate("TimerecordingBilling/Index"); + } + + protected function detailClosedAction($timerecordingBilling) + { + $r = $this->request; + $month = $r->get("month"); + $month = strtotime("01." . $month); + + $timerecordings = TimerecordingBillingEmployeeModel::search(["timerecordingBilling_id" => $timerecordingBilling[0]->id]); + $this->layout()->setTemplate("TimerecordingBilling/DetailClosed"); + $this->layout()->set("month", date("m.Y", $month)); + $this->layout()->set("timerecordings", $timerecordings); + + } + + protected function detailAction() + { + $r = $this->request; + $month = $r->get("month"); + if (!$month) { + $this->redirect("TimerecordingBilling"); + } + $timerecordingBilling = TimerecordingBillingModel::search(["month" => $month]); + if ($timerecordingBilling) { + $this->detailclosedAction($timerecordingBilling); + } else { + $month = strtotime("01." . $month); + $timerecordingsEmolyees = TimerecordingEmployeeModel::getAll(); + foreach ($timerecordingsEmolyees as $timerecordingsEmolyee) { + if ($timerecordingsEmolyee->bmd_active == 0) continue; + $user = new User($timerecordingsEmolyee->user_id); + $employee_number = (string)$user->getFlag('employee_number'); + $timerecordingReport = new TimerecordingReportController(); + $timerecordings[$timerecordingsEmolyee->user_id]['user_id'] = $timerecordingsEmolyee->user_id; + $timerecordings[$timerecordingsEmolyee->user_id]['user_name'] = $timerecordingsEmolyee->user->name; + $timerecordings[$timerecordingsEmolyee->user_id]['employee_number'] = $employee_number; + $timerecordings[$timerecordingsEmolyee->user_id]['data'] = $timerecordingReport->getTimerecordingsTimes('2', $month, $month, $month, $timerecordingsEmolyee->user_id, 0); + } + $this->layout()->set("timerecordings", $timerecordings); + $this->layout()->setTemplate("TimerecordingBilling/Detail"); + $this->layout()->set("month", date("m.Y", $month)); + } + } + + protected function apiAction() + { + $do = $this->request->do; + $month = $this->request->month; + + $data = []; + + switch ($do) { + case "generatebmdexport": + $return = $this->generateBmdExport($month); + break; + case "generatebmdexportnlz": + $return = $this->generateBmdExport($month, 1); + break; + case "generatebmdexportclosed": + $return = $this->generateBmdExportClosed($month); + break; + case "generatebmdexportnlzclosed": + $return = $this->generateBmdExportClosed($month, 1); + break; + case "completemonth": + $return = $this->completemonth($month); + break; + case "saveovertime": + $return = $this->saveovertime(); + 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); + } + + protected function addAction() + { + + + } + + protected function editAction() + { + + } + + protected function saveAction() + { + $r = $this->request; + $id = $r->id; + //var_dump($r->get());exit; + if (is_numeric($id) && $id > 0) { + $mode = "edit"; + $timerecordingbillings = new TimerecordingBilling($id); + if (!$timerecordingbillings->id) { + $this->layout()->setFlash("Timerecording nicht gefunden", "error"); + $this->redirect("TimerecordingBilling"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['month'] = trim($r->month); + $data['closetime'] = time(); + + + if (!$data['month']) { + $data['month'] = NULL; + } + if (!$data['closetime']) { + $data['closetime'] = NULL; + } + + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $timerecordingbillings->update($data); + + } else { + $timerecordingbillings = TimerecordingBillingModel::create($data); + } +// var_dump($filestore); +// exit; + $id = $timerecordingbillings->save(); + + if (!$id) { + $this->layout()->setFlash("Timerecording konnte nicht angelegt werden", "error"); + $this->redirect("TimerecordingBilling"); + } + + if ($mode == "edit") { +// $this->layout()->setFlash("Timerecording erfolgreich geändert", "success"); + } else if ($mode = "add") { +// $this->layout()->setFlash("Timerecording erfolgreich angelegt", "success"); + } + return $id; + } + + + protected function deleteAction() + { + $id = $this->request->id; + $timerecordingbillings = new TimerecordingBilling($id); + if (!$timerecordingbillings->id || $timerecordingbillings->id != $id) { + $this->layout()->setFlash("Timerecording nicht gefunden.", "error"); + $this->redirect("TimerecordingBilling"); + } + + $timerecordingbillings->delete(); + $this->redirect("TimerecordingBilling"); + } + + protected function generateBmdLine() + { + + } + + protected function generateBmdExportClosed($month, $nlz = 0) + { + $filename = "import_bmd_" . $month . ".csv"; + $file = fopen("php://output", 'w'); + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename=' . $filename); + $monthbmd = date("n", strtotime("01." . $month)); + $companybmd = "1"; + if ($nlz == 0) { + $headerarray = ["Monat", "Firma", "Mitarbeiter", "Lohnart", "Menge", "Satz", "Betrag", "Kostenstelle", "NLZ-Kennzeichen", "NLZ Von-Datum", "NLZ Bis-Datum"]; + fputcsv($file, $headerarray, ";"); + } else { + $headerarray = ["Firma", "Mitarbeiter", "DV-Nr", "Art", "Sonderzeit", "Verarbeitungs-KZ", "Von", "Bis", "Verwaltung", "Bezahlt"]; + fputcsv($file, $headerarray, ";"); + } + $billing = TimerecordingBillingModel::search(["month" => $month]); + $timerecordingBillingEmployees = TimerecordingBillingEmployeeModel::search(["timerecordingBilling_id" => $billing[0]->id]); + foreach ($timerecordingBillingEmployees as $timerecordingBillingEmployee) { + if ($timerecordingBillingEmployee->timerecordingEmployee->bmd_active == 0) continue; + $user = new User($timerecordingBillingEmployee->timerecordingEmployee->user_id); + $employee_number = (string)$user->getFlag('employee_number'); + $employeetypesbmd = TimerecordingEmployeeModel::$employeetypesbmd; + $employee_type = $employeetypesbmd[$timerecordingBillingEmployee->timerecordingEmployee->type]; + $overtimebase = 0; + if ($nlz == 0) { + $hours = $timerecordingBillingEmployee->ishours / 3600; + $hours = round($hours, 2); + $hours = str_replace(".", ",", $hours); + if ($hours > 0) { + $bodyarray = [$monthbmd, "1", $employee_number, $employee_type, $hours, "", "", "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + } + if ($timerecordingBillingEmployee->overtime50free > 0) { + $overtime50free = $timerecordingBillingEmployee->overtime50free / 3600; + $overtime50free = round($overtime50free, 2); + $overtimebase = $overtimebase + $overtime50free; + $overtime50free = str_replace(".", ",", $overtime50free); + $bodyarray = [$monthbmd, "1", $employee_number, "3110", $overtime50free, "", "", "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + } + if ($timerecordingBillingEmployee->overtime100free > 0) { + $overtime100free = $timerecordingBillingEmployee->overtime100free / 3600; + $overtime100free = round($overtime100free, 2); + $overtimebase = $overtimebase + $overtime100free; + $overtime100free = str_replace(".", ",", $overtime100free); + $bodyarray = [$monthbmd, "1", $employee_number, "3160", $overtime100free, "", "", "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + } + if ($overtimebase > 0) { + $overtimebase = str_replace(".", ",", $overtimebase); + $bodyarray = [$monthbmd, "1", $employee_number, "3100", $overtimebase, "", "", "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + } + + if ($timerecordingBillingEmployee->homeoffice > 0) { + $homeoffice = $timerecordingBillingEmployee->homeoffice; + $homeoffice = round($homeoffice, 2); + $homeoffice = str_replace(".", ",", $homeoffice); + $bodyarray = [$monthbmd, "1", $employee_number, "7590", $homeoffice, "", "", "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + } + + } else { + if ($timerecordingBillingEmployee->nlz_detail) { + foreach (json_decode($timerecordingBillingEmployee->nlz_detail, true) as $nlztime) { + + $bodyarray = [$companybmd, $employee_number, 1, $nlztime['categoryshort'], $nlztime['catExtended'], "3", $nlztime['start'], $nlztime['end'], $nlztime['time'], $nlztime['pay']]; + fputcsv($file, $bodyarray, ";"); + + + } + } + } + if ($timerecordingBillingEmployee->diet > 0 && $nlz == 0) { + $dietsum = round($timerecordingBillingEmployee->diet, 2); + $dietsum = str_replace(".", ",", $dietsum); + $bodyarray = [$monthbmd, $companybmd, $employee_number, "2500", "", "", $dietsum, "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + + } + + } + + + fclose($file); + exit; + } + + protected function generateBmdExport($month, $nlz = 0, $export = 1) + { + //create and download csv file + if ($export == 1) { + $filename = "import_bmd_" . $month . ".csv"; + $file = fopen("php://output", 'w'); + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename=' . $filename); + } + if ($export == 1) { + if ($nlz == 0) { + $headerarray = ["Monat", "Firma", "Mitarbeiter", "Lohnart", "Menge", "Satz", "Betrag", "Kostenstelle", "NLZ-Kennzeichen", "NLZ Von-Datum", "NLZ Bis-Datum"]; + fputcsv($file, $headerarray, ";"); + } else { + $headerarray = ["Firma", "Mitarbeiter", "DV-Nr", "Art", "Sonderzeit", "Verarbeitungs-KZ", "Von", "Bis", "Verwaltung", "Bezahlt"]; + fputcsv($file, $headerarray, ";"); + } + } + + + $month = strtotime("01." . $month); + //last of month + $monthend = date("Y-m-d", strtotime("last day of this month", $month)); + $monthend = strtotime($monthend . " 23:59:59"); + + + $monthbmd = date("n", $month); + $companybmd = "1"; + $timerecordingsEmolyees = TimerecordingEmployeeModel::getAll(); + foreach ($timerecordingsEmolyees as $timerecordingsEmolyee) { + if ($timerecordingsEmolyee->bmd_active == 0) continue; + $user = new User($timerecordingsEmolyee->user_id); + $employee_number = (string)$user->getFlag('employee_number'); + $employeetypesbmd = TimerecordingEmployeeModel::$employeetypesbmd; + $employee_type = $employeetypesbmd[$timerecordingsEmolyee->type]; + $timerecordingReport = new TimerecordingReportController(); + $timerecording = $timerecordingReport->getTimerecordingsTimes('2', $month, $month, $month, $timerecordingsEmolyee->user_id, 0); + if ($export == 0) { + $reponse[$employee_number]['employee_id'] = $timerecordingsEmolyee->id; + $reponse[$employee_number]['homeoffice'] = $timerecording['time']['homeoffice']; + $reponse[$employee_number]['istimeall'] = $timerecording['time']['isorder']; + $reponse[$employee_number]['musttime'] = $timerecording['time']['mustorder']; + } + + foreach ($timerecording['time']['isclean'] as $key => $value) { + $hours = $value; + //calc ishours in hours + $hours = $hours / 3600; + $hours = round($hours, 2); + $hours = str_replace(".", ",", $hours); + if (strpos($key, ',') !== false && $nlz == 0) { + if ($export == 1) { + $bodyarray = [$monthbmd, $companybmd, $employee_number, $employee_type, $hours, "", "", "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + } else { + $reponse[$employee_number]['istime'] = $value; + } + } else if (strpos($key, ',') === false && $nlz == 1) { + + } + + } + + if ($timerecording['time']['diet'] > 0 && $nlz == 0) { + $dietsum = round($timerecording['time']['diet'], 2); + if ($export == 1) { + $dietsum = str_replace(".", ",", $dietsum); + $bodyarray = [$monthbmd, $companybmd, $employee_number, "2500", "", "", $dietsum, "", "", "", ""]; + fputcsv($file, $bodyarray, ";"); + } else { + $reponse[$employee_number]['diet'] = $dietsum; + } + } + if (!empty($timerecording['time']['nlztimes']) && ($nlz == 1 || $export == 0)) { + foreach ($timerecording['time']['nlztimes'] as $nlztime) { + if (strtotime($nlztime['start']) < $month) { + $nlztime['start'] = date("d.m.Y", $month); + } + if ((strtotime($nlztime['end']) + 84599) > $monthend) { + $nlztime['end'] = date("d.m.Y", $monthend); + } + + + if (strpos($nlztime['categoryshort'], '6-') !== false) { + $catExtended = explode("-", $nlztime['categoryshort']); + $catExtended = $catExtended[1]; + $nlztime['categoryshort'] = "6"; + } else { + $catExtended = ""; + } + + if ($nlztime['minutes']) { + $timesecounds = $nlztime['minutes']; + $time = $nlztime['minutes'] / 60; + $time = round($time, 2); + $time = str_replace(".", ",", $time); + if ($nlztime['unpaid'] == "0") { + $pay = $time; + } else { + $pay = 0; + } + + } else { + if (empty($catExtended)) { + $time = ""; + $timesecounds = ""; + $pay = ""; + } else { + //calc days from $nlztime['start'] to $nlztime['end'] + $start = strtotime($nlztime['start']); + $end = strtotime($nlztime['end']); + $time = ($end - $start); + $timesecounds = $time; + $time = $time / 86400 + 1; + $time = round($time, 0); + + + if ($nlztime['unpaid'] == "0") { + $pay = $time; + } else { + $pay = 0; + } + } + + } + if ($export == 1) { + $bodyarray = [$companybmd, $employee_number, 1, $nlztime['categoryshort'], $catExtended, "3", $nlztime['start'], $nlztime['end'], $time, $pay]; + fputcsv($file, $bodyarray, ";"); + } else { + $reponse[$employee_number]['nlz'][] = array("categoryshort" => $nlztime['categoryshort'], "catExtended" => $catExtended, "start" => $nlztime['start'], "end" => $nlztime['end'], "time" => $time, "pay" => $pay); + } + + + } + if ($export == 0) { + $reponse[$employee_number]['daysum'] = json_encode($timerecording['time']['daysum']); + } + } + + } + if ($export == 1) { + fclose($file); + exit; + } else { + return $reponse; + } + + + } + + protected function completemonth($month) + { + $id = $this->saveAction(); + $user = new User($timerecordingsEmolyee->user_id); + $employee_number = (string)$user->getFlag('employee_number'); + + $timerecordings = $this->generateBmdExport($month, 0, 0); + foreach ($timerecordings as $employeenumber => $timerecording) { + $data = []; + $data['timerecordingBilling_id'] = $id; + $data['timerecordingEmployee_id'] = $timerecording['employee_id']; + $data['musthours'] = $timerecording['musttime']; + if ($timerecording['istime']) { + $data['ishours'] = $timerecording['istime']; + } else { + $data['ishours'] = 0; + } + $data['ishourssum'] = $timerecording['istimeall']; + $data['diet'] = $timerecording['diet']; + if ($timerecording['nlz']) { + $data['nlz_detail'] = json_encode($timerecording['nlz']); + } + if ($timerecording['daysum']) { + $data['nlz'] = $timerecording['daysum']; + } + if ($timerecording['homeoffice']) { + $data['homeoffice'] = $timerecording['homeoffice']; + } + + + if (!$data['diet']) { + $data['diet'] = 0; + + } + + $timerecordingbillingemployee = TimerecordingBillingEmployeeModel::create($data); + $timerecordingbillingemployee->save(); + } + $result['state'] = "success"; + echo json_encode($result); + die(); + } + + protected function saveovertime() + { + $id = $this->request->id; + $type = $this->request->type; + $timerecordingbillingsemployee = new TimerecordingBillingEmployee($id); + if ($type == "overtime") { + $sum = 0; + $data = []; + if ($this->request->overtime50) { + $data['overtime50free'] = $timerecordingbillingsemployee->overtime50free + $this->request->overtime50 * 3600; + $sum += $this->request->overtime50 * 3600; + } + if ($this->request->overtime100) { + $data['overtime100free'] = $timerecordingbillingsemployee->overtime100free + $this->request->overtime100 * 3600; + $sum += $this->request->overtime100 * 3600; + } + if ($this->request->overtimebpa) { + $timerecordingbillingsemployee->timerecordingEmployee->id; + $timerecordingEmployee = new TimerecordingEmployee($timerecordingbillingsemployee->timerecordingEmployee->id); + $dataemployee = []; + $dataemployee['bpahours'] = $timerecordingEmployee->bpahours + $this->request->overtimebpa * 3600; + $sum += $this->request->overtimebpa * 3600; + $timerecordingEmployee->update($dataemployee); + $timerecordingEmployee->save(); + + } + if ($data) { + $timerecordingbillingsemployee->update($data); + $timerecordingbillingsemployee->save(); + $timerecordingbillingsemployee->timerecordingEmployee->id; + $timerecordingEmployee = new TimerecordingEmployee($timerecordingbillingsemployee->timerecordingEmployee->id); + $dataemployee = []; + $dataemployee['overtime_now'] = $timerecordingEmployee->overtime_now - $sum; + $dataemployee['overtime'] = $timerecordingEmployee->overtime - $sum; + $timerecordingEmployee->update($dataemployee); + $timerecordingEmployee->save(); + } + } else if ($type == "difference") { + $sum = 0; + $data = []; + if ($this->request->overtime50) { + $data['overtime50free'] = $timerecordingbillingsemployee->overtime50free + $this->request->overtime50 * 3600; + $sum += $this->request->overtime50 * 3600; + } + if ($this->request->overtime100) { + $data['overtime100free'] = $timerecordingbillingsemployee->overtime100free + $this->request->overtime100 * 3600; + $sum += $this->request->overtime100 * 3600; + } + if ($this->request->overtimebpa) { + $timerecordingbillingsemployee->timerecordingEmployee->id; + $timerecordingEmployee = new TimerecordingEmployee($timerecordingbillingsemployee->timerecordingEmployee->id); + $dataemployee = []; + $dataemployee['bpahours'] = $timerecordingEmployee->bpahours + $this->request->overtimebpa * 3600; + $sum += $this->request->overtimebpa * 3600; + $timerecordingEmployee->update($dataemployee); + $timerecordingEmployee->save(); + + } + if ($sum > 0) { + $data['ishourssum'] = $timerecordingbillingsemployee->ishourssum - $sum; + $timerecordingbillingsemployee->update($data); + $timerecordingbillingsemployee->save(); + } + } + $response['state'] = "success"; + echo json_encode($response); + die(); + } +} diff --git a/application/TimerecordingBilling/TimerecordingBillingModel.php b/application/TimerecordingBilling/TimerecordingBillingModel.php new file mode 100644 index 000000000..b6751ed67 --- /dev/null +++ b/application/TimerecordingBilling/TimerecordingBillingModel.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("TimerecordingBilling", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingBilling($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("TimerecordingBilling", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingBilling($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("TimerecordingBilling", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingBilling($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("TimerecordingBilling", "*", "$where"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingBilling($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("month", $filter)) { + $month = $filter['month']; + if ($month) { + $where .= " AND month=$month"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/TimerecordingBillingEmployee/TimerecordingBillingEmployee.php b/application/TimerecordingBillingEmployee/TimerecordingBillingEmployee.php new file mode 100644 index 000000000..b8d95f194 --- /dev/null +++ b/application/TimerecordingBillingEmployee/TimerecordingBillingEmployee.php @@ -0,0 +1,61 @@ +$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/TimerecordingBillingEmployee/TimerecordingBillingEmployeeController.php b/application/TimerecordingBillingEmployee/TimerecordingBillingEmployeeController.php new file mode 100644 index 000000000..c75745430 --- /dev/null +++ b/application/TimerecordingBillingEmployee/TimerecordingBillingEmployeeController.php @@ -0,0 +1,172 @@ +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("TimerecordingBillingEmployee/Index"); + $timerecordingbillingemployees = TimerecordingBillingEmployeeModel::getAll(); + $this->layout()->set("timerecordingbillingemployees", $timerecordingbillingemployees); + + } + + protected function addAction() + { + $timerecordingBillingEmployees = TimerecordingBillingEmployeeModel::getAll(); + $this->layout()->set("timerecordingBillingEmployees", $timerecordingBillingEmployees); + $timerecordingEmployees = TimerecordingEmployeeModel::getAll(); + $this->layout()->set("timerecordingEmployees", $timerecordingEmployees); + + $this->layout()->setTemplate("TimerecordingBillingEmployee/Form"); + + } + + protected function editAction() + { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("fdfsdf nicht gefunden", "error"); + $this->redirect("TimerecordingBillingEmployee"); + } + + $timerecordingbillingemployees = new TimerecordingBillingEmployee($id); + if ($timerecordingbillingemployees->id != $id) { + $this->layout()->setFlash("fdfsdf nicht gefunden", "error"); + $this->redirect("TimerecordingBillingEmployee"); + } + + $this->layout()->set("timerecordingbillingemployees", $timerecordingbillingemployees); + 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"; + $timerecordingbillingemployees = new TimerecordingBillingEmployee($id); + if (!$timerecordingbillingemployees->id) { + $this->layout()->setFlash("dfsdfsdfds nicht gefunden", "error"); + $this->redirect("TimerecordingBillingEmployee"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['timerecordingBillingEmployee_id'] = trim($r->timerecordingBillingEmployee_id); + $data['timerecordingEmployee_id'] = trim($r->timerecordingEmployee_id); + $data['type'] = trim($r->type); + $data['ishours'] = trim($r->ishours); + $data['overtime25'] = trim($r->overtime25); + $data['plushours50'] = trim($r->plushours50); + $data['plushours50free'] = trim($r->plushours50free); + $data['plushours100'] = trim($r->plushours100); + $data['plushours100free'] = trim($r->plushours100free); + $data['homeoffice'] = trim($r->homeoffice); + $data['diet'] = trim($r->diet); + $data['nlz'] = trim($r->nlz); + $data['nlz_detail'] = trim($r->nlz_detail); + + + if (!$data['timerecordingBillingEmployee_id']) { + $data['timerecordingBillingEmployee_id'] = NULL; + } + if (!$data['timerecordingEmployee_id']) { + $data['timerecordingEmployee_id'] = NULL; + } + if (!$data['type']) { + $data['type'] = NULL; + } + if (!$data['ishours']) { + $data['ishours'] = NULL; + } + if (!$data['overtime25']) { + $data['overtime25'] = NULL; + } + if (!$data['plushours50']) { + $data['plushours50'] = NULL; + } + if (!$data['plushours50free']) { + $data['plushours50free'] = NULL; + } + if (!$data['plushours100']) { + $data['plushours100'] = NULL; + } + if (!$data['plushours100free']) { + $data['plushours100free'] = NULL; + } + if (!$data['homeoffice']) { + $data['homeoffice'] = NULL; + } + if ($data['diet'] == NULL) { + $data['diet'] = 0; + } + if (!$data['nlz']) { + $data['nlz'] = NULL; + } + if (!$data['nlz_detail']) { + $data['nlz_detail'] = NULL; + } + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $timerecordingbillingemployees->update($data); + + } else { + $timerecordingbillingemployees = TimerecordingBillingEmployeeModel::create($data); + } +// var_dump($filestore); +// exit; + $id = $timerecordingbillingemployees->save(); + + if (!$id) { + $this->layout()->setFlash("fdfsdf konnte nicht angelegt werden", "error"); + $this->redirect("TimerecordingBillingEmployee"); + } + + if ($mode == "edit") { + $this->layout()->setFlash("fdfsdf erfolgreich geändert", "success"); + } else if ($mode = "add") { + $this->layout()->setFlash("fdfsdf erfolgreich angelegt", "success"); + } + $this->redirect("TimerecordingBillingEmployee"); + } + + + protected function deleteAction() + { + $id = $this->request->id; + $timerecordingbillingemployees = new TimerecordingBillingEmployee($id); + if (!$timerecordingbillingemployees->id || $timerecordingbillingemployees->id != $id) { + $this->layout()->setFlash("fdfsdf nicht gefunden.", "error"); + $this->redirect("TimerecordingBillingEmployee"); + } + + $timerecordingbillingemployees->delete(); + $this->redirect("TimerecordingBillingEmployee"); + } + +} diff --git a/application/TimerecordingBillingEmployee/TimerecordingBillingEmployeeModel.php b/application/TimerecordingBillingEmployee/TimerecordingBillingEmployeeModel.php new file mode 100644 index 000000000..c7f69fd18 --- /dev/null +++ b/application/TimerecordingBillingEmployee/TimerecordingBillingEmployeeModel.php @@ -0,0 +1,139 @@ + $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("TimerecordingBillingEmployee", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingBillingEmployee($data); + } + return $item; + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("TimerecordingBillingEmployee", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingBillingEmployee($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("TimerecordingBillingEmployee", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingBillingEmployee($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("TimerecordingBillingEmployee", "*", "$where"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingBillingEmployee($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("timerecordingBilling_id", $filter)) { + $timerecordingBilling_id = $filter['timerecordingBilling_id']; + if (is_numeric($timerecordingBilling_id)) { + $where .= " AND timerecordingBilling_id='$timerecordingBilling_id'"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/TimerecordingCar/TimerecordingCar.php b/application/TimerecordingCar/TimerecordingCar.php new file mode 100644 index 000000000..01f300927 --- /dev/null +++ b/application/TimerecordingCar/TimerecordingCar.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/TimerecordingCar/TimerecordingCarController.php b/application/TimerecordingCar/TimerecordingCarController.php new file mode 100644 index 000000000..84277f341 --- /dev/null +++ b/application/TimerecordingCar/TimerecordingCarController.php @@ -0,0 +1,179 @@ +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("TimerecordingCar/Index"); + $timerecordingcars = TimerecordingCarModel::getAll(); + $this->layout()->set("timerecordingcars", $timerecordingcars); + + } + + protected function detailAction() + { + $timerecordingcarid = $this->request->id; + $this->layout()->setTemplate("TimerecordingCar/Detail"); + $timerecordingcar = TimerecordingCarModel::getOne($timerecordingcarid); + $this->layout()->set("timerecordingcar", $timerecordingcar); + $timerecordings = TimerecordingModel::search(["timerecordingCar_id_all" => $timerecordingcarid]); + $this->layout()->set("timerecordings", $timerecordings); + + } + + protected function addAction() + { + $timerecordingusers = UserModel::search(['employee' => 'true']); + $this->layout()->set("timerecordingusers", $timerecordingusers); + $this->layout()->setTemplate("TimerecordingCar/Form"); + + } + + protected function editAction() + { + $id = $this->request->id; + + if (!is_numeric($id) || !$id) { + $this->layout()->setFlash("Auto nicht gefunden", "error"); + $this->redirect("TimerecordingCar"); + } + + $timerecordingcars = new TimerecordingCar($id); + if ($timerecordingcars->id != $id) { + $this->layout()->setFlash("Auto nicht gefunden", "error"); + $this->redirect("TimerecordingCar"); + } + + + $this->layout()->set("timerecordingcars", $timerecordingcars); + 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"; + $timerecordingcars = new TimerecordingCar($id); + if (!$timerecordingcars->id) { + $this->layout()->setFlash("Autos nicht gefunden", "error"); + $this->redirect("TimerecordingCar"); + } + } else { + $mode = "add"; + } + + $data = []; + $data['number_plate'] = trim($r->number_plate); + $data['user_id'] = trim($r->user_id); + $data['brand'] = trim($r->brand); + $data['model'] = trim($r->model); + $data['mileage'] = trim($r->mileage); + $data['initial_approval'] = strtotime($r->initial_approval); + $data['timerecording'] = $r->timerecording; + $data['first_approval'] = trim($r->first_approval); + + + if (!$data['user_id'] || $data['user_id'] == "-") { + $data['user_id'] = null; + } + if (!$data['initial_approval']) { + $data['initial_approval'] = null; + } + + if (!$data['timerecording']) { + $data['timerecording'] = 0; + } + if (!$data['mileage']) { + $data['mileage'] = null; + } + + if (!$data['first_approval'] || trim($data['first_approval']) == "") { + $data['first_approval'] = null; + } + + if (!$data['number_plate']) { + $this->layout()->setFlash("Kennzeichen darf nicht leer sein", "error"); + $this->redirect("TimerecordingCar"); + } + if (!$data['brand']) { + $this->layout()->setFlash("Marke darf nicht leer sein", "error"); + $this->redirect("TimerecordingCar"); + } + if (!$data['model']) { + $this->layout()->setFlash("Model/Typ darf nicht leer sein", "error"); + $this->redirect("TimerecordingCar"); + } + + +// var_dump($_FILES); +// var_dump($upload); +// exit; + + + if ($mode == "edit") { + $timerecordingcars->update($data); + + } else { + $timerecordingcars = TimerecordingCarModel::create($data); + } +// var_dump($filestore); +// exit; + $id = $timerecordingcars->save(); + + $returnUrl = "TimerecordingCar"; + $returnAction = "Index"; + $returnVariables = array(); + $returnAnker = ""; + if ($this->request->returnto == "detail") { + $returnUrl = "TimerecordingCar"; + $returnAction = "detail"; + $returnVariables = array("id" => $id); + + } + TimerecordingCarModel::calcMileage(); + if (!$id) { + $this->layout()->setFlash("Auto konnte nicht angelegt werden", "error"); + $this->redirect("TimerecordingCar"); + } + + if ($mode == "edit") { + $this->layout()->setFlash("Auto erfolgreich geändert", "success"); + } else if ($mode = "add") { + $this->layout()->setFlash("Auto erfolgreich angelegt", "success"); + } + $this->redirect($returnUrl, $returnAction, $returnVariables, $returnAnker); + } + + + protected function deleteAction() + { + $id = $this->request->id; + $timerecordingcars = new TimerecordingCar($id); + if (!$timerecordingcars->id || $timerecordingcars->id != $id) { + $this->layout()->setFlash("Auto nicht gefunden.", "error"); + $this->redirect("TimerecordingCar"); + } + + $timerecordingcars->delete(); + $this->redirect("TimerecordingCar"); + } + +} diff --git a/application/TimerecordingCar/TimerecordingCarModel.php b/application/TimerecordingCar/TimerecordingCarModel.php new file mode 100644 index 000000000..d77f3fef6 --- /dev/null +++ b/application/TimerecordingCar/TimerecordingCarModel.php @@ -0,0 +1,157 @@ + $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("TimerecordingCar", "*", "id=$id LIMIT 1"); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingCar($data); + } + return $item; + } + + public static function calcMileage() + { + $TimerecordingCars = self::getAll(); + foreach ($TimerecordingCars as $TimerecordingCar) { + $timerecording = TimerecordingModel::search(["timerecordingCar_id" => $TimerecordingCar->id]); + if (!$timerecording) { + if ($TimerecordingCar->mileage_now != $TimerecordingCar->mileage) { + $TimerecordingCar->mileage_now = $TimerecordingCar->mileage; + $TimerecordingCar->save(); + } + } else { + if (!$TimerecordingCar->mileage_now || $TimerecordingCar->mileage_now < $timerecording[0]->mileage_end) { + $TimerecordingCar->mileage_now = $timerecording[0]->mileage_end; + $TimerecordingCar->save(); + } else if ($timerecording[0]->mileage_end < $TimerecordingCar->mileage) { + $TimerecordingCar->mileage_now = $TimerecordingCar->mileage; + $TimerecordingCar->save(); + } + } + } + + } + + public static function getAll() + { + $items = []; + + $db = FronkDB::singleton(); + + $res = $db->select("TimerecordingCar", "*", "1=1"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingCar($data); + } + } + return $items; + + } + + public static function getFirst() + { + $db = FronkDB::singleton(); + + $where = self::getSqlFilter($filter); + $res = $db->select("TimerecordingCar", "*", "$where "); + if ($db->num_rows($res)) { + $data = $db->fetch_object($res); + $item = new TimerecordingCar($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("TimerecordingCar", "*", "$where"); + if ($db->num_rows($res)) { + while ($data = $db->fetch_object($res)) { + $items[] = new TimerecordingCar($data); + } + } + return $items; + } + + private static function getSqlFilter($filter) + { + $where = "1=1 "; + + //var_dump($filter);exit; + if (array_key_exists("timerecording", $filter)) { + $timerecording = $filter['timerecording']; + if (is_numeric($timerecording)) { + $where .= " AND timerecording=$timerecording"; + } + } + + //var_dump($filter, $where);exit; + return $where; + } + +} diff --git a/application/TimerecordingCategory/TimerecordingCategoryController.php b/application/TimerecordingCategory/TimerecordingCategoryController.php index 561298780..1b4f115d1 100644 --- a/application/TimerecordingCategory/TimerecordingCategoryController.php +++ b/application/TimerecordingCategory/TimerecordingCategoryController.php @@ -87,6 +87,7 @@ class TimerecordingCategoryController extends mfBaseController $data['require_comment'] = trim($r->require_comment); $data['only_admin'] = trim($r->only_admin); $data['businesstrip'] = trim($r->businesstrip); + $data['unpaid'] = trim($r->unpaid); if (!$data['name']) { @@ -107,6 +108,9 @@ class TimerecordingCategoryController extends mfBaseController if (!$data['businesstrip']) { $data['businesstrip'] = 0; } + if (!$data['unpaid']) { + $data['unpaid'] = 0; + } // var_dump($_FILES); // var_dump($upload); // exit; diff --git a/application/TimerecordingCategory/TimerecordingCategoryModel.php b/application/TimerecordingCategory/TimerecordingCategoryModel.php index 1d343e2d2..eaa7a89be 100644 --- a/application/TimerecordingCategory/TimerecordingCategoryModel.php +++ b/application/TimerecordingCategory/TimerecordingCategoryModel.php @@ -9,7 +9,8 @@ class TimerecordingCategoryModel private $require_comment; private $only_admin; private $businesstrip; - public static $hourday_definition = array(1 => "Uhrzeit (von/bis)", 2 => "Tage (von/bis)", 3 => "Startdatum", 4 => "Enddatum", 5 => "Anzahl Tage", 6 => "ZA Uhrzeit (von/bis)"); + private $unpaid; + public static $hourday_definition = array(1 => "Uhrzeit (von/bis)", 2 => "Tage (von/bis)", 3 => "Startdatum", 4 => "Enddatum", 5 => "Anzahl Tage", 6 => "ZA Uhrzeit (von/bis)", 7 => "Fahrtenbuch (von/bis)"); public static $approval_definition = array(0 => "Nein", 1 => "Ja"); public static $require_comment_definition = array(0 => "Nein", 1 => "Ja"); public static $businesstrip_definition = array(0 => "Nein", 1 => "Ja"); diff --git a/application/TimerecordingEmployee/TimerecordingEmployeeController.php b/application/TimerecordingEmployee/TimerecordingEmployeeController.php index 9d1110968..52493034d 100644 --- a/application/TimerecordingEmployee/TimerecordingEmployeeController.php +++ b/application/TimerecordingEmployee/TimerecordingEmployeeController.php @@ -114,13 +114,21 @@ class TimerecordingEmployeeController extends mfBaseController $data['holidays'] = trim($r->holidays); $data['plushours'] = $plushours; $data['startdate'] = strtotime($r->startdate); + $data['enddate'] = strtotime($r->enddate); $data['type'] = trim($r->type); + $data['bmd_active'] = trim($r->bmd_active); $data['overtime'] = $overtime; # if (!$data['overtime']) { $data['overtime'] = 0; } + if (!$data['bmd_active']) { + $data['bmd_active'] = 0; + } + if (!$data['enddate']) { + $data['enddate'] = null; + } if ($r->birthday) { $data['birthday'] = strtotime($r->birthday); diff --git a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php index a76f9a4a7..b42acc1ce 100644 --- a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php +++ b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php @@ -16,7 +16,10 @@ class TimerecordingEmployeeModel private $overtime_timestamp; private $bpahours; private $startdate; + private $enddate; + private $bmd_active; private $birthday; + public static $employeetypesbmd = array('1' => '1000', '2' => '1200', '3' => '1400'); public static function find($data) diff --git a/application/TimerecordingReport/TimerecordingReportController.php b/application/TimerecordingReport/TimerecordingReportController.php index 8c4722f1f..7e4b18f54 100644 --- a/application/TimerecordingReport/TimerecordingReportController.php +++ b/application/TimerecordingReport/TimerecordingReportController.php @@ -25,6 +25,8 @@ class TimerecordingReportController extends mfBaseController $this->layout()->set("timerecordingusers", $timerecordingusers); $timerecordings = TimerecordingModel::getAll(); $this->layout()->set("timerecordings", $timerecordings); + $timerecordingCars = TimerecordingCarModel::search(['timerecording' => 1]); + $this->layout()->set("timerecordingCars", $timerecordingCars); } protected function apiAction() @@ -57,7 +59,7 @@ class TimerecordingReportController extends mfBaseController $this->returnJson($data); } - protected function getTimerecordingsApi($datatype, $dataweek, $datamonth, $datayear) + public function getTimerecordingsApi($datatype, $dataweek, $datamonth, $datayear) { $mustSeconds = 0; $isSeconds = 0; @@ -290,6 +292,16 @@ class TimerecordingReportController extends mfBaseController $sum = "-" . sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); $day = $daysgerm[date("w", $timerecording->start)]; $isSeconds = $isSeconds + $seconds; + } else if ($timerecording->timerecordingCategory->hourday == 7) { + $date = date("d.m.Y", $timerecording->start); + $datadate = date("Y-m-d", $timerecording->start); + $start = date("H:i", $timerecording->start); + $end = date("H:i", $timerecording->end); + $seconds = $timerecording->end - $timerecording->start; + $minutes = floor(($seconds % 3600) / 60); + $hours = floor($seconds / 3600); + $sum = sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); + $day = $daysgerm[date("w", $timerecording->start)]; } if ($timerecording->timerecordingCategory->approval == 1 && $timerecording->approved == 0) { @@ -298,8 +310,17 @@ class TimerecordingReportController extends mfBaseController $state = ''; } $edit = ""; - if ($timerecording->businesstrip == 1) { - $category = "" . $timerecording->timerecordingCategory->name . " (Dienstreise: " . $timerecording->businesstrip_info . ")"; + if ($timerecording->timerecordingCategory->hourday == 7) { + $distance = $timerecording->mileage_end - $timerecording->mileage_start; + $category = "" . $timerecording->timerecordingCategory->name . "(" . $timerecording->timerecordingCar->number_plate . " " . $distance . "KM) (Zielort: " . $timerecording->businesstrip_info . ")"; + } else if ($timerecording->businesstrip == 1) { + if ($timerecording->timerecordingCar) { + $distance = $timerecording->mileage_end - $timerecording->mileage_start; + $car = " (" . $timerecording->timerecordingCar->number_plate . " " . $distance . "KM)"; + } else { + $car = ""; + } + $category = "" . $timerecording->timerecordingCategory->name . "$car (Dienstreise: " . $timerecording->businesstrip_info . ")"; } else if ($timerecording->homeoffice == 1) { $category = "" . $timerecording->timerecordingCategory->name . " (Homeoffice)"; } else { @@ -322,15 +343,18 @@ class TimerecordingReportController extends mfBaseController data-userid="' . $timerecording->user_id . '" data-businesstrip="' . $timerecording->businesstrip . '" data-businesstripinfo="' . $timerecording->businesstrip_info . '" - data-homeoffice="' . $timerecording->homeoffice . '" - data-days="' . $timerecording->days . '" + data-homeoffice="' . $timerecording->homeoffice . '" + data-days="' . $timerecording->days . '" + data-car="' . $timerecording->timerecordingCar_id . '" + data-mileagestart="' . $timerecording->mileage_start . '" + data-mileageend="' . $timerecording->mileage_end . '" title="Bearbeiten">'; else : $edit .= '
    '; endif; $edit .= ''; endif; - if ($datatype == 3 && $timerecording->timerecordingCategory->hourday == 1) { + if ($datatype == 3 && ($timerecording->timerecordingCategory->hourday == 1 || $timerecording->timerecordingCategory->hourday == 7 || $timerecording->timerecordingCategory->hourday == 5)) { } else { $rows[] = array( 'user' => array('user' => $timerecording->user->name, 'order' => $timerecording->user->name), @@ -363,23 +387,33 @@ class TimerecordingReportController extends mfBaseController } - protected function getTimerecordingsTimes($datatype, $dataweek, $datamonth, $datayear) + public function getTimerecordingsTimes($datatype, $dataweek, $datamonth, $datayear, $user_id = NULL, $ajax = 1) { $r = $this->request; $mustSeconds = 0; $isSeconds = 0; + $isSecondscleanarray = array(); $holiDays = 0; $plusHours = 0; + $nlzTimes = array(); + $daysum = array(); + if (!$user_id) { + $user_id = $r->user_id; + } + $rows = []; - $employee = TimerecordingEmployeeModel::search(['user_id' => $r->user_id]); + $employee = TimerecordingEmployeeModel::search(['user_id' => $user_id]); if ($employee) { $holiDays = $employee[0]->holidays; $plusHours = $employee[0]->plushours; + $plusHours_now = $employee[0]->plushours_now; + $overtime_now = $employee[0]->overtime_now; $auto_workinghours = $employee[0]->auto_workinghours; $startdate = $employee[0]->startdate; + $bpahours = $employee[0]->bpahours; } - $workinghours = TimerecordingEmployeeWorkingHourModel::search(['user_id' => $r->user_id]); + $workinghours = TimerecordingEmployeeWorkingHourModel::search(['user_id' => $user_id]); $holidays = TimerecordingHolidayModel::getAll(); foreach ($workinghours as $workinghour) { @@ -402,7 +436,7 @@ class TimerecordingReportController extends mfBaseController $timestamp_sonntag = strtotime("{$year}-W{$kw}-7"); $firstdate = strtotime(date("Y-m-d", $timestamp_montag) . " 00:00:00"); $lastdate = strtotime(date("Y-m-d", $timestamp_sonntag) . ' 23:59:59'); - $searchArray = ['user_id' => $r->user_id, 'start' => $timestamp_montag, 'end' => $lastdate]; + $searchArray = ['user_id' => $user_id, 'start' => $timestamp_montag, 'end' => $lastdate]; $daycounter = '0'; @@ -422,7 +456,11 @@ class TimerecordingReportController extends mfBaseController $lastdate = strtotime(date("Y-m-t", $datamonth)); $daycount = date("t", $datamonth); $lastdate = strtotime(date("Y-m-d", $lastdate) . ' 23:59:59'); - $searchArray = ['user_id' => $r->user_id, 'start' => $firstdate, 'end' => $lastdate]; + //Lastdate staticmust deleted +// $lastdate = strtotime("2024-03-22 23:59:59"); +// $daycount=22; + + $searchArray = ['user_id' => $user_id, 'start' => $firstdate, 'end' => $lastdate]; $timestamp = $firstdate; for ($i = 1; $i <= $daycount; $i++) { @@ -441,7 +479,7 @@ class TimerecordingReportController extends mfBaseController $lastdate = strtotime(date("Y-12-31 23:59:59", $datayear)); $daycount = date("t", $datamonth); $lastdate = strtotime(date("Y-m-d", $lastdate) . ' 23:59:59'); - $searchArray = ['user_id' => $r->user_id, 'start' => $firstdate, 'end' => $lastdate]; + $searchArray = ['user_id' => $user_id, 'start' => $firstdate, 'end' => $lastdate]; $timestamp = $firstdate; for ($i = 1; $i <= $daycount; $i++) { @@ -462,14 +500,52 @@ class TimerecordingReportController extends mfBaseController $timerecordingcategories = TimerecordingCategoryModel::getAll(); $timerecordings = TimerecordingModel::search($searchArray); + $responsecount = count($timerecordings); + $oldday = ""; + $homeoffice = false; + $homeofficesum = 0; + $dietsum = 0; + $diet = 0; + $dietbase = TimerecordingBillingModel::$dieatBase; + foreach ($timerecordings as $timerecording): $state = ""; $enddate = ""; $sum = "-"; $day = ""; $orderdate = $timerecording->start; + if ($oldday != date('Y-m-d', $timerecording->start)) { + + if ($homeoffice == 1) { + $homeofficesum++; + $homeoffice = false; + } + if ($diet > 10800) { + if ($diet >= 43200) { + $diet = 43200; + } + $calcdiet = $dietbase / 12; + $calcdiet = ($diet / 3600) * $calcdiet; + $dietsum = $dietsum + $calcdiet; + } + $diet = 0; + + } + if ($timerecording->homeoffice == 1 && (!$homeoffice || $homeoffice == 1)) { + + $homeoffice = 1; + } else { + $homeoffice = 0; + } + + + if ($timerecording->businesstrip == 1 && $timerecording->timerecordingCategory->hourday == 1) { + $diet = $diet + $timerecording->end - $timerecording->start; + } + if ($timerecording->timerecordingCategory->hourday == 1) { + $date = date("d.m.Y", $timerecording->start); $datadate = date("Y-m-d", $timerecording->start); $start = date("H:i", $timerecording->start); @@ -480,6 +556,27 @@ class TimerecordingReportController extends mfBaseController $sum = sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); $day = $daysgerm[date("w", $timerecording->start)]; $isSeconds = $isSeconds + $seconds; + if ($isSecondscleanarray[$timerecording->timerecordingCategory->short]) { + $isSecondscleanarray[$timerecording->timerecordingCategory->short] = $isSecondscleanarray[$timerecording->timerecordingCategory->short] + $seconds; + } else { + $isSecondscleanarray[$timerecording->timerecordingCategory->short] = $seconds; + } + + + if ($timerecording->timerecordingCategory->short != "1000,1200,1400") { + if (!$daysum[$timerecording->timerecordingCategory->name]) { + $daysum[$timerecording->timerecordingCategory->name] = $seconds; + } else { + $daysum[$timerecording->timerecordingCategory->name] = $daysum[$timerecording->timerecordingCategory->name] + $seconds; + } + + $nlzTimes[$timerecording->id]['start'] = date("d.m.Y", $timerecording->start); + $nlzTimes[$timerecording->id]['end'] = date("d.m.Y", $timerecording->end); + $nlzTimes[$timerecording->id]['minutes'] = $seconds / 60; + $nlzTimes[$timerecording->id]['unpaid'] = $timerecording->timerecordingCategory->unpaid; + $nlzTimes[$timerecording->id]['category'] = $timerecording->timerecordingCategory->name; + $nlzTimes[$timerecording->id]['categoryshort'] = $timerecording->timerecordingCategory->short; + } } else if ($timerecording->timerecordingCategory->hourday == 2 || ($timerecording->timerecordingCategory->hourday == 3 && $timerecording->end)) { $date = date("d.m.", $timerecording->start) . " - " . $daysgerm[date("w", $timerecording->end)] . " " . date("d.m.Y", $timerecording->end); $datadate = date("Y-m-d", $timerecording->start); @@ -500,10 +597,18 @@ class TimerecordingReportController extends mfBaseController } $summcounter = 0; $savecounter = 0; + $sumdays = 0; + for ($i = $starttimecalc; $i <= $endtimecalc; $i = $i + 86400) { $holidaycounter = $workingHours[date("w", $i)]; - $isSeconds = $isSeconds + $holidaycounter; - $summcounter = $summcounter + $holidaycounter; + $daycheck = date("Y-m-d", $i); + if (!$holiDay[$daycheck]) { + if ($holidaycounter) { + $isSeconds = $isSeconds + $holidaycounter; + $summcounter = $summcounter + $holidaycounter; + $sumdays++; + } + } if ($savecounter == 1000) { echo $savecounter; die(); @@ -513,7 +618,24 @@ class TimerecordingReportController extends mfBaseController $seconds = $summcounter; $minutes = floor(($seconds % 3600) / 60); $hours = floor($seconds / 3600); - $sum = sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); +// $sum = sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); + if ($sumdays == 1 || $sumdays == 0) { + $sum = $sumdays . " Tag"; + } else if ($sumdays > 1) { + $sum = $sumdays . " Tage"; + } + + if (!$daysum[$timerecording->timerecordingCategory->name]) { + $daysum[$timerecording->timerecordingCategory->name] = $sumdays; + } else { + $daysum[$timerecording->timerecordingCategory->name] = $daysum[$timerecording->timerecordingCategory->name] + $sumdays; + } + $nlzTimes[$timerecording->id]['start'] = date("d.m.Y", $timerecording->start); + $nlzTimes[$timerecording->id]['end'] = date("d.m.Y", $timerecording->end); + $nlzTimes[$timerecording->id]['days'] = $sumdays; + $nlzTimes[$timerecording->id]['unpaid'] = $timerecording->timerecordingCategory->unpaid; + $nlzTimes[$timerecording->id]['category'] = $timerecording->timerecordingCategory->name; + $nlzTimes[$timerecording->id]['categoryshort'] = $timerecording->timerecordingCategory->short; } else if ($timerecording->timerecordingCategory->hourday == 3 && !$timerecording->end) { $date = date("d.m.Y", $timerecording->start) . " - " . $daysgerm[date("w", time())] . " " . date("d.m.Y", time());; @@ -554,6 +676,18 @@ class TimerecordingReportController extends mfBaseController $end = "-"; $day = $daysgerm[date("w", $timerecording->start)]; $sum = $timerecording->days . " Tage"; + } else if ($timerecording->timerecordingCategory->hourday == 6) { + $date = date("d.m.Y", $timerecording->start); + $datadate = date("Y-m-d", $timerecording->start); + $start = date("H:i", $timerecording->start); + $end = date("H:i", $timerecording->end); +// $seconds = $timerecording->hours; + $seconds = $timerecording->end - $timerecording->start; + $minutes = floor(($seconds % 3600) / 60); + $hours = floor($seconds / 3600); + $sum = "-" . sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); + $day = $daysgerm[date("w", $timerecording->start)]; + $isSeconds = $isSeconds + $seconds; } if ($timerecording->timerecordingCategory->approval == 1 && $timerecording->approved == 0) { @@ -593,18 +727,75 @@ class TimerecordingReportController extends mfBaseController } else { } + $oldday = date('Y-m-d', $timerecording->start); endforeach; + if ($homeoffice == 1) { + $homeofficesum++; + $homeoffice = 0; + } + if ($diet > 10800) { + if ($diet >= 43200) { + $diet = 43200; + } + $calcdiet = $dietbase / 12; + $calcdiet = ($diet / 3600) * $calcdiet; + $dietsum = $dietsum + $calcdiet; + } + + $summseconds = $isSeconds - $mustSeconds; + $isorder = $isSeconds; + if ($isSeconds < 0) { + $isSeconds = $isSeconds * -1; + $isSeconds = "-" . sprintf('%02dh:%02dm', floor($isSeconds / 3600), floor($isSeconds / 60 % 60)); + } else { + $isSeconds = sprintf('%02dh:%02dm', floor($isSeconds / 3600), floor($isSeconds / 60 % 60)); + } + $summsecondsorder = $summseconds; + if ($summseconds < 0) { + $summseconds = $summseconds * -1; + $summseconds = "-" . sprintf('%02dh:%02dm', floor($summseconds / 3600), floor($summseconds / 60 % 60)); + } else { + $summseconds = sprintf('%02dh:%02dm', floor($summseconds / 3600), floor($summseconds / 60 % 60)); + } + $plusHours_noworder = $plusHours_now; + if ($plusHours_now < 0) { + $plusHours_now = $plusHours_now * -1; + $plusHours_now = "-" . sprintf('%02dh:%02dm', floor($plusHours_now / 3600), floor($plusHours_now / 60 % 60)); + } else { + $plusHours_now = sprintf('%02dh:%02dm', floor($plusHours_now / 3600), floor($plusHours_now / 60 % 60)); + } + $json['success'] = true; $json['time']['auto_workinghours'] = $auto_workinghours; - $json['time']['is'] = sprintf('%02dh:%02dm', floor($isSeconds / 3600), floor($isSeconds / 60 % 60)); + $json['time']['is'] = $isSeconds; + $json['time']['isorder'] = $isorder; + $json['time']['isclean'] = $isSecondscleanarray; $json['time']['must'] = sprintf('%02dh:%02dm', floor($mustSeconds / 3600), floor($mustSeconds / 60 % 60)); + $json['time']['mustorder'] = $mustSeconds; $json['time']['holidays'] = $holiDays; $json['time']['plushours'] = sprintf('%02dh:%02dm', floor($plusHours / 3600), floor($plusHours / 60 % 60)); + $json['time']['plushours_now'] = $plusHours_now; + $json['time']['plushours_noworder'] = $plusHours_noworder; + $json['time']['bpahours'] = sprintf('%02dh:%02dm', floor($bpahours / 3600), floor($bpahours / 60 % 60)); + + $json['time']['overtime_now'] = sprintf('%02dh:%02dm', floor($overtime_now / 3600), floor($overtime_now / 60 % 60)); + $json['time']['overtime_noworder'] = $overtime_now; + $json['time']['homeoffice'] = $homeofficesum; + $json['time']['summseconds'] = $summseconds; + $json['time']['summsecondsorder'] = $summsecondsorder; + $json['time']['nlztimes'] = $nlzTimes; + $json['time']['diet'] = $dietsum; + $json['time']['daysum'] = $daysum; $json['recordsFiltered'] = $responsecount; $json['recordsTotal'] = $responsecount; - $json = json_encode($json); - echo trim($json); - die(); + + if ($ajax == 1) { + $json = json_encode($json); + echo trim($json); + die(); + } else { + return $json; + } } protected function addAction() diff --git a/application/VoiceCallActive/VoiceCallActive.php b/application/VoiceCallActive/VoiceCallActive.php new file mode 100644 index 000000000..da22152ae --- /dev/null +++ b/application/VoiceCallActive/VoiceCallActive.php @@ -0,0 +1,9 @@ +loadMe(); + $this->layout()->set("me", $me); + $this->me = $me; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + $this->kolmisoftMore = new KolmisoftMore($this->VOICE_PORTAL_HOST, $this->VOICE_PORTAL_API_KEY, $this->VOICE_PORTAL_USERNAME); + + } + + protected function indexAction(): void { + $this->layout()->setTemplate("VoiceCallActive/Index"); + } + + protected function apiAction() { + $do = $this->request->do; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + switch ($do) { + case "getActiveCalls": + $return = $this->getActiveCalls(); + break; + default: + $return = false; + break; + } + + if (!$return) { + $return = [ + "status" => "error", + "message" => "Invalid request." + ]; + } + + die(json_encode($return)); + } + + private function getActiveCalls(): array { + return [ + "rows" => array_reverse($this->kolmisoftMore->getActiveCalls()) + ]; + } +} \ No newline at end of file diff --git a/application/VoiceCallHistory/VoiceCallHistory.php b/application/VoiceCallHistory/VoiceCallHistory.php new file mode 100644 index 000000000..e334b4004 --- /dev/null +++ b/application/VoiceCallHistory/VoiceCallHistory.php @@ -0,0 +1,9 @@ +loadMe(); + $this->layout()->set("me", $me); + $this->me = $me; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + $this->kolmisoftMore = new KolmisoftMore($this->VOICE_PORTAL_HOST, $this->VOICE_PORTAL_API_KEY, $this->VOICE_PORTAL_USERNAME); + + } + + protected function indexAction(): void { + $this->layout()->setTemplate("VoiceCallHistory/Index"); + } + + protected function apiAction() { + $do = $this->request->do; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + switch ($do) { + case "getCalls": + $return = $this->getCalls(); + break; + case "importCallsFromToday": + $return = $this->importCallsFromToday(); + break; + default: + $return = false; + break; + } + + if (!$return) { + $return = [ + "status" => "error", + "message" => "Invalid request." + ]; + } + + die(json_encode($return)); + } + + private function importCallsFromToday(): array { + $startDate = strtotime(date("Y-m-d 0:00:00")); + $endDate = strtotime(date("Y-m-d 23:59:59")); + + $callHistory = $this->kolmisoftMore->getVoiceCallHistory($startDate, $endDate); + + return VoiceCallHistoryModel::importCallsFromKolmisoft($callHistory); + } + + private function getCalls(): array { + $json = json_decode(file_get_contents('php://input'), true); + + $filters = $json['filters'] ?? []; + $page = $json['pagination']['page'] ?? 1; + $perPage = $json['pagination']['per_page'] ?? 10; + + $calls = VoiceCallHistoryModel::getVoiceCallHistory($filters, $perPage, $perPage * $page - $perPage); + $totalRows = VoiceCallHistoryModel::countVoiceCallHistory($filters); + + return [ + "rows" => $calls, + "pagination" => [ + "page" => $page, + "total_pages" => ceil($totalRows / $perPage), + "per_page" => $perPage, + "total_rows" => intval($totalRows) + ] + ]; + + } + + +} \ No newline at end of file diff --git a/application/VoiceCallHistory/VoiceCallHistoryModel.php b/application/VoiceCallHistory/VoiceCallHistoryModel.php new file mode 100644 index 000000000..0e26604d3 --- /dev/null +++ b/application/VoiceCallHistory/VoiceCallHistoryModel.php @@ -0,0 +1,143 @@ + $value) { + if (property_exists(get_called_class(), $field)) { + $this->$field = $value; + } + } + } + + /** + * Generate SQL Filter condition (space separated) for a given column. + * + * @param string|null $filterValue The filter value to match against. + * @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(?string $filterValue, string $columnName): string { + $sql = ""; + if (!empty($filterValue)) { + $filterItems = explode(" ", $filterValue); + foreach ($filterItems as $item) { + $sql .= " AND `$columnName` LIKE '%" . $item . "%'"; + } + } + + return $sql; + } + + //TODO: combine these two functions into one + public static function importCallsFromKolmisoft($callHistory): array { + { + + $modifiedCallHistory = []; + for ($i = 0; $i < count($callHistory); $i++) { + $call = $callHistory[$i]; + $date = date("Y-m-d H:i:s", strtotime($call["calldate2"] . " UTC")); + + $modifiedCall = [ + "uid" => $call["uniqueid"], + "voice_account" => strpos($call["clid"], "Anonymous") !== false ? 'Anonymous' : preg_replace('/[^0-9]/', '', explode(" ", $call["clid"])[0]), + "start" => $date, + "source" => strpos($call["clid"], "nymous") !== false ? 'Anonymous' : str_replace("+", "", $call["src"]), + "destination" => $call["dst"], + "state" => preg_replace('/[^0-9]/', '', explode("(", $call["dispod"])[1]), + "billable" => gettype($call["did"]) === "string" ? 0 : 1, + "duration" => $call["nice_billsec"], + ]; + $modifiedCallHistory[] = $modifiedCall; + } + + $voiceHistoryImport = VoiceCallHistoryModel::importVoiceCallHistory($modifiedCallHistory); + + if ($callHistory === false) { + return [ + "status" => "error", + "message" => "Failed to import calls." + ]; + } + + return [ + "status" => "success", + "message" => $voiceHistoryImport["message"] + ]; + } + } + + public static function importVoiceCallHistory($callHistory): array { + $db = FronkDB::singleton(); + + $sql = /** @lang text */ "INSERT INTO `VoiceCallHistory` (`uid`, `voice_account`, `start`, `source`, `destination`, `state`, `billable`, `duration`) VALUES "; + $values = []; + foreach ($callHistory as $voiceCall) { + $uid = $voiceCall['uid']; + $valueStr = "(" . + ($voiceCall['uid'] === 'Anonymous' ? 'NULL' : "'$uid'") . ", " . + ($voiceCall['voice_account'] === 'Anonymous' ? 'NULL' : "'" . $voiceCall['voice_account']. "'" ) . ", '" . + $voiceCall['start'] . "', '" . + ($voiceCall['source'] === 'Anonymous' ? "NULL" : $voiceCall['source']) . "', '" . + ($voiceCall['destination'] === 'Anonymous' ? "NULL" : $voiceCall['destination'] ) . "', " . + $voiceCall['state'] . ", " . + $voiceCall['billable'] . ", " . + $voiceCall['duration'] . ")"; + + $values[] = $valueStr; + } + + $sql .= implode(", ", $values); + $sql .= " ON DUPLICATE KEY UPDATE duration = VALUES(duration)"; + + $db->query($sql); + + return [ + "message" => "Imported " . count($callHistory) . " calls to the history." + ]; + } + + public static function getSqlFilter($filters): string { + + $sql = ""; + if (isset($filters['start']['from']) && isset($filters['start']['to'])) { + $sql = " AND `start` >= FROM_UNIXTIME(" . $filters['start']['from'] . ") AND `start` <= FROM_UNIXTIME(" . $filters['start']['to'] . ")"; + } + $sql .= isset($filters['end']) ? " AND `start` <= '" . $filters['end'] . "'" : ""; + $sql .= isset($filters['source']) ? self::generateFilterCondition($filters['source'], "source") : ""; + $sql .= isset($filters['destination']) ? self::generateFilterCondition($filters['destination'], "destination") : ""; + $sql .= isset($filters['billable']) ? self::generateFilterCondition($filters['billable'], "billable") : ""; + $sql .= isset($filters['duration']) ? self::generateFilterCondition($filters['duration'], "duration") : ""; + + return $sql . " ORDER BY `start` DESC"; + } + + public static function getVoiceCallHistory($filters, $limit = null, $offset = 0): array { + $db = FronkDB::singleton(); + $sql = "SELECT * FROM `VoiceCallHistory` WHERE 1 " . self::getSqlFilter($filters); + $sql .= $limit === null ? "" : " LIMIT " . $limit . " OFFSET " . $offset; + + $result = $db->query($sql); + $rows = []; + while ($row = $result->fetch_assoc()) { + $rows[] = new VoiceCallHistoryModel($row); + } + + return $rows; + } + + public static function countVoiceCallHistory($filters) { + $db = FronkDB::singleton(); + $sql = "SELECT COUNT(*) as `total_rows` FROM `VoiceCallHistory` WHERE 1 " . self::getSqlFilter($filters); + $result = $db->query($sql); + return $result->fetch_assoc()['total_rows']; + } +} \ No newline at end of file diff --git a/application/VoiceCallHistoryJob/VoiceCallHistoryJob.php b/application/VoiceCallHistoryJob/VoiceCallHistoryJob.php new file mode 100644 index 000000000..6dbe12e62 --- /dev/null +++ b/application/VoiceCallHistoryJob/VoiceCallHistoryJob.php @@ -0,0 +1,9 @@ +loadMe(); + $this->layout()->set("me", $me); + $this->me = $me; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + $this->kolmisoftMore = new KolmisoftMore($this->VOICE_PORTAL_HOST, $this->VOICE_PORTAL_API_KEY, $this->VOICE_PORTAL_USERNAME); + + } + + protected function indexAction(): void { + $this->layout()->setTemplate("VoiceCallHistoryJob/Index"); + } + + protected function apiAction() { + $do = $this->request->do; + + if (!$this->me->isAdmin()) { + $this->redirect("dashboard"); + } + + switch ($do) { + case "runJobs": + $return = $this->runJobs(); + break; + default: + $return = false; + break; + } + + if (!$return) { + $return = [ + "status" => "error", + "message" => "Invalid request." + ]; + } + + die(json_encode($return)); + } + + public function runJobs(): array { + VoiceCallHistoryJobModel::createJobsUntilToday(); + + $jobs = VoiceCallHistoryJobModel::getJobsNotDone(); + + $messages = [ + "success" => [], + "error" => [] + ]; + foreach ($jobs as $job) { + $startDate = strtotime(date("Y-m-d 00:00:00", strtotime($job->date))); + $endDate = strtotime(date("Y-m-d 00:00:00", strtotime($job->date . " +1 day"))); + + $callHistory = $this->kolmisoftMore->getVoiceCallHistory($startDate, $endDate); + + $importedCalls = VoiceCallHistoryModel::importCallsFromKolmisoft($callHistory); + + if ($importedCalls) { + $messages["success"][$job->date] = $importedCalls["message"]; + VoiceCallHistoryJobModel::updateJobStatus($job->id, "success"); + } else { + $messages["error"][$job->date] = "Failed to import calls for job $job->id."; + VoiceCallHistoryJobModel::updateJobStatus($job->id, "failed"); + } + } + + return $messages; + } +} \ No newline at end of file diff --git a/application/VoiceCallHistoryJob/VoiceCallHistoryJobModel.php b/application/VoiceCallHistoryJob/VoiceCallHistoryJobModel.php new file mode 100644 index 000000000..42d540f57 --- /dev/null +++ b/application/VoiceCallHistoryJob/VoiceCallHistoryJobModel.php @@ -0,0 +1,86 @@ + $value) { + if (property_exists(get_called_class(), $field)) { + $this->$field = $value; + } + } + } + + /** + * Generate SQL Filter condition (space separated) for a given column. + * + * @param string|null $filterValue The filter value to match against. + * @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(?string $filterValue, string $columnName): string { + $sql = ""; + if (!empty($filterValue)) { + $filterItems = explode(" ", $filterValue); + foreach ($filterItems as $item) { + $sql .= " AND `$columnName` LIKE '%" . $item . "%'"; + } + } + + return $sql; + } + + public static function createJobsUntilToday(): array { + $db = FronkDB::singleton(); + + // $i = first day of the month; $i <= today; $i += 1 day + $values = []; + for ($i = strtotime(date("Y-m-01")); $i <= strtotime(date("Y-m-d")); $i += 86400) { + $values[] = "('" . date("Y-m-d", $i) . "')"; + } + + $valueStr = implode(", ", $values); + + $db->query("INSERT INTO `VoiceCallHistoryJob` (`date`) VALUES $valueStr ON DUPLICATE KEY UPDATE date=VALUES(date)"); + $db->query("UPDATE `VoiceCallHistoryJob` SET `status` = 'created', `finished` = NULL WHERE `date` = '" . date("Y-m-d") . "'"); + + return [ + "message" => "Created " . count($values) . " jobs." + ]; + } + + public static function updateJobStatus($id, $status): array { + $db = FronkDB::singleton(); + + $escapedStatus = $db->escape($status); + $escapedId = $db->escape($id); + + $finished = $status == "success" ? ", `finished` = NOW()" : ""; + + $db->query("UPDATE `VoiceCallHistoryJob` SET `status` = '$escapedStatus' $finished WHERE `id` = $escapedId"); + + return [ + "message" => "Updated job $id status to $status." + ]; + } + + public static function getJobsNotDone(): array { + $db = FronkDB::singleton(); + + $query = $db->query("SELECT * FROM `VoiceCallHistoryJob` WHERE `status` = 'created' OR `status` = 'failed' OR `status` = 'pending' ORDER BY `date`"); + + $items = []; + if($db->num_rows($query)) { + while($data = $db->fetch_object($query)) { + $items[] = new VoiceCallHistoryJobModel($data); + } + } + return $items; + } + +} \ No newline at end of file diff --git a/config/config.sample.php b/config/config.sample.php index e3c9b6b76..42c653a8c 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -37,6 +37,7 @@ const IVT_DBPASS = ""; const IVT_DBNAME = "ivtdb"; +//Raspberry Display Configuration const XINON_RASPBERRY_DISPLAY_SSH_USER = "changeme"; const XINON_RASPBERRY_DISPLAY_SSH_PASS = "changeme"; @@ -817,4 +818,8 @@ const PDFOUTPUTPATH = BASEDIR . "/var/temp"; const GIT_BIN_PATH = "/usr/bin/git"; const PDFTOTEXT_BIN_PATH = "/usr/bin/pdftotext"; -const PDFUNITE_BIN_PATH = "/usr/bin/pdfunite"; \ No newline at end of file +const PDFUNITE_BIN_PATH = "/usr/bin/pdfunite"; + +const TT_KOLMISOFT_API_URL = "vportal.xxx.xx"; +const TT_KOLMISOFT_API_KEY = ""; +const TT_KOLMISOFT_API_USERNAME = ""; diff --git a/db/migrations/20240312154600_add_historic_ticket.php b/db/migrations/20240312154600_add_historic_ticket.php new file mode 100644 index 000000000..bb97275ff --- /dev/null +++ b/db/migrations/20240312154600_add_historic_ticket.php @@ -0,0 +1,79 @@ +getEnvironment() == "thetool") { + //HistoricTicket Table + $historicTicket = $this->table("HistoricTicket", ["signed" => true]); + + $historicTicket->addColumn("ticket_number", "integer", ["null" => true]); + $historicTicket->addColumn("ticket_verifier", "string", ["null" => false, "default" => "0", "limit" => 255]); + $historicTicket->addColumn("priority", "integer", ["null" => false, "default" => "1"]); + $historicTicket->addColumn("status_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("status", "string", ["null" => true, "limit" => 255]); + $historicTicket->addColumn("type_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("type", "string", ["null" => true, "limit" => 255]); + $historicTicket->addColumn("user_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("agent_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("contact_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("company", "string", ["null" => false, "limit" => 255]); + $historicTicket->addColumn("company_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("first_name", "string", ["null" => false, "limit" => 255]); + $historicTicket->addColumn("middle_name", "string", ["null" => false, "limit" => 255]); + $historicTicket->addColumn("last_name", "string", ["null" => false, "limit" => 255]); + $historicTicket->addColumn("email", "string", ["null" => false, "limit" => 255]); + $historicTicket->addColumn("phone", "string", ["null" => false, "limit" => 255]); + $historicTicket->addColumn("subject", "string", ["null" => false, "limit" => 255]); + $historicTicket->addColumn("ctime", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("mtime", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("muser_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("files_folder_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("unseen", "integer", ["null" => false, "default" => "1"]); + $historicTicket->addColumn("group_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("order_id", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("last_response_time", "integer", ["null" => false, "default" => "0"]); + $historicTicket->addColumn("cc_addresses", "string", ["null" => false, "limit" => 255]); + $historicTicket->save(); + + //HistoricTicketMessage Table + $historicTicketMessage = $this->table("HistoricTicketMessage", ["signed" => true]); + + $historicTicketMessage->addColumn("ticket_id", "integer", ["null" => false]); + $historicTicketMessage->addColumn("status_id", "integer", ["null" => false, "default" => "0"]); + $historicTicketMessage->addColumn("type_id", "integer", ["null" => false, "default" => "0"]); + $historicTicketMessage->addColumn("has_status", "integer", ["null" => false, "default" => "0", "limit" => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY]); + $historicTicketMessage->addColumn("has_type", "integer", ["null" => false, "default" => "0", "limit" => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY]); + $historicTicketMessage->addColumn("content", "text", ["null" => true]); + $historicTicketMessage->addColumn("attachments", "string", ["null" => false, "limit" => 255]); + $historicTicketMessage->addColumn("is_note", "integer", ["null" => false, "default" => "0", "limit" => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY]); + $historicTicketMessage->addColumn("user_id", "integer", ["null" => false, "default" => "0"]); + $historicTicketMessage->addColumn("ctime", "integer", ["null" => false]); + $historicTicketMessage->addColumn("mtime", "integer", ["null" => false]); + $historicTicketMessage->addColumn("rate_id", "integer", ["null" => false, "default" => "0"]); + $historicTicketMessage->addColumn("rate_amount", "integer", ["null" => false, "default" => "0"]); + $historicTicketMessage->addColumn("rate_hours", "integer", ["null" => false, "default" => "0"]); + $historicTicketMessage->addColumn("rate_name", "string", ["null" => false, "limit" => 255]); + $historicTicketMessage->addColumn("rate_cost_code", "string", ["null" => true, "limit" => 255]); + $historicTicketMessage->save(); + + } + + if ($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $this->table("HistoricTicket")->drop()->save(); + $this->table("HistoricTicketMessage")->drop()->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240312203000_add_domain.php b/db/migrations/20240312203000_add_domain.php new file mode 100644 index 000000000..f3a13c65a --- /dev/null +++ b/db/migrations/20240312203000_add_domain.php @@ -0,0 +1,64 @@ +getEnvironment() == "thetool") { + //Domain Table + $domainTable = $this->table("Domain", ["signed" => true]); + $domainTable->addColumn("inwxRoId", "integer", ["null" => true]); + $domainTable->addColumn("domain", "string", ["null" => true, "limit" => 255]); + $domainTable->addColumn("period", "string", ["null" => true, "limit" => 50]); + $domainTable->addColumn("crDate", "integer", ["null" => true]); + $domainTable->addColumn("exDate", "integer", ["null" => true]); + $domainTable->addColumn("reDate", "integer", ["null" => true]); + $domainTable->addColumn("upDate", "integer", ["null" => true]); + $domainTable->addColumn("transferLock", "integer", ["null" => true, "limit" => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY]); + $domainTable->addColumn("status", "string", ["null" => true, "limit" => 50]); + $domainTable->addColumn("authCode", "string", ["null" => true, "limit" => 50]); + $domainTable->addColumn("registrant", "integer", ["null" => true]); + $domainTable->addColumn("admin", "integer", ["null" => true]); + $domainTable->addColumn("tech", "integer", ["null" => true]); + $domainTable->addColumn("billing", "integer", ["null" => true]); + $domainTable->addColumn("ns", "string", ["null" => true, "limit" => 255]); + $domainTable->addColumn("pleskId", "string", ["null" => true, "limit" => 255]); + $domainTable->addColumn("pleskHostingType", "string", ["null" => true, "limit" => 255]); + $domainTable->addColumn("pleskCreated", "integer", ["null" => true]); + $domainTable->save(); + + //DomainContact Table + + $domainContactTable = $this->table("DomainContact", ["signed" => true]); + $domainContactTable->addColumn("inwxRoId", "integer", ["null" => true]); + $domainContactTable->addColumn("type", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("name", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("street", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("city", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("pc", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("cc", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("voice", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("email", "string", ["null" => true, "limit" => 255]); + $domainContactTable->addColumn("protection", "integer", ["null" => true, "limit" => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY]); + $domainContactTable->addColumn("usedCount", "integer", ["null" => true]); + $domainContactTable->addColumn("verificationStatus", "string", ["null" => true, "limit" => 255]); + $domainContactTable->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $this->table("Domain")->drop()->save(); + $this->table("DomainContact")->drop()->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240317165103_timerecording_car.php b/db/migrations/20240317165103_timerecording_car.php new file mode 100644 index 000000000..a96d000e1 --- /dev/null +++ b/db/migrations/20240317165103_timerecording_car.php @@ -0,0 +1,40 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingCar", ["signed" => true]); + $table->addColumn("number_plate", "string", ["null" => false]); + $table->addColumn("brand", "text", ["null" => true]); + $table->addColumn("model", "text", ["null" => true]); + $table->addColumn("mileage", "integer", ["null" => true]); + $table->addColumn("mileage_now", "integer", ["null" => true]); + $table->addColumn("mileage_timestamp", "integer", ["null" => true]); + $table->addColumn("initial_approval", "integer", ["null" => true]); + $table->addColumn("timerecording", "integer", ["default" => 1]); + $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("TimerecordingCar")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} +?> \ No newline at end of file diff --git a/db/migrations/20240317171644_timerecording_add_fields_car.php b/db/migrations/20240317171644_timerecording_add_fields_car.php new file mode 100644 index 000000000..165c29a2d --- /dev/null +++ b/db/migrations/20240317171644_timerecording_add_fields_car.php @@ -0,0 +1,36 @@ +getEnvironment() == "thetool") { + $table = $this->table("Timerecording", ["signed" => true]); + $table->addColumn("timerecordingCar_id", "integer", ["null" => true, "default" => NULL, "after" => "businesstrip_info"]); + $table->addColumn("mileage_start", "integer", ["null" => true, "default" => NULL, "after" => "timerecordingCar_id"]); + $table->addColumn("mileage_end", "integer", ["null" => true, "default" => NULL, "after" => "mileage_start"]); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if ($this->getEnvironment() == "thetool") { + $this->table("Timerecording")->removeColumn("timerecordingCar")->save(); + $this->table("Timerecording")->removeColumn("mileage_start")->save(); + $this->table("Timerecording")->removeColumn("mileage_end")->save(); + } + + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240326191604_timerecording_category_add_field_unpaid.php b/db/migrations/20240326191604_timerecording_category_add_field_unpaid.php new file mode 100644 index 000000000..47f64eaff --- /dev/null +++ b/db/migrations/20240326191604_timerecording_category_add_field_unpaid.php @@ -0,0 +1,30 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingCategory", ["signed" => true]); + $table->addColumn("unpaid", "integer", ["null" => false, "default" => '0', "after" => "businesstrip"]); + $table->update(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if ($this->getEnvironment() == "thetool") { + $this->table("TimerecordingCategory")->removeColumn("unpaid")->save(); + } + + if ($this->getEnvironment() == "addressdb") { + } + } +} diff --git a/db/migrations/20240328153550_timerecording_car_add_field_initialapproval.php b/db/migrations/20240328153550_timerecording_car_add_field_initialapproval.php new file mode 100644 index 000000000..fbf96264f --- /dev/null +++ b/db/migrations/20240328153550_timerecording_car_add_field_initialapproval.php @@ -0,0 +1,31 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingCar", ["signed" => true]); + $table->addColumn("first_approval", "integer", ["null" => true, "default" => NULL, "after" => "initial_approval"]); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $this->table("TimerecordingCar")->removeColumn("initial_approval")->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240401144219_timerecording_employee_add_field_bmd.php b/db/migrations/20240401144219_timerecording_employee_add_field_bmd.php new file mode 100644 index 000000000..e0190d657 --- /dev/null +++ b/db/migrations/20240401144219_timerecording_employee_add_field_bmd.php @@ -0,0 +1,31 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingEmployee", ["signed" => true]); + $table->addColumn("bmd_active", "integer", ["null" => false, "default" => 1, "after" => "bpahours"]); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $this->table("TimerecordingEmployee")->removeColumn("bmd_active")->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240402075053_timerecording_billing.php b/db/migrations/20240402075053_timerecording_billing.php new file mode 100644 index 000000000..39d5116a7 --- /dev/null +++ b/db/migrations/20240402075053_timerecording_billing.php @@ -0,0 +1,35 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingBilling", ["signed" => true]); + + $table->addColumn("month", "string", ["null" => false]); + $table->addColumn("closetime", "integer", ["null" => false]); + $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("TimerecordingBilling")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} +?> \ No newline at end of file diff --git a/db/migrations/20240402075109_timerecording_billing_employee.php b/db/migrations/20240402075109_timerecording_billing_employee.php new file mode 100644 index 000000000..ef8ef3407 --- /dev/null +++ b/db/migrations/20240402075109_timerecording_billing_employee.php @@ -0,0 +1,48 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingBillingEmployee", ["signed" => true]); + + $table->addColumn("timerecordingBilling_id", "integer", ["null" => false]); + $table->addColumn("timerecordingEmployee_id", "integer", ["null" => false]); + $table->addColumn("musthours", "integer", ["null" => false]); + $table->addColumn("ishours", "integer", ["null" => false]); + $table->addColumn("ishourssum", "integer", ["null" => false]); + $table->addColumn("plushours25", "integer", ["null" => false, "default" => "0"]); + $table->addColumn("overtime50", "integer", ["null" => false, "default" => "0"]); + $table->addColumn("overtime50free", "integer", ["null" => false, "default" => "0"]); + $table->addColumn("overtime100", "integer", ["null" => false, "default" => "0"]); + $table->addColumn("overtime100free", "integer", ["null" => false, "default" => "0"]); + $table->addColumn("homeoffice", "integer", ["null" => false, "default" => "0"]); + $table->addColumn("diet", "decimal", ["null" => false, "default" => "0", "precision" => 10, "scale" => 2]); + $table->addColumn("nlz", "text", ["null" => true]); + $table->addColumn("nlz_detail", "text", ["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("TimerecordingBillingEmployee")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} + +?> \ No newline at end of file diff --git a/db/migrations/20240403064256_timerecording_car_add_field_user.php b/db/migrations/20240403064256_timerecording_car_add_field_user.php new file mode 100644 index 000000000..61f180de2 --- /dev/null +++ b/db/migrations/20240403064256_timerecording_car_add_field_user.php @@ -0,0 +1,31 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingCar", ["signed" => true]); + $table->addColumn("user_id", "integer", ["null" => true, "after" => "id"]); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $this->table("TimerecordingCar")->removeColumn("user_id")->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240409064828_fiber_plan_dispatcher.php b/db/migrations/20240409064828_fiber_plan_dispatcher.php new file mode 100644 index 000000000..1a36c911a --- /dev/null +++ b/db/migrations/20240409064828_fiber_plan_dispatcher.php @@ -0,0 +1,39 @@ +getEnvironment() == "thetool") { + $table = $this->table("FiberPlanDispatcher", ["signed" => true]); + + $table->addColumn("network_id", "integer", ["null" => false]); + $table->addColumn("object_type", "integer", ["null" => false]); + $table->addColumn("gps_lat", "decimal", ["null" => true, "precision" => 15, "scale" => 10]); + $table->addColumn("gps_long", "decimal", ["null" => true, "precision" => 15, "scale" => 10]); + $table->addColumn("description", "text", ["null" => false]); + $table->addColumn("type", "text", ["null" => true]); + $table->addColumn("comment", "text", ["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("FiberPlanDispatcher")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} diff --git a/db/migrations/20240409064838_fiber_plan_dispatchersleeve.php b/db/migrations/20240409064838_fiber_plan_dispatchersleeve.php new file mode 100644 index 000000000..078b0d9e0 --- /dev/null +++ b/db/migrations/20240409064838_fiber_plan_dispatchersleeve.php @@ -0,0 +1,34 @@ +getEnvironment() == "thetool") { + $table = $this->table("FiberPlanDispatchersleeve", ["signed" => true]); + + $table->addColumn("fiberPlanDispatcher_id", "integer", ["null" => false]); + $table->addColumn("name", "text", ["null" => false]); + $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("FiberPlanDispatchersleeve")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} diff --git a/db/migrations/20240410150500_add_voice_call_history.php b/db/migrations/20240410150500_add_voice_call_history.php new file mode 100644 index 000000000..a7cd27fd5 --- /dev/null +++ b/db/migrations/20240410150500_add_voice_call_history.php @@ -0,0 +1,45 @@ +getEnvironment() == "thetool") { + + //VoiceCallHistory Table + $voiceCallHistoryTable = $this->table("VoiceCallHistory", ["signed" => true]); + $voiceCallHistoryTable->addColumn("uid", "string", ["null" => false, "limit" => 255]); + $voiceCallHistoryTable->addColumn("voice_account", "string", ["null" => true, "limit" => 255]); + $voiceCallHistoryTable->addColumn("start", "datetime", ["null" => false]); + $voiceCallHistoryTable->addColumn("source", "string", ["null" => true, "limit" => 255]); + $voiceCallHistoryTable->addColumn("destination", "string", ["null" => true, "limit" => 255]); + $voiceCallHistoryTable->addColumn("state", "integer", ["null" => true]); + $voiceCallHistoryTable->addColumn("billable", "integer", ["null" => false, "limit" => \Phinx\Db\Adapter\MysqlAdapter::INT_TINY]); + $voiceCallHistoryTable->addColumn("duration", "integer", ["null" => false]); + + //VoiceCallHistory Table Indexes + $voiceCallHistoryTable->addIndex(["billable"]); + $voiceCallHistoryTable->addIndex(["voice_account"]); + $voiceCallHistoryTable->addIndex(["uid"], ["unique" => true]); + + $voiceCallHistoryTable->save(); + + //VoiceCallHistoryJob Table + $voiceCallHistoryJobTable = $this->table("VoiceCallHistoryJob", ["signed" => true]); + $voiceCallHistoryJobTable->addColumn("date", "date", ["null" => false]); + $voiceCallHistoryJobTable->addColumn("status", "enum", ["values" => ["created", "pending", "running", "success", "failed"], "default" => "created", "null" => false]); + $voiceCallHistoryJobTable->addColumn("finished", "date", ["null" => true]); + $voiceCallHistoryJobTable->addIndex(["date"], ["unique" => true]); + + $voiceCallHistoryJobTable->save(); + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $this->table("VoiceCallHistory")->drop()->save(); + $this->table("VoiceCallHistoryJob")->drop()->save(); + } + } +} diff --git a/db/migrations/20240416123342_device_add_field_parent_id.php b/db/migrations/20240416123342_device_add_field_parent_id.php new file mode 100644 index 000000000..662206069 --- /dev/null +++ b/db/migrations/20240416123342_device_add_field_parent_id.php @@ -0,0 +1,31 @@ +getEnvironment() == "thetool") { + $table = $this->table("Device", ["signed" => true]); + $table->addColumn("parent_id", "integer", ["null" => true, "after" => "devicetype_id"]); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $this->table("Device")->removeColumn("parent_id")->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} diff --git a/db/migrations/20240416144500_fiber_plan_pipe.php b/db/migrations/20240416144500_fiber_plan_pipe.php new file mode 100644 index 000000000..d05660684 --- /dev/null +++ b/db/migrations/20240416144500_fiber_plan_pipe.php @@ -0,0 +1,50 @@ +getEnvironment() == "thetool") { + $table = $this->table("FiberPlanPipe", ["signed" => true]); + + $table->addColumn("description", "text", ["null" => false]); + $table->addColumn("gisid", "text", ["null" => true]); + $table->addColumn("type", "integer", ["null" => false]); + $table->addColumn("type_description", "integer", ["null" => true]); + $table->addColumn("fiberPlanPipeTemplate_id", "integer", ["null" => true]); + $table->addColumn("length", "integer", ["null" => false]); + $table->addColumn("startpoint_type", "integer", ["null" => false]); + $table->addColumn("startpoint_network_id", "integer", ["null" => false]); + $table->addColumn("startpoint", "integer", ["null" => false]); + $table->addColumn("midpoint", "text", ["null" => true]); + $table->addColumn("entpoint_type", "integer", ["null" => false]); + $table->addColumn("endpoint_network_id", "integer", ["null" => false]); + $table->addColumn("endpoint", "integer", ["null" => false]); + $table->addColumn("status", "integer", ["null" => false]); + $table->addColumn("responsible", "integer", ["null" => false]); + $table->addColumn("responsible_text", "text", ["null" => true]); + $table->addColumn("address_id", "integer", ["null" => true]); + $table->addColumn("comment", "text", ["null" => true]); + $table->addColumn("edit_by", "integer", ["null" => false]); + $table->addColumn("create_by", "integer", ["null" => false]); + $table->addColumn("edit", "integer", ["null" => false]); + $table->addColumn("create", "integer", ["null" => false]); + $table->save(); + } + + if ($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if ($this->getEnvironment() == "thetool") { + $this->table("FiberPlanPipe")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} \ No newline at end of file diff --git a/db/migrations/20240416144521_fiber_plan_pipe_manufacturer.php b/db/migrations/20240416144521_fiber_plan_pipe_manufacturer.php new file mode 100644 index 000000000..a25203848 --- /dev/null +++ b/db/migrations/20240416144521_fiber_plan_pipe_manufacturer.php @@ -0,0 +1,33 @@ +getEnvironment() == "thetool") { + $table = $this->table("FiberPlanPipeManufacturer", ["signed" => true]); + $table->addColumn("name", "string", ["null" => false]); + $table->addColumn("colors", "text", ["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("FiberPlanPipeManufacturer")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} \ No newline at end of file diff --git a/db/migrations/20240416144535_fiber_plan_pipe_template.php b/db/migrations/20240416144535_fiber_plan_pipe_template.php new file mode 100644 index 000000000..2360807b6 --- /dev/null +++ b/db/migrations/20240416144535_fiber_plan_pipe_template.php @@ -0,0 +1,34 @@ +getEnvironment() == "thetool") { + $table = $this->table("FiberPlanPipeTemplate", ["signed" => true]); + $table->addColumn("fiberPlanPipeManufacturer_id", "integer", ["null" => false]); + $table->addColumn("pipe7x4", "integer", ["null" => true]); + $table->addColumn("pipe14x10", "integer", ["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("FiberPlanPipeTemplate")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} \ No newline at end of file diff --git a/db/migrations/20240416144626_fiber_plan_pipe_endpoint.php b/db/migrations/20240416144626_fiber_plan_pipe_endpoint.php new file mode 100644 index 000000000..e78a3196e --- /dev/null +++ b/db/migrations/20240416144626_fiber_plan_pipe_endpoint.php @@ -0,0 +1,36 @@ +getEnvironment() == "thetool") { + $table = $this->table("FiberPlanPipeEndpoint", ["signed" => true]); + $table->addColumn("fiberPlanPipe_id", "integer", ["null" => false]); + $table->addColumn("pop_id", "integer", ["null" => true]); + $table->addColumn("fiberPlanDispatcher_id", "integer", ["null" => true]); + $table->addColumn("building_id", "integer", ["null" => true]); + $table->addColumn("sort", "integer", ["null" => false]); + $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("FiberPlanPipeEndpoint")->drop()->save(); + } + if ($this->getEnvironment() == "addressdb") { + } + } +} \ No newline at end of file diff --git a/db/migrations/20240416190300_add_voice_call_history_start_index.php b/db/migrations/20240416190300_add_voice_call_history_start_index.php new file mode 100644 index 000000000..ad11b0d15 --- /dev/null +++ b/db/migrations/20240416190300_add_voice_call_history_start_index.php @@ -0,0 +1,19 @@ +getEnvironment() == "thetool") { + //VoiceCallHistory Table add start index + $this->table("VoiceCallHistory")->addIndex(["start"])->save(); + } + } + + public function down(): void { + if ($this->getEnvironment() == "thetool") { + $this->table("VoiceCallHistory")->removeIndex(["start"])->save(); + } + } +} diff --git a/lib/Inwx/Inwx.php b/lib/Inwx/Inwx.php new file mode 100644 index 000000000..6d1c6ed2f --- /dev/null +++ b/lib/Inwx/Inwx.php @@ -0,0 +1,155 @@ +username = $username; + $this->password = $password; + } + + /** + * Get the list of contacts. + * + * @param int $pageLimit + * @return array + * @throws Exception + */ + public function contactList(int $pageLimit = 300): array { + $requestData = array( + 'jsonrpc' => '2.0', + 'method' => 'contact.list', + 'params' => array( + 'user' => $this->username, + 'pass' => $this->password, + 'pagelimit' => $pageLimit, + ), + 'id' => 1 + ); + + return $this->makeRequest($requestData)['contact']; + } + + /** + * Get the list of domains. + * + * @param int $pageLimit + * @return array + * @throws Exception + */ + public function domainList(int $pageLimit = 300): array { + $requestData = array( + 'jsonrpc' => '2.0', + 'method' => 'domain.list', + 'params' => array( + 'user' => $this->username, + 'pass' => $this->password, + 'pagelimit' => $pageLimit, + ), + 'id' => 1 + ); + + return $this->makeRequest($requestData)['domain']; + } + + /** + * Check if a domain is available. + * + * @param string $domain + * @param string $tld + * @return array + * @throws Exception + */ + public function domainCheck(string $domain): array { + $requestData = array( + 'jsonrpc' => '2.0', + 'method' => 'domain.check', + 'params' => array( + 'user' => $this->username, + 'pass' => $this->password, + 'domain' => $domain + ), + 'id' => 1 + ); + + return $this->makeRequest($requestData); + } + + /** + * Get the price of a domain. + * + * @param string $domain + * @param string $priceType reg | renewal | transfer | update | trade | restore + * @return array + * @throws Exception + */ + public function domainGetDomainPrice(string $domain, string $priceType): array { + $requestData = array( + 'jsonrpc' => '2.0', + 'method' => 'domain.getdomainprice', + 'params' => array( + 'user' => $this->username, + 'pass' => $this->password, + 'domain' => $domain, + 'pricetype' => $priceType, + ), + 'id' => 1 + ); + + return $this->makeRequest($requestData); + } + + /** + * Make a request to the INWX API. + * + * @param array $requestData + * @return array + * @throws Exception + */ + private function makeRequest(array $requestData): array { + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $this->apiUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData)); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Accept: application/json' + )); + + $response = curl_exec($ch); + + if ($response === false) { + throw new Exception('cURL Error: ' . curl_error($ch)); + } + + curl_close($ch); + + $responseData = json_decode($response, true); + + if (isset($responseData['error'])) { + throw new Exception('JSON-RPC Error: ' . $responseData['error']['message']); + } + + if (!isset($responseData['resData'])) { + throw new Exception('Unexpected response format.'); + } + + return $responseData['resData']; + } +} +?> diff --git a/lib/KolmisoftMore/KolmisoftMore.php b/lib/KolmisoftMore/KolmisoftMore.php new file mode 100644 index 000000000..89c784f53 --- /dev/null +++ b/lib/KolmisoftMore/KolmisoftMore.php @@ -0,0 +1,100 @@ +host = $host; + $this->apiKey = $apiKey; + $this->username = $username; + } + + /** + * Generate hash for the given query parameters + * @param $queryParameters - Array of query parameters to generate hash + * @return string + */ + public function generateHash($queryParameters): string { + // concatenate all query parameters values in order of the array and then add apiKey to the end + + $queryString = implode('', $queryParameters); + $queryString .= $this->apiKey; + + return hash('sha1', $queryString); + } + + /** + * Make a request to the Kolmisoft API + * @param $path - API path + * @param $queryString - Query string + * @return array|bool + */ + public function makeRequest($path, $queryString) { + $url = "https://{$this->host}/billing/api/$path?$queryString"; + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + + $response = curl_exec($curl); + + try { + $response = new SimpleXMLElement($response); + } catch (Exception $e) { + return false; + } + + $response = json_decode(json_encode($response), true); + + if (is_array($response)) { + return $response; + } else { + return false; + } + } + + public function getVoiceCallHistory($startDate, $endDate) { + + $queryParameters = [ + 'period_start' => $startDate, + 'period_end' => $endDate + ]; + + $hash = $this->generateHash($queryParameters); + + $queryParameters['hash'] = $hash; + $queryParameters['u'] = $this->username; + + $queryString = http_build_query($queryParameters); + + $response = $this->makeRequest('user_calls_get', $queryString); + + if ($response) { + return $response['calls_stat']['calls']['call']; + } else { + return false; + } + + } + + public function getActiveCalls() { + $queryParameters = ['u' => $this->username]; + + $hash = $this->generateHash($queryParameters); + + $queryParameters['hash'] = $hash; + + $queryString = http_build_query($queryParameters); + + $response = $this->makeRequest('active_calls_get', $queryString); + + if ($response) { + return $response['status']['active_call']; + } else { + return false; + } + } + +} \ No newline at end of file diff --git a/lib/Plesk/Plesk.php b/lib/Plesk/Plesk.php new file mode 100644 index 000000000..d0406d99f --- /dev/null +++ b/lib/Plesk/Plesk.php @@ -0,0 +1,36 @@ +host = $host; + $this->authorization = $authorization; + } + + public function getAllDomains() { + // Implement code to fetch all configured domains using Plesk API + // You can use cURL or any HTTP client library to make API requests + // Example: + $url = "https://{$this->host}/api/v2/domains"; + $headers = array( + "Authorization: {$this->authorization}", + "Content-Type: application/json" + ); + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + + $response = curl_exec($curl); + + $response = json_decode($response, true); + + if (is_array($response)) { + return $response; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php b/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php index d3c8045c9..d8c21fe51 100644 --- a/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php +++ b/lib/mvcfronk/mfUpload/mfUpload_TmpFile.php @@ -89,8 +89,8 @@ class mfUpload_TmpFile { return false; } - $filename = preg_replace('/[^a-z0-9$()+%äöüß._-]/i', '_', $filename); - $filename = preg_replace('/[^a-z0-9$()+%äöüß\[\]&#;,._-]/i', '_', $filename); + $filename = preg_replace('/[^a-z0-9$()+%äöüÄÖÜß._-]/i', '_', $filename); + $filename = preg_replace('/[^a-z0-9$()+%äöüÄÖÜß\[\]&#;,._-]/i', '_', $filename); $parts = explode(".",$filename); $ext = strtolower(array_pop($parts)); diff --git a/public/js/pages/timerecording/index.js b/public/js/pages/timerecording/index.js index ad7b846a1..c2bf0611b 100644 --- a/public/js/pages/timerecording/index.js +++ b/public/js/pages/timerecording/index.js @@ -223,7 +223,25 @@ $(document).ready(function () { $(this).prop("min", ''); $(this).val(''); }) + } else if (parseInt($(this).find(':selected').data('hourday')) === 7) { + $("#endtime-div").show(); + $("#endtime-div").find('input').each(function () { + $(this).prop("required", true); + $(this).prop("disabled", false); + }); + $("#enddate-div").hide(); + $("#enddate-div").find('input').each(function () { + $(this).prop("required", false); + $(this).prop("min", ''); + $(this).val(''); + }) + $('#businesstrip_info').val(''); + $('#businesstrip_info').show(); + $('.car-div-car').show(); + } + + if (parseInt($(this).find(':selected').data('comment')) === 1) { $('#comment').prop("required", true); } else { @@ -235,11 +253,28 @@ $(document).ready(function () { $('#businesstrip').prop("checked", false); $('#businesstrip_info').val(''); $('#businesstrip_info').hide(); + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('#timerecordingCar_id').val('').change(); + $('.car-div').hide(); + } else if (parseInt($(this).find(':selected').data('hourday')) === 7) { + $('.businesstrip-div').show(); + $('.businesstrip-check-div').hide(); + $('#businesstrip').prop("checked", true); + $('#businesstrip_info').show(); + $('#businesstrip_info').prop('required', true); + $('#homeoffice-div').hide(); } else { $('.businesstrip-div').hide(); $('#businesstrip').prop("checked", false); $('#businesstrip_info').val(''); + $('#timerecordingCar_id').val('').change(); + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('.car-div').hide(); + $('#businesstrip_info').hide(); + } if (parseInt($(this).find(':selected').data('homeoffice')) === 1) { @@ -306,12 +341,26 @@ $(document).ready(function () { $('#businesstrip_info').show(); $('#businesstrip_info').prop('required', true); $('#homeoffice-div').hide(); + $('#timerecordingCar_id').val('').change(); } if ($(this).data('homeoffice') == 1) { $('.businesstrip-div').hide(); $('#homeoffice').prop("checked", true); $('#homeoffice-div').show(); } + if ($(this).data('car')) { + + $('#timerecordingCar_id').val($(this).data('car')).change(); + if ($(this).data('mileagestart')) { + $('.car-div').show(); + $('.car-div').find('input').prop("required", true); + $('#mileage_start').val($(this).data('mileagestart')); + $('#mileage_end').val($(this).data('mileageend')); + $('#mileage_end').prop("min", $(this).data('mileagestart')); + } else { + + } + } $('.alert-success').remove(); window.scrollTo(0, 0); }); @@ -324,8 +373,14 @@ $(document).ready(function () { $('#businesstrip').prop("checked", false); $('#businesstrip_info').val(''); $('#businesstrip_info').hide(); + $('#businesstrip_info').prop("required", false); $('#homeoffice').prop("checked", false); + $('.car-div').hide(); + $('.car-div').find('input').val(''); + $('.car-div').find('input').prop("required", false); + $('#timerecordingCar_id').val('').change(); $('#timerecordingCategory_id').change(); + }); $("body").on("change", "#dataweek,#datamonth,#datayear", function () { @@ -362,7 +417,7 @@ $(document).ready(function () { $('#businesstrip_info').prop('required', true); $('#homeoffice').prop('checked', false); $('#homeoffice-div').hide(); - + $('.car-div-car').show(); } else { $('#businesstrip_info').hide(); $('#businesstrip_info').val(''); @@ -376,6 +431,10 @@ $(document).ready(function () { if ($(this).prop('checked') == true) { $('#businesstrip').prop('checked', false); $('.businesstrip-div').hide(); + $('#timerecordingCar_id').val(''); + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('.car-div').hide(); $('#businesstrip_info').hide(); $('#businesstrip_info').val(''); $('#businesstrip_info').prop('required', false); @@ -414,6 +473,24 @@ $(document).ready(function () { }); + $("body").on("change", "#timerecordingCar_id", function () { + if ($('#timerecordingCar_id').val() == "") { + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('.car-div').hide(); + $('.car-div-car').show(); + } else { + $('.car-div').show(); + $('.car-div').find('input').prop("required", true); + $('#mileage_start').val($(this).find(':selected').data('mileagenow')); + $('#mileage_end').prop("min", $('#mileage_start').val()); + } + }); + + $("body").on("change", "#mileage_start", function () { + $('#mileage_end').prop("min", $('#mileage_start').val()); + }); + $("body").on("click", ".delete-item", function () { if (confirm('Buchung wirklich löschen?')) { $.post(deleteUrl, { @@ -430,12 +507,16 @@ $(document).ready(function () { $('#alert-box').remove(); var businesstrip = false; var homeoffice = false; + var car = false; if ($('#businesstrip').prop('checked') == true) { businesstrip = 1; } if ($('#homeoffice').prop('checked') == true) { homeoffice = 1; } + if ($.trim($('#timerecordingCar_id').val())) { + car = 1; + } $.post(insertUrl, { id: $.trim($('#id').val()), timerecordingCategory_id: $.trim($('#timerecordingCategory_id').val()), @@ -446,6 +527,9 @@ $(document).ready(function () { comment: $.trim($('#comment').val()), businesstrip: businesstrip, businesstrip_info: $.trim($('#businesstrip_info').val()), + timerecordingCar_id: $.trim($('#timerecordingCar_id').val()), + mileage_start: $.trim($('#mileage_start').val()), + mileage_end: $.trim($('#mileage_end').val()), homeoffice: homeoffice, hourday: $.trim($('#timerecordingCategory_id').find(':selected').data('hourday')), ajax: 1 @@ -459,10 +543,13 @@ $(document).ready(function () {
    Erfolgreich
    ` + result.message + `
    `); - $('#businesstrip').prop('checked', false); - $('#businesstrip_info').hide(); - $('#businesstrip_info').val(''); - $('#businesstrip_info').prop('required', false); + if ($.trim($('#mileage_start').val())) { + $('#timerecordingCar_id').find(':selected').data('mileagenow', $.trim($('#mileage_end').val())); + } + if (car == 1) { + $('#timerecordingCar_id').val('').change(); + } + } if (result.state === "error") { $('.wrapper .container-fluid').prepend(`
    diff --git a/public/js/pages/timerecordingReport/index.js b/public/js/pages/timerecordingReport/index.js index 92396fffd..44307a3e7 100644 --- a/public/js/pages/timerecordingReport/index.js +++ b/public/js/pages/timerecordingReport/index.js @@ -250,6 +250,22 @@ $(document).ready(function () { $('#days-div').show(); $('#days').prop("required", true); + } else if (parseInt($(this).find(':selected').data('hourday')) === 7) { + $("#endtime-div").show(); + $("#endtime-div").find('input').each(function () { + $(this).prop("required", true); + $(this).prop("disabled", false); + }); + $("#enddate-div").hide(); + $("#enddate-div").find('input').each(function () { + $(this).prop("required", false); + $(this).prop("min", ''); + $(this).val(''); + }) + $('#businesstrip_info').val(''); + $('#businesstrip_info').show(); + $('.car-div-car').show(); + } if (parseInt($(this).find(':selected').data('comment')) === 1) { $('#comment').prop("required", true); @@ -262,10 +278,25 @@ $(document).ready(function () { $('#businesstrip').prop("checked", false); $('#businesstrip_info').val(''); $('#businesstrip_info').hide(); + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('#timerecordingCar_id').val('').change(); + $('.car-div').hide(); + } else if (parseInt($(this).find(':selected').data('hourday')) === 7) { + $('.businesstrip-div').show(); + $('.businesstrip-check-div').hide(); + $('#businesstrip').prop("checked", true); + $('#businesstrip_info').show(); + $('#businesstrip_info').prop('required', true); + $('#homeoffice-div').hide(); } else { $('.businesstrip-div').hide(); $('#businesstrip').prop("checked", false); $('#businesstrip_info').val(''); + $('#timerecordingCar_id').val('').change(); + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('.car-div').hide(); $('#businesstrip_info').hide(); } @@ -342,12 +373,26 @@ $(document).ready(function () { $('#businesstrip_info').show(); $('#businesstrip_info').prop('required', true); $('#homeoffice-div').hide(); + $('#timerecordingCar_id').val('').change(); } if ($(this).data('homeoffice') == 1) { $('.businesstrip-div').hide(); $('#homeoffice').prop("checked", true); $('#homeoffice-div').show(); } + if ($(this).data('car')) { + + $('#timerecordingCar_id').val($(this).data('car')).change(); + if ($(this).data('mileagestart')) { + $('.car-div').show(); + $('.car-div').find('input').prop("required", true); + $('#mileage_start').val($(this).data('mileagestart')); + $('#mileage_end').val($(this).data('mileageend')); + $('#mileage_end').prop("min", $(this).data('mileagestart')); + } else { + + } + } $('.alert-success').remove(); window.scrollTo(0, 0); }); @@ -365,6 +410,10 @@ $(document).ready(function () { $('#businesstrip_info').val(''); $('#businesstrip_info').hide(); $('#homeoffice').prop("checked", false); + $('.car-div').hide(); + $('.car-div').find('input').val(''); + $('.car-div').find('input').prop("required", false); + $('#timerecordingCar_id').val('').change(); $('#timerecordingCategory_id').change(); }); @@ -431,7 +480,7 @@ $(document).ready(function () { $('#businesstrip_info').prop('required', true); $('#homeoffice').prop('checked', false); $('#homeoffice-div').hide(); - + $('.car-div-car').show(); } else { $('#businesstrip_info').hide(); $('#businesstrip_info').val(''); @@ -445,6 +494,10 @@ $(document).ready(function () { if ($(this).prop('checked') == true) { $('#businesstrip').prop('checked', false); $('.businesstrip-div').hide(); + $('#timerecordingCar_id').val(''); + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('.car-div').hide(); $('#businesstrip_info').hide(); $('#businesstrip_info').val(''); $('#businesstrip_info').prop('required', false); @@ -456,6 +509,24 @@ $(document).ready(function () { }); + $("body").on("change", "#timerecordingCar_id", function () { + if ($('#timerecordingCar_id').val() == "") { + $('.car-div').find('input').prop("required", false); + $('.car-div').find('input').val(''); + $('.car-div').hide(); + $('.car-div-car').show(); + } else { + $('.car-div').show(); + $('.car-div').find('input').prop("required", true); + $('#mileage_start').val($(this).find(':selected').data('mileagenow')); + $('#mileage_end').prop("min", $('#mileage_start').val()); + } + }); + + $("body").on("change", "#mileage_start", function () { + $('#mileage_end').prop("min", $('#mileage_start').val()); + }); + $("body").on("click", ".delete-item", function () { if (confirm('Buchung wirklich löschen?')) { $.post(deleteUrl, { @@ -474,12 +545,16 @@ $(document).ready(function () { userid = $('#user_id_select').val(); var businesstrip = false; var homeoffice = false; + var car = false; if ($('#businesstrip').prop('checked') == true) { businesstrip = 1; } if ($('#homeoffice').prop('checked') == true) { homeoffice = 1; } + if ($.trim($('#timerecordingCar_id').val())) { + car = 1; + } $.post(insertUrl, { id: $.trim($('#id').val()), user_id: userid, @@ -492,6 +567,9 @@ $(document).ready(function () { comment: $.trim($('#comment').val()), businesstrip: businesstrip, businesstrip_info: $.trim($('#businesstrip_info').val()), + timerecordingCar_id: $.trim($('#timerecordingCar_id').val()), + mileage_start: $.trim($('#mileage_start').val()), + mileage_end: $.trim($('#mileage_end').val()), homeoffice: homeoffice, hourday: $.trim($('#timerecordingCategory_id').find(':selected').data('hourday')), ajax: 1 @@ -505,6 +583,12 @@ $(document).ready(function () {
    Erfolgreich
    ` + result.message + `
    `); + if ($.trim($('#mileage_start').val())) { + $('#timerecordingCar_id').find(':selected').data('mileagenow', $.trim($('#mileage_end').val())); + } + if (car == 1) { + $('#timerecordingCar_id').val('').change(); + } $('#businesstrip').prop('checked', false); $('#businesstrip_info').hide(); $('#businesstrip_info').val(''); diff --git a/public/plugins/notification/notify.js b/public/plugins/notification/notify.js index 37d92dee0..7fee5da5f 100644 --- a/public/plugins/notification/notify.js +++ b/public/plugins/notification/notify.js @@ -6,9 +6,19 @@ document.addEventListener('DOMContentLoaded', () => { // @formatter:on const notyf = new Notyf({ - duration: 10000 * 1000, position: { + duration: 10000, position: { x: 'right', y: 'bottom', }, ripple: true, dismissible: true, fontSize: '32px', + types: [{ + type: "info", + backgroundColor: "#17a2b8", + icon: {className: "fa fa-info-circle text-white",tagName: "i"} + }, + { + type: 'warning', + backgroundColor: '#ffc107', + icon: {className: 'fa fa-exclamation-triangle text-white',tagName: 'i',}, + }] }); /** @@ -22,13 +32,14 @@ document.addEventListener('DOMContentLoaded', () => { notyf.success(text); break; case 'info': - notyf.info(text); + notyf.open({type: 'info', message: text}); break; case 'warning': - notyf.warning(text); + notyf.open({type: 'warning', message: text}); break; case'warn': - notyf.warning(text); + notyf.open({type: 'warning', message: text}); + break; case 'error': notyf.error(text); break; diff --git a/public/plugins/vue/tt-components/css/tt-table.css b/public/plugins/vue/tt-components/css/tt-table.css new file mode 100644 index 000000000..a7d6e9c3a --- /dev/null +++ b/public/plugins/vue/tt-components/css/tt-table.css @@ -0,0 +1,20 @@ +.tt-table.loading tbody { + position: relative; +} + +.tt-table.loading tbody:after { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.1); + background-image: url(data:image/gif;base64,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); + background-position: center; + background-repeat: no-repeat; + background-size: 50px 50px; + content: ""; +} +.tt-table-card .page-link { + padding: 5px .75rem !important; +} \ No newline at end of file diff --git a/public/plugins/vue/tt-components/tt-table.js b/public/plugins/vue/tt-components/tt-table.js new file mode 100644 index 000000000..a376ead40 --- /dev/null +++ b/public/plugins/vue/tt-components/tt-table.js @@ -0,0 +1,337 @@ + +//TODO: tt-autocomplete , tt-select aswell as tt-input should be used for filtering +//TODO: Add sorting functionality +//TODO: Add export to excel and pdf functionality +//TODO: Add Date-Range filter +//TODO: Add Exact Date filter +//TODO: Add new prop serverSide to disable pagination and filtering on the client side +//TODO: Add filtering function if serverSide is disabled +//TODO: Add JSDoc for various functions and props + +/** + * @typedef {Object} ttTableColumnConfig + * @property {string} text - The display text of the column. + * @property {string} key - The unique key of the column. + * @property {string} filter - Indicates if filtering is enabled for the column. + * @property {boolean} sortEnabled - Indicates if sorting is enabled for the column. + * @property {string} class - The CSS class(es) applied to the column. + */ + +//TODO: export this to its own file +Vue.component('tt-date-range', { + template: ` + + `, props: ['value'], + data() { + return { + inputValue: '', + isInitialized: false, + locale: { + "format": "DD.MM.YYYY HH:mm", + "separator": " - ", + "applyLabel": "Übernehmen", + "cancelLabel": "Abbrechen", + "fromLabel": "Von", + "toLabel": "Bis", + "customRangeLabel": "Benutzerdefiniert", + "weekLabel": "W", + "daysOfWeek": [ + "So", + "Mo", + "Di", + "Mi", + "Do", + "Fr", + "Sa" + ], + "monthNames": [ + "Januar", + "Februar", + "März", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember" + ], + "firstDay": 1 + }, + } + }, + methods: { + initialize() { + if (!this.isInitialized) { + this.isInitialized = true; + $(this.$refs.input).daterangepicker({ + autoUpdateInput: true, + timePicker: true, + timePicker24Hour: true, + locale: this.locale, + }); + + this.$refs.input.click(); + + const _this = this; + $(this.$refs.input).on('apply.daterangepicker', function(ev, picker) { + console.log('now emitting chang', picker.startDate.unix(), picker.endDate.unix()); + _this.$emit('change', { + target: { + value: { + from: picker.startDate.unix() + 7200, + to: picker.endDate.unix() + 7200 + } + } + }); + }); + } + } + }, + beforeDestroy() { + $(this.$refs.input).off('apply.daterangepicker'); + }, +}) + +Vue.component('tt-table', { + template: ` +
    +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    {{ column.text }}
    + + + +
    Keine Ergebnisse!
    Laden...
    +
    +
    + `, props: { + fetchUrl: String, striped: { + type: Boolean, default: true + }, bordered: { + type: Boolean, default: true + }, hover: { + type: Boolean, default: true + }, small: Boolean, excelExport: Boolean, pdfExport: Boolean, tableConfig: { + type: Object, default: () => ({}) + } + }, data() { + return { + loading: false, rows: null, pagination: null, filters: {}, debounceTimeout: null, latestFetchTimestamp: null + }; + }, + + methods: { + /** + * Creates a debounced function that delays invoking `fn` until after `wait` milliseconds + * have elapsed since the last time the debounced function was invoked. + * + * @param {Function} fn The function to debounce. + * @param {number} wait The number of milliseconds to delay. + * @return {Function} The debounced function. + */ + debounce(fn, wait) { + return function (...args) { + const context = this; + if (this.debounceTimeout) clearTimeout(this.debounceTimeout); + this.debounceTimeout = setTimeout(() => fn.apply(context, args), wait); + } + }, /** + * Fetches and updates data for a specified page. + * + * @param {number} page The page number to fetch data for. + * @async + */ + async fetchData(page= 0) { + try { + const fetchTimestamp = Date.now(); + this.latestFetchTimestamp = fetchTimestamp; + const response = await axios.post(this.fetchUrl, { + pagination: { + page: Math.max(page, 1), per_page: this.pagination?.per_page ? this.pagination.per_page : 10, + }, filters: this.filters, + }); + + if (fetchTimestamp !== this.latestFetchTimestamp) return; + + if (typeof response.data !== 'object') { // if the response is not an object + this.rows = []; + this.pagination = {page: 1, per_page: 10, total_rows: 0, total_pages: 1}; + } else { + this.rows = response.data.rows; + this.pagination = response.data.pagination; + } + this.loading = false; + } catch (error) { + console.error('Error fetching data:', error); + } + }, /** + * Fetches rows for a given page, with an option to debounce the fetch operation. + * + * @param {number} page The page number to fetch. Defaults to 1. + * @param {boolean} debounce Whether to debounce the fetch operation. Defaults to false. + */ + async fetchRows(page = 1, debounce = false) { + this.loading = true + if (debounce) { + this.debounce(this.fetchData.bind(this), 300)(page); + } else { + await this.fetchData(page); // Directly call fetchData without debounce + } + }, + applyFilter(event, key) { + this.$set(this.filters, key, event.target.value); // Ensure reactivity + } + }, watch: { + filters: { + handler: function () { + this.fetchRows(this.pagination.page, true).then(); + }, deep: true + } + }, computed: { + /** + * Returns an object containing the columns' configuration. + * @return {ttTableColumnConfig} The columns configuration. + */ + columns() { + return this.tableConfig.headers.reduce((columns, column) => { + if (!column.key) { + console.warn('WARN: tt-table: Column text or key is not defined:', column); + return columns; // Continue to the next iteration without modifying the accumulator + } + columns[column.key] = { + text: column.text, + key: column.key, + filter: column.filter !== undefined ? column.filter : 'search', + filterOptions: column.filterOptions || undefined, + sortEnabled: column.sortEnabled !== undefined ? column.sortEnabled : true, + class: column.class !== undefined ? column.class : '' + }; + return columns; + }, {}); + + }, pagesToDisplay() { + let range = 2; // Number of pages before and after the current page + let start = (this.pagination.page < 4 ? 1 : this.pagination.page - range) ; + let end = (this.pagination.page + range > this.pagination.total_pages ? this.pagination.total_pages : this.pagination.page + range); + if (end < 5) end = 5; + + // Adjust start and end if they are out of bounds + end = end > this.pagination.total_pages ? this.pagination.total_pages : end; + + // Adjust the start and end if we are at the end of the page range + if (this.pagination.page > this.pagination.total_pages - 2) { + start = this.pagination.total_pages - 4 < 1 ? 1 : this.pagination.total_pages - 4; + } + + // Create an array of page numbers to display + let pagesArray = []; + for (let i = start; i <= end; i++) { + pagesArray.push(i); + } + + return pagesArray; + } + + }, mounted() { + if(this.tableConfig.defaultPageSize) { + this.pagination = {page: 1, per_page: this.tableConfig.defaultPageSize, total_rows: null, total_pages: 1}; + } + this.fetchRows().then(); + }, +}) \ No newline at end of file diff --git a/scripts/voice/run-voice-call-history-job.php b/scripts/voice/run-voice-call-history-job.php new file mode 100644 index 000000000..0bfebd080 --- /dev/null +++ b/scripts/voice/run-voice-call-history-job.php @@ -0,0 +1,21 @@ +#!/usr/bin/php +id); +define("INTERNAL_USER_USERNAME", $me->username); + +$voiceCallHistoryJobController = new VoiceCallHistoryJobController(false); + +$voiceCallHistoryJobController->runJobs(); \ No newline at end of file