From 30409c4a23f733960376f937763f422f907f55d8 Mon Sep 17 00:00:00 2001 From: Spitzer Daniel Date: Thu, 22 Feb 2024 19:08:32 +0100 Subject: [PATCH 1/5] =?UTF-8?q?Zeiterfassung=20Update/Bugfix=20*=20Timerec?= =?UTF-8?q?ordingReportController.php=20verweist=20in=20einer=20gewissen?= =?UTF-8?q?=20Datenbank-Eintragskonstellation=20auf=20einen=20ung=C3=BClti?= =?UTF-8?q?gen=20Array=20Index.=20Hab=20die=20gesamtsollzeitberechnung=20t?= =?UTF-8?q?empor=C3=A4r=20ausgeschalten=20*=20Neu=20Migration=20(Vorbereit?= =?UTF-8?q?en=20der=20DB=20auf=20eigenes=20=C3=9C-Zeitkonto)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimerecordingEmployeeModel.php | 3 ++ .../TimerecordingReportController.php | 6 ++-- ...erecording_employee_add_field_overtime.php | 33 +++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 db/migrations/20240222175444_timerecording_employee_add_field_overtime.php diff --git a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php index 913b19bb1..2de108268 100644 --- a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php +++ b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php @@ -6,7 +6,10 @@ class TimerecordingEmployeeModel private $type; private $auto_workinghours; private $holidays; + private $holidays_now; private $plushours; + private $plushours_now; + private $overtime; private $startdate; diff --git a/application/TimerecordingReport/TimerecordingReportController.php b/application/TimerecordingReport/TimerecordingReportController.php index 0077c2402..c4e3423ae 100644 --- a/application/TimerecordingReport/TimerecordingReportController.php +++ b/application/TimerecordingReport/TimerecordingReportController.php @@ -100,7 +100,7 @@ class TimerecordingReportController extends mfBaseController $dDate = date('Y-m-d', $timestamp); $dDay = date('w', $timestamp); if (!$holiDay[$dDate]) { - $mustSeconds = $mustSeconds + $workingHours[$dDay]; + // $mustSeconds = $mustSeconds + $workingHours[$dDay]; } $timestamp = $timestamp + 86400; @@ -117,7 +117,7 @@ class TimerecordingReportController extends mfBaseController $dDate = date('Y-m-d', $timestamp); $dDay = date('w', $timestamp); if (!$holiDay[$dDate]) { - $mustSeconds = $mustSeconds + $workingHours[$dDay]; + // $mustSeconds = $mustSeconds + $workingHours[$dDay]; } $timestamp = $timestamp + 86400; } @@ -133,7 +133,7 @@ class TimerecordingReportController extends mfBaseController $dDate = date('Y-m-d', $timestamp); $dDay = date('w', $timestamp); if (!$holiDay[$dDate]) { - $mustSeconds = $mustSeconds + $workingHours[$dDay]; + //$mustSeconds = $mustSeconds + $workingHours[$dDay]; } $timestamp = $timestamp + 86400; diff --git a/db/migrations/20240222175444_timerecording_employee_add_field_overtime.php b/db/migrations/20240222175444_timerecording_employee_add_field_overtime.php new file mode 100644 index 000000000..dcbb61f15 --- /dev/null +++ b/db/migrations/20240222175444_timerecording_employee_add_field_overtime.php @@ -0,0 +1,33 @@ +getEnvironment() == "thetool") { + $table = $this->table("TimerecordingEmployee", ["signed" => true]); + $table->addColumn("overtime", "integer", ["null" => false, "default" => '0', "after" => "plushours_now"]); + $table->changeColumn('holidays_now', 'integer', ["null" => false, "default" => '0']); + $table->changeColumn('plushours_now', 'integer', ["null" => false, "default" => '0']); + $table->update(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } + + public function down(): void + { + if($this->getEnvironment() == "thetool") { + $this->table("TimerecordingEmployee")->removeColumn("overtime")->save(); + } + + if($this->getEnvironment() == "addressdb") { + + } + } +} From 634ba2ee6e5720bfb4817ea34574efc41ff9cf7b Mon Sep 17 00:00:00 2001 From: Spitzer Daniel Date: Thu, 22 Feb 2024 19:14:16 +0100 Subject: [PATCH 2/5] =?UTF-8?q?Zeiterfassung=20Update/Bugfix=20*=20Timerec?= =?UTF-8?q?ordingReportController.php=20verweist=20in=20einer=20gewissen?= =?UTF-8?q?=20Datenbank-Eintragskonstellation=20auf=20einen=20ung=C3=BClti?= =?UTF-8?q?gen=20Array=20Index.=20Hab=20die=20gesamtsollzeitberechnung=20t?= =?UTF-8?q?empor=C3=A4r=20ausgeschalten=20*=20Neu=20Migration=20(Vorbereit?= =?UTF-8?q?en=20der=20DB=20auf=20eigenes=20=C3=9C-Zeitkonto)=20*=20Kalende?= =?UTF-8?q?r=20Feiertagsdescription=20angepasst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Layout/default/TimerecordingCalendar/Index.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Layout/default/TimerecordingCalendar/Index.php b/Layout/default/TimerecordingCalendar/Index.php index aa7a9ae75..a2c9a6095 100644 --- a/Layout/default/TimerecordingCalendar/Index.php +++ b/Layout/default/TimerecordingCalendar/Index.php @@ -176,7 +176,8 @@ $daysgerm = array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); id: , start: 'timestamp) ?>', end: 'timestamp) ?>', - title: 'description ?>' + title: 'description ?>', + description: 'description ?>' }); Date: Mon, 26 Feb 2024 21:01:50 +0100 Subject: [PATCH 3/5] =?UTF-8?q?Zeiterfassung=20Update/Bugfix=20*=20Timerec?= =?UTF-8?q?ordingReportController.php=20verweist=20in=20einer=20gewissen?= =?UTF-8?q?=20Datenbank-Eintragskonstellation=20auf=20einen=20ung=C3=BClti?= =?UTF-8?q?gen=20Array=20Index.=20Hab=20die=20gesamtsollzeitberechnung=20t?= =?UTF-8?q?empor=C3=A4r=20ausgeschalten=20*=20Neu=20Migration=20(Vorbereit?= =?UTF-8?q?en=20der=20DB=20auf=20eigenes=20=C3=9C-Zeitkonto)=20*=20Kalende?= =?UTF-8?q?r=20Feiertagsdescription=20angepasst=20*=20Geburtstage=20nun=20?= =?UTF-8?q?m=C3=B6glich=20in=20Personaladministration=20und=20Kalender=20*?= =?UTF-8?q?=20Initiale=20=C3=9Cberstunden=20sind=20nun=20m=C3=B6glich=20*?= =?UTF-8?q?=20Berechnung=20Urlaubstage=20nun=20exakt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../default/TimerecordingCalendar/Index.php | 37 ++- Layout/default/TimerecordingEmployee/Form.php | 17 ++ Layout/default/TimerecordingReport/Index.php | 1 + .../Timerecording/TimerecordingController.php | 76 +++++- .../Timerecording/TimerecordingModel.php | 9 + .../TimerecordingCalendarController.php | 2 + .../TimerecordingEmployeeController.php | 16 ++ .../TimerecordingEmployeeModel.php | 6 + .../TimerecordingReportController.php | 241 ++++++++++++++++++ ...erecording_employee_add_field_overtime.php | 8 + public/js/pages/timerecordingReport/index.js | 33 ++- 11 files changed, 437 insertions(+), 9 deletions(-) diff --git a/Layout/default/TimerecordingCalendar/Index.php b/Layout/default/TimerecordingCalendar/Index.php index a2c9a6095..502f4d150 100644 --- a/Layout/default/TimerecordingCalendar/Index.php +++ b/Layout/default/TimerecordingCalendar/Index.php @@ -169,6 +169,7 @@ $daysgerm = array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); let requestUrl = " 'getTimerecordings', 'datatype' => '3', 'datayear' => time()]) ?>"; var cindex = 1; var holiDays = []; + var birthdays = []; @@ -182,7 +183,28 @@ $daysgerm = array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); birthday) : + $year = date("Y", time()); + $year = $year - 1; + $Byear = date("Y", $timerecordingemployee->birthday); + for ($i = 0; $i < 5; $i++) : + $age = $year - $Byear; ?> + birthdays.push({ + id: , + start: 'birthday) ?>', + end: 'birthday) ?>', + title: 'user->name ?> ()', + description: 'Geburtstag user->name ?> ()' + }); + + cindex = ; $.getJSON(requestUrl, function (data) { @@ -224,7 +246,7 @@ $daysgerm = array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); // Calendar Event Source // Birthday Events Source - var birthdayEvents = { + var holiDayEvents = { id: 1, backgroundColor: 'rgba(255, 0, 0 , 1)', borderColor: 'rgba(255, 0, 0 , 1)', @@ -233,12 +255,19 @@ $daysgerm = array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); }; var holidayEvents = { - id: 5, + id: 7, backgroundColor: 'rgba(0,204,204,.25)', - borderColor: 'rgb(192 0 255)', + borderColor: 'rgb(8 241 8)', textColor: '#000', events: holidays }; + var birthdayEvents = { + id: 5, + backgroundColor: 'rgb(68 15 241 / 76%)', + borderColor: 'rgb(68 15 241 / 76%)', + textColor: '#fff', + events: birthdays + }; var initialLocaleCode = 'en'; var calendarEl = document.getElementById('calendar'); var calendar = new FullCalendar.Calendar(calendarEl, { @@ -266,7 +295,7 @@ $daysgerm = array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); navLinks: 'true', events: [], height: 800, - eventSources: [holidayEvents, birthdayEvents] + eventSources: [birthdayEvents, holiDayEvents, holidayEvents] }); calendar.render(); }); diff --git a/Layout/default/TimerecordingEmployee/Form.php b/Layout/default/TimerecordingEmployee/Form.php index 40ab0f030..7cf2ddf2d 100644 --- a/Layout/default/TimerecordingEmployee/Form.php +++ b/Layout/default/TimerecordingEmployee/Form.php @@ -89,6 +89,15 @@ $daysSelect .= ""; value="startdate) ? date('Y-m-d', $timerecordingemployees->startdate): "" ?>"/> +
+ +
+ "/> +
+
+
@@ -106,6 +115,14 @@ $daysSelect .= ""; value="plushours / 3600) ?>"/>
+
+ +
+ overtime / 3600) ?>"/> +
+
diff --git a/Layout/default/TimerecordingReport/Index.php b/Layout/default/TimerecordingReport/Index.php index 2bbcfbf58..c6af1b85b 100644 --- a/Layout/default/TimerecordingReport/Index.php +++ b/Layout/default/TimerecordingReport/Index.php @@ -352,6 +352,7 @@ $years[time() - 31536000] = date('Y', time() - 31536000); let insertUrl = ""; let deleteUrl = ""; let requestUrl = " 'getTimerecordings']) ?>"; + let requestTimesUrl = " 'getTimerecordingsTimes']) ?>"; diff --git a/application/Timerecording/TimerecordingController.php b/application/Timerecording/TimerecordingController.php index 13e1f06f2..48bf920a7 100644 --- a/application/Timerecording/TimerecordingController.php +++ b/application/Timerecording/TimerecordingController.php @@ -262,7 +262,7 @@ class TimerecordingController extends mfBaseController } if ($id) { $timerecordingCategoriess = TimerecordingCategoryModel::search(['id' => $data['timerecordingCategory_id']]); - if ($timerecordingCategoriess[0]->approval == "1") { + if ($timerecordingCategoriess[0]->approval == "1" && !$r->user_id) { $body = 'Beantrag von: ' . $this->me->name . ' '; $body .= 'Buchungsart: ' . $timerecordingCategoriess[0]->name . ' @@ -286,6 +286,9 @@ class TimerecordingController extends mfBaseController $email->setTo(TT_TIMERECORDING_EMAIL); $email->send(); } + if ($data['timerecordingCategory_id'] == "3") { + $this->updateHolidays($data['user_id']); + } } if ($mode == "edit") { @@ -303,6 +306,69 @@ class TimerecordingController extends mfBaseController $this->redirect("Timerecording"); } + protected function updateHolidays($userid) + { + $employee = TimerecordingEmployeeModel::search(['user_id' => $userid]); + if ($employee) { + $employee = $employee[0]; + $holidays = $employee->holidays; + $holidays_now = $employee->holidays_now; + $holidays_timestamp = $employee->holidays_timestamp; + $workinghours = TimerecordingEmployeeWorkingHourModel::search(['user_id' => $userid]); + $realHolidays = TimerecordingHolidayModel::getAll(); + foreach ($realHolidays as $realHoliday) { + $realholiDay[date('Y-m-d', $realHoliday->timestamp)] = $realHoliday->timestamp; + } + if (!$holidays_timestamp) { + $holidays_timestamp = $employee->startdate; + $holidays_now = $holidays; + } + $timerecordings = TimerecordingModel::search(['user_id' => $userid, 'start' => $holidays_timestamp, 'timerecordingCategory_id' => 3]); + foreach ($timerecordings as $timerecording) { + $daycounter = ($timerecording->end - $timerecording->start) / 86400; + $daycounter=intval(round($daycounter,0,PHP_ROUND_HALF_DOWN)); + $daycounter = $daycounter * 86400; + if (is_int($daycounter)) { + for ($i = 86400; $i <= $daycounter; $i = $i + 86400) { + $holidayDays[date("Y-m-d", $timerecording->start + $i - 86400)] = 1; + } + } + } + + + foreach ($workinghours as $workinghour) { + + $whstart = strtotime(date('Y-m-d', time()) . " " . $workinghour->start . ":00"); + $whend = strtotime(date('Y-m-d', time()) . " " . $workinghour->end . ":00"); + if (!$workingHours[$workinghour->day]) { + $workingHours[$workinghour->day] = $whend - $whstart; + } else { + $workingHours[$workinghour->day] = $workingHours[$workinghour->day] + $whend - $whstart; + } + } + //check if holiday is already in the list + foreach ($holidayDays as $key => $holidayDay) { + if ($realholiDay[$key]) { + + } else if ($workingHours[date('w', strtotime($key))]) { + $holidays_now--; + } + } + if ($holidays_now != $employee->holidays_now) { + $employeeupdate = new TimerecordingEmployee($employee->id); + $data = []; + $data['holidays_now'] = $holidays_now; + $employeeupdate->update($data); + $employeeupdate->save(); + + } + } + } + + protected function updatePlushours($userid) + { + + } protected function getTimerecordingsApi($datatype, $dataweek, $datamonth, $datayear) { @@ -314,8 +380,8 @@ class TimerecordingController extends mfBaseController $rows = []; $employee = TimerecordingEmployeeModel::search(['user_id' => $this->me->id]); if ($employee) { - $holiDays = $employee[0]->holidays; - $plusHours = $employee[0]->plushours; + $holiDays = $employee[0]->holidays_now; + $plusHours = $employee[0]->plushours_now; $auto_workinghours = $employee[0]->auto_workinghours; } @@ -621,12 +687,14 @@ class TimerecordingController extends mfBaseController { $id = $this->request->id; $timerecordings = new Timerecording($id); + $userid = $timerecordings->user_id; if (!$timerecordings->id || $timerecordings->id != $id) { $this->layout()->setFlash("Buchung nicht gefunden.", "error"); $this->redirect("Timerecording"); } - $timerecordings->delete(); + $this->updateHolidays($userid); + if ($this->request->ajax == 1) { die(); } diff --git a/application/Timerecording/TimerecordingModel.php b/application/Timerecording/TimerecordingModel.php index 1d74c4516..7b83a7a1e 100644 --- a/application/Timerecording/TimerecordingModel.php +++ b/application/Timerecording/TimerecordingModel.php @@ -150,6 +150,15 @@ class TimerecordingModel $where .= " AND ((`start` >= $start AND `start` <= $end) OR (`end` >= $start AND `end` <= $end) OR `end` is NULL) ORDER by user_id ASC"; } } + if (array_key_exists("start", $filter) && array_key_exists("timerecordingCategory_id", $filter)) { + $start = $filter['start']; + $timerecordingCategory_id = $filter['timerecordingCategory_id']; + if (is_numeric($start) && is_numeric($timerecordingCategory_id)) { + $where .= " AND `start` >= $start AND `timerecordingCategory_id` = $timerecordingCategory_id ORDER by start ASC"; + } + } + + if (array_key_exists("starttime", $filter) && array_key_exists("endtime", $filter)) { $starttime = $filter['starttime']; $endtime = $filter['endtime']; diff --git a/application/TimerecordingCalendar/TimerecordingCalendarController.php b/application/TimerecordingCalendar/TimerecordingCalendarController.php index 97eb1fe46..699da04fe 100644 --- a/application/TimerecordingCalendar/TimerecordingCalendarController.php +++ b/application/TimerecordingCalendar/TimerecordingCalendarController.php @@ -20,6 +20,8 @@ class TimerecordingCalendarController extends mfBaseController { $timerecordingholidays = TimerecordingHolidayModel::getAll(); $this->layout()->set("timerecordingholidays", $timerecordingholidays); + $timerecordingemployees = TimerecordingEmployeeModel::getAll(); + $this->layout()->set("timerecordingemployees", $timerecordingemployees); $this->layout()->setTemplate("TimerecordingCalendar/Index"); } diff --git a/application/TimerecordingEmployee/TimerecordingEmployeeController.php b/application/TimerecordingEmployee/TimerecordingEmployeeController.php index 0986a1114..9d1110968 100644 --- a/application/TimerecordingEmployee/TimerecordingEmployeeController.php +++ b/application/TimerecordingEmployee/TimerecordingEmployeeController.php @@ -101,6 +101,12 @@ class TimerecordingEmployeeController extends mfBaseController if (is_numeric($plushours)) { $plushours = $plushours * 3600; } + $overtime = $r->overtime; + $overtime = str_replace(',', '.', $overtime); + if (is_numeric($overtime)) { + $overtime = $overtime * 3600; + } + $data = []; $data['user_id'] = trim($r->user_id); @@ -109,8 +115,18 @@ class TimerecordingEmployeeController extends mfBaseController $data['plushours'] = $plushours; $data['startdate'] = strtotime($r->startdate); $data['type'] = trim($r->type); + $data['overtime'] = $overtime; +# + if (!$data['overtime']) { + $data['overtime'] = 0; + } + if ($r->birthday) { + $data['birthday'] = strtotime($r->birthday); + } else { + $data['birthday'] = null; + } if (!$data['user_id']) { $this->layout()->setFlash("Mitarbeiter darf nicht leer sein", "error"); $this->redirect("TimerecordingEmployee"); diff --git a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php index 2de108268..a4fce4ecd 100644 --- a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php +++ b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php @@ -7,10 +7,16 @@ class TimerecordingEmployeeModel private $auto_workinghours; private $holidays; private $holidays_now; + private $holidays_timestamp; private $plushours; private $plushours_now; + private $plushours_timestamp; private $overtime; + private $overtime_now; + private $overtime_timestamp; + private $bpahours; private $startdate; + private $birthday; public static function find($data) diff --git a/application/TimerecordingReport/TimerecordingReportController.php b/application/TimerecordingReport/TimerecordingReportController.php index c4e3423ae..68a0333fc 100644 --- a/application/TimerecordingReport/TimerecordingReportController.php +++ b/application/TimerecordingReport/TimerecordingReportController.php @@ -41,6 +41,9 @@ class TimerecordingReportController extends mfBaseController case "getTimerecordings": $return = $this->getTimerecordingsApi($datatype, $dataweek, $datamonth, $datayear); break; + case "getTimerecordingsTimes": + $return = $this->getTimerecordingsTimes($datatype, $dataweek, $datamonth, $datayear); + break; default: $return = false; } @@ -307,6 +310,244 @@ class TimerecordingReportController extends mfBaseController die(); } + + protected function getTimerecordingsTimes($datatype, $dataweek, $datamonth, $datayear) + { + $r = $this->request; + $mustSeconds = 0; + $isSeconds = 0; + $holiDays = 0; + $plusHours = 0; + + $rows = []; + $employee = TimerecordingEmployeeModel::search(['user_id' => $r->user_id]); + if ($employee) { + $holiDays = $employee[0]->holidays; + $plusHours = $employee[0]->plushours; + $auto_workinghours = $employee[0]->auto_workinghours; + + } + $workinghours = TimerecordingEmployeeWorkingHourModel::search(['user_id' => $r->user_id]); + $holidays = TimerecordingHolidayModel::getAll(); + foreach ($workinghours as $workinghour) { + + $whstart = strtotime(date('Y-m-d', time()) . " " . $workinghour->start . ":00"); + $whend = strtotime(date('Y-m-d', time()) . " " . $workinghour->end . ":00"); + if (!$workingHours[$workinghour->day]) { + $workingHours[$workinghour->day] = $whend - $whstart; + } else { + $workingHours[$workinghour->day] = $workingHours[$workinghour->day] + $whend - $whstart; + } + } + foreach ($holidays as $holiday) { + $holiDay[date('Y-m-d', $holiday->timestamp)] = $holiday->timestamp; + } + + if ($datatype == 1) { + $kw = date('W', $dataweek); + $year = date('Y', $dataweek); + $timestamp_montag = strtotime("{$year}-W{$kw}"); + $timestamp_sonntag = strtotime("{$year}-W{$kw}-7"); + $firstdate = strtotime(date("Y-m-d", $timestamp_montag) . " 00:00:00"); + $lastdate = strtotime(date("Y-m-d", $timestamp_sonntag) . ' 23:59:59'); + $searchArray = ['user_id' => $r->user_id, 'start' => $timestamp_montag, 'end' => $lastdate]; + + $daycounter = '0'; + + $timestamp = $timestamp_montag; + for ($i = 1; $i <= 7; $i++) { + $dDate = date('Y-m-d', $timestamp); + $dDay = date('w', $timestamp); + if (!$holiDay[$dDate]) { + $mustSeconds = $mustSeconds + $workingHours[$dDay]; + } + + $timestamp = $timestamp + 86400; + } + } else if ($datatype == 2) { + $firstdate = strtotime(date("Y-m-01", $datamonth)); + $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]; + $timestamp = $firstdate; + + for ($i = 1; $i <= $daycount; $i++) { + $dDate = date('Y-m-d', $timestamp); + $dDay = date('w', $timestamp); + if (!$holiDay[$dDate]) { + $mustSeconds = $mustSeconds + $workingHours[$dDay]; + } + + $timestamp = $timestamp + 86400; + } + + + } else if ($datatype == 3) { + $firstdate = strtotime(date("Y-01-01", $datayear)); + $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]; + $timestamp = $firstdate; + + for ($i = 1; $i <= $daycount; $i++) { + $dDate = date('Y-m-d', $timestamp); + $dDay = date('w', $timestamp); + if (!$holiDay[$dDate]) { + $mustSeconds = $mustSeconds + $workingHours[$dDay]; + } + + $timestamp = $timestamp + 86400; + } + + + } + + + $daysgerm = array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); + $timerecordingcategories = TimerecordingCategoryModel::getAll(); + + $timerecordings = TimerecordingModel::search($searchArray); + $responsecount = count($timerecordings); + foreach ($timerecordings as $timerecording): + $state = ""; + $enddate = ""; + $sum = "-"; + $day = ""; + $orderdate = $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); + $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)]; + $isSeconds = $isSeconds + $seconds; + } 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); + $enddate = date("Y-m-d", $timerecording->end); + $start = "-"; + $end = "-"; + $day = $daysgerm[date("w", $timerecording->start)]; + + if ($lastdate < $timerecording->end) { + $endtimecalc = $lastdate; + } else { + $endtimecalc = $timerecording->end; + } + if ($firstdate > $timerecording->start) { + $starttimecalc = $firstdate; + } else { + $starttimecalc = $timerecording->start; + } + $summcounter = 0; + $savecounter = 0; + for ($i = $starttimecalc; $i <= $endtimecalc; $i = $i + 86400) { + $holidaycounter = $workingHours[date("w", $i)]; + $isSeconds = $isSeconds + $holidaycounter; + $summcounter = $summcounter + $holidaycounter; + if ($savecounter == 1000) { + echo $savecounter; + die(); + } + $savecounter++; + } + $seconds = $summcounter; + $minutes = floor(($seconds % 3600) / 60); + $hours = floor($seconds / 3600); + $sum = sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); + + } else if ($timerecording->timerecordingCategory->hourday == 3 && !$timerecording->end) { + $date = date("d.m.Y", $timerecording->start) . " - " . $daysgerm[date("w", time())] . " " . date("d.m.Y", time());; + $datadate = date("Y-m-d", $timerecording->start); + $start = "-"; + $end = "-"; + $day = $daysgerm[date("w", $timerecording->start)]; + if ($lastdate < $timerecording->end) { + $endtimecalc = $lastdate; + } else { + $endtimecalc = $timerecording->end; + } + if ($firstdate > $timerecording->start) { + $starttimecalc = $firstdate; + } else { + $starttimecalc = $timerecording->start; + } + $summcounter = 0; + $savecounter = 0; + for ($i = $starttimecalc; $i <= $endtimecalc; $i = $i + 86400) { + $holidaycounter = $workingHours[date("w", $i)]; + $isSeconds = $isSeconds + $holidaycounter; + $summcounter = $summcounter + $holidaycounter; + if ($savecounter == 1000) { + echo $savecounter; + die(); + } + $savecounter++; + } + $seconds = $summcounter; + $minutes = floor(($seconds % 3600) / 60); + $hours = floor($seconds / 3600); + $sum = sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); + + } + + if ($timerecording->timerecordingCategory->approval == 1 && $timerecording->approved == 0) { + $state = ''; + } else if ($timerecording->timerecordingCategory->approval == 1 && $timerecording->approved == 1) { + $state = ''; + } + $edit = ""; + if ($timerecording->businesstrip == 1) { + $category = "" . $timerecording->timerecordingCategory->name . " (Dienstreise: " . $timerecording->businesstrip_info . ")"; + } else { + $category = $timerecording->timerecordingCategory->name; + } + if ($timerecording->timerecordingCategory->hourday == 3 && !$timerecording->end) { + $category = $category . "(offen)"; + } + + + if ($timerecording->completed == 0 && $timerecording->timerecordingCategory->only_admin == 0): + if ($timerecording->approved == 0) : + $edit = ''; + else : + $edit .= '
'; + endif; + $edit .= ''; + endif; + if ($datatype == 3 && $timerecording->timerecordingCategory->hourday == 1) { + } else { + + } + endforeach; + $json['success'] = true; + $json['time']['auto_workinghours'] = $auto_workinghours; + $json['time']['is'] = sprintf('%02dh:%02dm', floor($isSeconds / 3600), floor($isSeconds / 60 % 60)); + $json['time']['must'] = sprintf('%02dh:%02dm', floor($mustSeconds / 3600), floor($mustSeconds / 60 % 60)); + $json['time']['holidays'] = $holiDays; + $json['time']['plushours'] = sprintf('%02dh:%02dm', floor($plusHours / 3600), floor($plusHours / 60 % 60)); + $json['recordsFiltered'] = $responsecount; + $json['recordsTotal'] = $responsecount; + $json = json_encode($json); + echo trim($json); + die(); + } + protected function addAction() { diff --git a/db/migrations/20240222175444_timerecording_employee_add_field_overtime.php b/db/migrations/20240222175444_timerecording_employee_add_field_overtime.php index dcbb61f15..eb1eb2351 100644 --- a/db/migrations/20240222175444_timerecording_employee_add_field_overtime.php +++ b/db/migrations/20240222175444_timerecording_employee_add_field_overtime.php @@ -10,6 +10,14 @@ final class TimerecordingEmployeeAddFieldOvertime extends AbstractMigration if($this->getEnvironment() == "thetool") { $table = $this->table("TimerecordingEmployee", ["signed" => true]); $table->addColumn("overtime", "integer", ["null" => false, "default" => '0', "after" => "plushours_now"]); + $table->addColumn("overtime_now", "integer", ["null" => false, "default" => '0', "after" => "plushours_now"]); + $table->addColumn("overtime_timestamp", "integer", ["null" => true, "after" => "overtime_now"]); + $table->addColumn("holidays_timestamp", "integer", ["null" => true, "after" => "holidays_now"]); + $table->addColumn("plushours_timestamp", "integer", ["null" => true, "after" => "plushours_now"]); + $table->addColumn("birthday", "integer", ["null" => true, "after" => "startdate"]); + + + $table->addColumn("bpahours", "integer", ["null" => false, "default" => '0', "after" => "overtime"]); $table->changeColumn('holidays_now', 'integer', ["null" => false, "default" => '0']); $table->changeColumn('plushours_now', 'integer', ["null" => false, "default" => '0']); $table->update(); diff --git a/public/js/pages/timerecordingReport/index.js b/public/js/pages/timerecordingReport/index.js index c4c54969e..01b13ebd4 100644 --- a/public/js/pages/timerecordingReport/index.js +++ b/public/js/pages/timerecordingReport/index.js @@ -90,6 +90,7 @@ table = $('#datatable').DataTable({ $('#must-time').text(json.time.must); $('#holidays').text(json.time.holidays); $('#plushours').text(json.time.plushours); + $('#selectsearch').change(); return json.data; } @@ -182,6 +183,7 @@ if (state) { $(document).ready(function () { $(".select2").select2(); + $("body").on("change", "#timerecordingCategory_id", function () { if (parseInt($(this).find(':selected').data('hourday')) === 2) { $("#endtime-div").hide(); @@ -295,6 +297,34 @@ $(document).ready(function () { $("body").on("change", "#dataweek,#datamonth,#datayear", function () { table.ajax.reload(null, false); }); + + $("body").on("change", "#selectsearch", function () { + var datatype; + if (!$(this).val()) { + $('#must-time').text('N/A'); + $('#is-time').text('N/A'); + } else { + $('.display-calendar').each(function (index) { + if ($(this).hasClass('active-calendar')) { + datatype = $(this).data('datatype'); + } + }); + if (datatype == 1 || datatype == 2) { + $.post(requestTimesUrl, { + id: $.trim($(this).data('id')), + datatype: datatype, + user_id: $(this).find(':selected').data('userid'), + dataweek: $('#dataweek').val(), + datamonth: $('#datamonth').val(), + ajax: 1 + }).done(function (data) { + var json = $.parseJSON(data); + $('#must-time').text(json.time.must); + $('#is-time').text(json.time.is); + }); + } + } + }); $("body").on("click", ".display-calendar", function () { $('.display-calendar').each(function (index) { $(this).removeClass('active-calendar'); @@ -350,7 +380,7 @@ $(document).ready(function () { e.preventDefault(); $('#alert-box').remove(); var userid; - userid = $('#user_id_select').val(); + userid = $('#user_id_select').val(); var businesstrip = false; if ($('#businesstrip').prop('checked') == true) { businesstrip = 1; @@ -403,5 +433,6 @@ $(document).ready(function () { }); }); $('#timerecordingCategory_id').change(); + }) ; \ No newline at end of file From 5501c381effd889b0cd9188a28ba8c688690b4d4 Mon Sep 17 00:00:00 2001 From: Spitzer Daniel Date: Mon, 26 Feb 2024 22:11:23 +0100 Subject: [PATCH 4/5] =?UTF-8?q?Zeiterfassung=20Update/Bugfix=20*=20Timerec?= =?UTF-8?q?ordingReportController.php=20verweist=20in=20einer=20gewissen?= =?UTF-8?q?=20Datenbank-Eintragskonstellation=20auf=20einen=20ung=C3=BClti?= =?UTF-8?q?gen=20Array=20Index.=20Hab=20die=20gesamtsollzeitberechnung=20t?= =?UTF-8?q?empor=C3=A4r=20ausgeschalten=20*=20Neu=20Migration=20(Vorbereit?= =?UTF-8?q?en=20der=20DB=20auf=20eigenes=20=C3=9C-Zeitkonto)=20*=20Kalende?= =?UTF-8?q?r=20Feiertagsdescription=20angepasst=20*=20Geburtstage=20nun=20?= =?UTF-8?q?m=C3=B6glich=20in=20Personaladministration=20und=20Kalender=20*?= =?UTF-8?q?=20Initiale=20=C3=9Cberstunden=20sind=20nun=20m=C3=B6glich=20*?= =?UTF-8?q?=20Berechnung=20Urlaubstage=20nun=20exakt=20*=20Berechnung=20de?= =?UTF-8?q?r=20Mehrstunden=20nun=20exakt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Layout/default/Timerecording/Index.php | 2 +- .../Timerecording/TimerecordingController.php | 97 ++++++++++++++++--- public/js/pages/timerecording/index.js | 10 +- 3 files changed, 90 insertions(+), 19 deletions(-) diff --git a/Layout/default/Timerecording/Index.php b/Layout/default/Timerecording/Index.php index dc073fd1f..af5b2dcee 100644 --- a/Layout/default/Timerecording/Index.php +++ b/Layout/default/Timerecording/Index.php @@ -294,7 +294,7 @@ $years[time() - 31536000] = date('Y', time() - 31536000);
- diff --git a/application/Timerecording/TimerecordingController.php b/application/Timerecording/TimerecordingController.php index 48bf920a7..455c7579b 100644 --- a/application/Timerecording/TimerecordingController.php +++ b/application/Timerecording/TimerecordingController.php @@ -197,6 +197,7 @@ class TimerecordingController extends mfBaseController } else { $data['user_id'] = $this->me->id; } + $data['start'] = $starttime; $data['end'] = $endtime; $data['timerecordingCategory_id'] = trim($r->timerecordingCategory_id); @@ -289,6 +290,7 @@ class TimerecordingController extends mfBaseController if ($data['timerecordingCategory_id'] == "3") { $this->updateHolidays($data['user_id']); } + $this->updatePlushours($data['user_id']); } if ($mode == "edit") { @@ -326,7 +328,7 @@ class TimerecordingController extends mfBaseController $timerecordings = TimerecordingModel::search(['user_id' => $userid, 'start' => $holidays_timestamp, 'timerecordingCategory_id' => 3]); foreach ($timerecordings as $timerecording) { $daycounter = ($timerecording->end - $timerecording->start) / 86400; - $daycounter=intval(round($daycounter,0,PHP_ROUND_HALF_DOWN)); + $daycounter = intval(round($daycounter, 0, PHP_ROUND_HALF_DOWN)); $daycounter = $daycounter * 86400; if (is_int($daycounter)) { for ($i = 86400; $i <= $daycounter; $i = $i + 86400) { @@ -367,10 +369,35 @@ class TimerecordingController extends mfBaseController protected function updatePlushours($userid) { + $employee = TimerecordingEmployeeModel::search(['user_id' => $userid]); + if ($employee) { + $employee = $employee[0]; + $plushours = $employee->plushours; + $plushours_now = $employee->plushours_now; + $plushours_timestamp = $employee->plushours_timestamp; + if (!$plushours_timestamp) { + $plushours_timestamp = $employee->startdate; + $plushours_now = $plushours; + } + $endtime = time() - 86400; + $endtime = date("Y-m-d", $endtime); + $endtime = strtotime($endtime . " 23:59:00"); + + $return = $this->getTimerecordingsApi(5, null, null, null, $plushours_timestamp, $endtime); + $diffTime = $return['is'] - $return['must']; + $plushours_now = $plushours_now + $diffTime; + if ($employee->plushours_now != $diffTime) { + $employeeupdate = new TimerecordingEmployee($employee->id); + $data = []; + $data['plushours_now'] = $plushours_now; + $employeeupdate->update($data); + $employeeupdate->save(); + } + } } - protected function getTimerecordingsApi($datatype, $dataweek, $datamonth, $datayear) + protected function getTimerecordingsApi($datatype, $dataweek, $datamonth, $datayear, $startime = null, $endtime = null) { $mustSeconds = 0; $isSeconds = 0; @@ -460,6 +487,26 @@ class TimerecordingController extends mfBaseController } + } else if ($datatype == 5) { + $firstdate = $startime; + $lastdate = $endtime; + $timediff = $lastdate - $firstdate; + $daycount = $timediff / 86400; + $daycount = round($daycount, 0, PHP_ROUND_HALF_DOWN); + $searchArray = ['user_id' => $this->me->id, 'start' => $firstdate, 'end' => $lastdate]; + $timestamp = $firstdate; + + for ($i = 1; $i <= $daycount; $i++) { + $dDate = date('Y-m-d', $timestamp); + $dDay = date('w', $timestamp); + if (!$holiDay[$dDate]) { + $mustSeconds = $mustSeconds + $workingHours[$dDay]; + } + + $timestamp = $timestamp + 86400; + } + + } @@ -601,23 +648,35 @@ class TimerecordingController extends mfBaseController ); } endforeach; - $json['success'] = true; - $json['time']['auto_workinghours'] = $auto_workinghours; - $json['time']['is'] = sprintf('%02dh:%02dm', floor($isSeconds / 3600), floor($isSeconds / 60 % 60)); - $json['time']['must'] = sprintf('%02dh:%02dm', floor($mustSeconds / 3600), floor($mustSeconds / 60 % 60)); - $json['time']['holidays'] = $holiDays; - $json['time']['plushours'] = sprintf('%02dh:%02dm', floor($plusHours / 3600), floor($plusHours / 60 % 60)); - $json['data'] = $rows; - $json['recordsFiltered'] = $responsecount; - $json['recordsTotal'] = $responsecount; - $json = json_encode($json); - echo trim($json); - die(); + if ($datatype == 5) { + $response['is'] = $isSeconds; + $response['must'] = $mustSeconds; + return $response; + } else { + if ($plusHours < 0) { + $plusHoursMinutes = $plusHours * -1; + } else { + $plusHoursMinutes = $plusHours; + } + + $json['success'] = true; + $json['time']['auto_workinghours'] = $auto_workinghours; + $json['time']['is'] = sprintf('%02dh:%02dm', floor($isSeconds / 3600), floor($isSeconds / 60 % 60)); + $json['time']['must'] = sprintf('%02dh:%02dm', floor($mustSeconds / 3600), floor($mustSeconds / 60 % 60)); + $json['time']['holidays'] = $holiDays; + $json['time']['plushours'] = sprintf('%02dh:%02dm', floor($plusHours / 3600), floor($plusHoursMinutes / 60 % 60)); + $json['data'] = $rows; + $json['recordsFiltered'] = $responsecount; + $json['recordsTotal'] = $responsecount; + $json = json_encode($json); + echo trim($json); + die(); + } } protected function fillWorkinghours($dataweek) { - $dataweek = strtotime($dataweek); + $employee = TimerecordingEmployeeModel::search(['user_id' => $this->me->id]); if ($employee) { $auto_workinghours = $employee[0]->auto_workinghours; @@ -651,7 +710,7 @@ class TimerecordingController extends mfBaseController $daycounter = '0'; - + $update = false; $timestamp = $timestamp_montag; for ($i = 1; $i <= 7; $i++) { $dDate = date('Y-m-d', $timestamp); @@ -663,6 +722,7 @@ class TimerecordingController extends mfBaseController $endtime = strtotime($dDate . " " . $workingHour['end'] . ":00"); $check = $this->checkTimerecording($starttime, $endtime); if ($check['state'] == "success") { + $update = 1; $data = []; $data['user_id'] = $this->me->id; $data['start'] = $starttime; @@ -681,6 +741,10 @@ class TimerecordingController extends mfBaseController $timestamp = $timestamp + 86400;; } + if ($update) { + $this->updatePlushours($this->me->id); + $this->updateHolidays($this->me->id); + } } protected function deleteAction() @@ -694,6 +758,7 @@ class TimerecordingController extends mfBaseController } $timerecordings->delete(); $this->updateHolidays($userid); + $this->updatePlushours($userid); if ($this->request->ajax == 1) { die(); diff --git a/public/js/pages/timerecording/index.js b/public/js/pages/timerecording/index.js index dca9798cf..6bfceedec 100644 --- a/public/js/pages/timerecording/index.js +++ b/public/js/pages/timerecording/index.js @@ -86,6 +86,11 @@ table = $('#datatable').DataTable({ $('#must-time').text(json.time.must); $('#holidays').text(json.time.holidays); $('#plushours').text(json.time.plushours); + if ($("#plushours").text().includes("-")) { + $('#plushours-label').css('background-color', '#fda7a7'); + } else { + $('#plushours-label').css('background-color', '#d0fbd9'); + } if (json.time.auto_workinghours == "1") { $('#auto-workinghours-button').show(); } @@ -317,7 +322,8 @@ $(document).ready(function () { }); $("body").on("click", "#auto-workinghours-button", function () { - const date = new Date($('#date').val()); + var timestamp = $('#dataweek').val() * 1000 + const date = new Date(timestamp); var day = date.getDay(), diff = date.getDate() - day + (day == 0 ? -6 : 1); diff = date.getDate() - day + (day == 0 ? -6 : 1); @@ -333,7 +339,7 @@ $(document).ready(function () { if (confirm('Sollen die Arbeitszeiten von ' + monday + ' bis ' + sunday + ' automatisch eingetragen werden?')) { $.post(autoWorkinghoursUrl, { - dataweek: $.trim($('#date').val()), + dataweek: $.trim($('#dataweek').val()), ajax: 1 }).done(function (data) { table.ajax.reload(); From 04976033edefe1d0107b2290f849efc1de8eac87 Mon Sep 17 00:00:00 2001 From: Spitzer Daniel Date: Tue, 27 Feb 2024 10:58:05 +0100 Subject: [PATCH 5/5] =?UTF-8?q?Zeiterfassung=20Update/Bugfix=20*=20Timerec?= =?UTF-8?q?ordingReportController.php=20verweist=20in=20einer=20gewissen?= =?UTF-8?q?=20Datenbank-Eintragskonstellation=20auf=20einen=20ung=C3=BClti?= =?UTF-8?q?gen=20Array=20Index.=20Hab=20die=20gesamtsollzeitberechnung=20t?= =?UTF-8?q?empor=C3=A4r=20ausgeschalten=20*=20Neu=20Migration=20(Vorbereit?= =?UTF-8?q?en=20der=20DB=20auf=20eigenes=20=C3=9C-Zeitkonto)=20*=20Kalende?= =?UTF-8?q?r=20Feiertagsdescription=20angepasst=20*=20Geburtstage=20nun=20?= =?UTF-8?q?m=C3=B6glich=20in=20Personaladministration=20und=20Kalender=20*?= =?UTF-8?q?=20Initiale=20=C3=9Cberstunden=20sind=20nun=20m=C3=B6glich=20*?= =?UTF-8?q?=20Berechnung=20Urlaubstage=20nun=20exakt=20*=20Anzeige=20Mehrs?= =?UTF-8?q?tunden/=C3=9Cberstunden/Offene=20Urlaube=20in=20Personaladminis?= =?UTF-8?q?tration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Layout/default/TimerecordingEmployee/Index.php | 11 ++++++++++- application/Timerecording/TimerecordingController.php | 3 +++ .../TimerecordingEmployeeModel.php | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Layout/default/TimerecordingEmployee/Index.php b/Layout/default/TimerecordingEmployee/Index.php index 28167f002..d0f1a795f 100644 --- a/Layout/default/TimerecordingEmployee/Index.php +++ b/Layout/default/TimerecordingEmployee/Index.php @@ -42,6 +42,9 @@ $type[3] = "Lehrling"; Start Zeitaufzeichnung Sollzeiten Sollstunden + Mehrstunden + Überstunden + Offene Urlaube Schnellbuchung @@ -53,6 +56,9 @@ $type[3] = "Lehrling"; + + + @@ -73,6 +79,9 @@ $type[3] = "Lehrling"; id]['startdate']) ? date("d.m.Y", $timerecordingemployees[$timerecordinguser->id]['startdate']) : "-" ?> id]['datetimetext'] : "" ?> + id]['plushours_now']/ 3600),($timerecordingemployees[$timerecordinguser->id]['plushours_now']/ 60 % 60)) ?> + id]['overtime_now']/ 3600),($timerecordingemployees[$timerecordinguser->id]['overtime_now']/ 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 = [6]; + var hidesearch = [3,4,5,6,7,9]; $(document).ready(function () { diff --git a/application/Timerecording/TimerecordingController.php b/application/Timerecording/TimerecordingController.php index 455c7579b..b52c4943b 100644 --- a/application/Timerecording/TimerecordingController.php +++ b/application/Timerecording/TimerecordingController.php @@ -18,6 +18,9 @@ class TimerecordingController extends mfBaseController protected function indexAction() { + $this->updatePlushours($this->me->id); + $this->updateHolidays($this->me->id); + $timerecordingCategoriess = TimerecordingCategoryModel::getAll(); $this->layout()->set("timerecordingCategoriess", $timerecordingCategoriess); $this->layout()->setTemplate("Timerecording/Index"); diff --git a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php index a4fce4ecd..a76f9a4a7 100644 --- a/application/TimerecordingEmployee/TimerecordingEmployeeModel.php +++ b/application/TimerecordingEmployee/TimerecordingEmployeeModel.php @@ -147,6 +147,9 @@ class TimerecordingEmployeeModel $where .= " AND user_id=$userid"; } } + if (array_key_exists("startdate", $filter)) { + $where .= " AND startdate is not null"; + } //var_dump($filter, $where);exit; return $where;