Zeiterfassung Feature Updates

* Reports wurde um Soll/Ist Detail Auswertung erweitert
* Nachtzulage wird nun auch in der Verrechnungsübersicht angezeigt
* M25,Ü50,Ü100 werden nun in Stichtagsauswertung mit berechnet
* Bei der offenen Arbeitstage Auswertung wird nun die Arbeitszeitverschiebung rausgerechnet
This commit is contained in:
Daniel Spitzer
2026-02-13 08:39:15 +01:00
parent ae73d9be4d
commit b81ea45823
6 changed files with 371 additions and 6 deletions

View File

@@ -40,6 +40,7 @@
<th class="text-center">Sollabweichung</th> <th class="text-center">Sollabweichung</th>
<th class="text-center">Akuelle Gutstunden</th> <th class="text-center">Akuelle Gutstunden</th>
<th class="text-center">Akuelle Überstunden</th> <th class="text-center">Akuelle Überstunden</th>
<th class="text-center">Nachtzulage</th>
<?php if ($me->superexpertEnabled()): ?> <?php if ($me->superexpertEnabled()): ?>
<th class="text-center">Black P. Stunden</th> <th class="text-center">Black P. Stunden</th>
<?php endif; ?> <?php endif; ?>
@@ -55,6 +56,7 @@
<th></th> <th></th>
<th></th> <th></th>
<th></th> <th></th>
<th></th>
<?php if ($me->superexpertEnabled()): ?> <?php if ($me->superexpertEnabled()): ?>
<th></th> <th></th>
<?php endif; ?> <?php endif; ?>
@@ -101,6 +103,8 @@
class="text-center"><?= $timerecording['data']['time']['plushours_now'] ?></td> class="text-center"><?= $timerecording['data']['time']['plushours_now'] ?></td>
<td data-order="<?= $timerecording['data']['time']['overtime_noworder'] ?>" <td data-order="<?= $timerecording['data']['time']['overtime_noworder'] ?>"
class="text-center"><?= $timerecording['data']['time']['overtime_now'] ?></td> class="text-center"><?= $timerecording['data']['time']['overtime_now'] ?></td>
<td data-order="<?= $timerecording['data']['time']['overtimes']['nightAllowance'] ?>"
class="text-center"><?= number_format(round($timerecording['data']['time']['overtimes']['nightAllowance'] / 3600, 2), "2", ",", ".") ?></td>
<?php if ($me->superexpertEnabled()): ?> <?php if ($me->superexpertEnabled()): ?>
<td data-order="<?= $timerecording['data']['time']['bpahours'] ?>" <td data-order="<?= $timerecording['data']['time']['bpahours'] ?>"
class="text-center"><?= $timerecording['data']['time']['bpahours'] ?></td> class="text-center"><?= $timerecording['data']['time']['bpahours'] ?></td>
@@ -126,9 +130,9 @@
src="<?= self::getResourcePath() ?>datatables/DataTables-2x/datatables.min.js"></script> src="<?= self::getResourcePath() ?>datatables/DataTables-2x/datatables.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
var hidesearch = [2, 3, 4, 5, 6, 8, 9]; var hidesearch = [2, 3, 4, 5, 6, 7, 9, 10];
<?php if ($me->superexpertEnabled()): ?> <?php if ($me->superexpertEnabled()): ?>
hidesearch = [2, 3, 4, 5, 6, 7, 9, 10]; hidesearch = [2, 3, 4, 5, 6, 7, 8, 10, 11];
<?php endif; ?> <?php endif; ?>
var pageLength = 100; var pageLength = 100;
var initc=2; var initc=2;

View File

@@ -144,6 +144,7 @@
<th title="Mehrstunden 25%" class="text-center min-w-70">M25</th> <th title="Mehrstunden 25%" class="text-center min-w-70">M25</th>
<th title="Überstunden 50%" class="text-center min-w-70">Ü50</th> <th title="Überstunden 50%" class="text-center min-w-70">Ü50</th>
<th title="Überstunden 100%" class="text-center min-w-70">Ü100</th> <th title="Überstunden 100%" class="text-center min-w-70">Ü100</th>
<th title="Nachtzulage" class="text-center min-w-70">NZ</th>
<th class="text-center">Diäten</th> <th class="text-center">Diäten</th>
<th class="text-center" title="Homeoffice">HO</th> <th class="text-center" title="Homeoffice">HO</th>
</tr> </tr>
@@ -164,6 +165,7 @@
<th></th> <th></th>
<th></th> <th></th>
<th></th> <th></th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -219,6 +221,7 @@
class="text-center position-relative "><?= ($timerecording->overtime50free > 0) ? '<i class="fas fa-arrow-to-left change-overtime-50" data-toggle="modal" data-target="#overtimeModal" data-hours="' . number_format(round($timerecording->overtime50free / 3600, 2), "2", ",", ".") . '" data-id="' . $timerecording->id . '"></i>' : '' ?> <?= '<span class="filler-left">' . number_format(round($timerecording->overtime50free / 3600, 2), "2", ",", ".") ?></span></td> class="text-center position-relative "><?= ($timerecording->overtime50free > 0) ? '<i class="fas fa-arrow-to-left change-overtime-50" data-toggle="modal" data-target="#overtimeModal" data-hours="' . number_format(round($timerecording->overtime50free / 3600, 2), "2", ",", ".") . '" data-id="' . $timerecording->id . '"></i>' : '' ?> <?= '<span class="filler-left">' . number_format(round($timerecording->overtime50free / 3600, 2), "2", ",", ".") ?></span></td>
<td data-order="<?= $timerecording->overtime100free ?>" <td data-order="<?= $timerecording->overtime100free ?>"
class="text-center position-relative "><?= ($timerecording->overtime100free > 0) ? '<i class="fas fa-arrow-to-left change-overtime-100" data-toggle="modal" data-target="#overtimeModal" data-hours="' . number_format(round($timerecording->overtime100free / 3600, 2), "2", ",", ".") . '" data-id="' . $timerecording->id . '"></i>' : '' ?> <?= '<span class="filler-left">' . number_format(round($timerecording->overtime100free / 3600, 2), "2", ",", ".") ?></span></td> class="text-center position-relative "><?= ($timerecording->overtime100free > 0) ? '<i class="fas fa-arrow-to-left change-overtime-100" data-toggle="modal" data-target="#overtimeModal" data-hours="' . number_format(round($timerecording->overtime100free / 3600, 2), "2", ",", ".") . '" data-id="' . $timerecording->id . '"></i>' : '' ?> <?= '<span class="filler-left">' . number_format(round($timerecording->overtime100free / 3600, 2), "2", ",", ".") ?></span></td>
<td class="text-center"><?= number_format(round($timerecording->night_allowance / 3600, 2), "2", ",", ".") ?></td>
<td data-order="<?= $timerecording->diet ?>" <td data-order="<?= $timerecording->diet ?>"
class="text-center"><?= number_format($timerecording->diet, 2, ',', '.') . " €" ?></td> class="text-center"><?= number_format($timerecording->diet, 2, ',', '.') . " €" ?></td>
<td class="text-center"><?= $timerecording->homeoffice ?> T</td> <td class="text-center"><?= $timerecording->homeoffice ?> T</td>
@@ -312,9 +315,9 @@
src="<?= self::getResourcePath() ?>datatables/DataTables-2x/datatables.min.js?<?= $git_merge_ts ?>"></script> src="<?= self::getResourcePath() ?>datatables/DataTables-2x/datatables.min.js?<?= $git_merge_ts ?>"></script>
<script type="text/javascript"> <script type="text/javascript">
var hidesearch = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; var hidesearch = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
<?php if ($me->superexpertEnabled()): ?> <?php if ($me->superexpertEnabled()): ?>
hidesearch = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; hidesearch = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
<?php endif; ?> <?php endif; ?>
var pageLength = 100; var pageLength = 100;
var initc=3; var initc=3;

View File

@@ -56,6 +56,26 @@
</form> </form>
</div> </div>
</div> </div>
<div class="feature col-lg-6 card h-100 mt-3">
<div class="card-body">
<form class="form-horizontal" method="post"
action="<?= self::getUrl("TimerecordingReportExport", "generateworkdaysdetail") ?>">
<h3 class="fs-2 text-body-emphasis">Soll/Ist Detail Auswertung <i
class="fa-duotone fa-solid fa-file-xls fa-xls-calendar"></i></h3>
<p>Hier wird eine XLS Auswertung pro Mitarbeiter generiert mit Soll, Ist und Differenz für jeden Arbeitstag im Monat.<br>
</p>
<div class="row">
<div class="input-group col-12 col-lg-6">
<input type="month" name="month" class="form-control" value="<?= date('Y-m'); ?>" aria-label="Monat">
<button class="btn btn-outline-secondary" type="submit">Auswerten</button>
</div>
</div>
</form>
</div>
</div>
</div> </div>
</div> </div>

View File

@@ -1167,6 +1167,9 @@ class TimerecordingController extends mfBaseController
$hours = floor($seconds / 3600); $hours = floor($seconds / 3600);
$sum = "-" .sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes); $sum = "-" .sprintf("%02d", $hours) . ":" . sprintf("%02d", $minutes);
$day = $daysgerm[date("w", $timerecording->start)]; $day = $daysgerm[date("w", $timerecording->start)];
if ($ajax == 0) {
$workdaycheck[] = $datadate;
}
} }
if (($timerecording->timerecordingCategory->approval == 1 && $timerecording->approved == 0) || ($timerecording->timerecordingCategory->approval_fibu == 1 && $timerecording->approved == 0)) { if (($timerecording->timerecordingCategory->approval == 1 && $timerecording->approved == 0) || ($timerecording->timerecordingCategory->approval_fibu == 1 && $timerecording->approved == 0)) {

View File

@@ -1,5 +1,8 @@
<?php <?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class TimerecordingBillingController extends mfBaseController class TimerecordingBillingController extends mfBaseController
{ {
@@ -121,6 +124,9 @@ class TimerecordingBillingController extends mfBaseController
case "generateopenworkdays": case "generateopenworkdays":
$return = $this->generateopenworkdays($month); $return = $this->generateopenworkdays($month);
break; break;
case "generateworkdaysdetail":
$return = $this->generateworkdaysdetail($month);
break;
case "generatebmdexportclosed": case "generatebmdexportclosed":
$return = $this->generateBmdExportClosed($month); $return = $this->generateBmdExportClosed($month);
break; break;
@@ -436,6 +442,162 @@ class TimerecordingBillingController extends mfBaseController
exit; exit;
} }
protected function generateworkdaysdetail($month)
{
// Aktiviert das 1904-Datumssystem global für dieses Script, um negative Zeiten zu unterstützen
\PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar(\PhpOffice\PhpSpreadsheet\Shared\Date::CALENDAR_MAC_1904);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$headerarray = ["Monat", "Mitarbeiter", "Datum", "Soll", "Ist", "Differenz"];
$column = 'A';
foreach ($headerarray as $header) {
$sheet->setCellValue($column . '1', $header);
$column++;
}
$month_start = strtotime("01." . $month);
$month_end = strtotime("last day of this month", $month_start);
$month_end = strtotime("23:59:59", $month_end);
$daycount = date("t", $month_start);
$holidays = TimerecordingHolidayModel::getAll();
$holiDay = [];
foreach ($holidays as $holiday) {
$holiDay[date('Y-m-d', $holiday->timestamp)] = $holiday->timestamp;
}
$rowIdx = 2;
$timerecordingsEmployees = TimerecordingEmployeeModel::getAll();
foreach ($timerecordingsEmployees as $timerecordingsEmployee) {
if ($timerecordingsEmployee->bmd_active == 0 || $timerecordingsEmployee->startdate > $month_end || ($timerecordingsEmployee->enddate && $timerecordingsEmployee->enddate < $month_start)) continue;
$user = new User($timerecordingsEmployee->user_id);
$user_id = $user->id;
// Schedule
$workinghours = TimerecordingEmployeeWorkingHourModel::search(['user_id' => $user_id]);
$userWorkingHours = [];
foreach ($workinghours as $wh) {
if (!isset($userWorkingHours[$wh->day])) $userWorkingHours[$wh->day] = 0;
$userWorkingHours[$wh->day] += (strtotime("2000-01-01 " . $wh->end . ":00") - strtotime("2000-01-01 " . $wh->start . ":00"));
}
$workinghourshistory = TimerecordingEmployeeWorkingHourHistoryModel::search(['user_id' => $user_id]);
$userWorkingHoursHistory = [];
if ($workinghourshistory) {
$userWorkingHoursHistory[9732489200] = $userWorkingHours;
foreach ($workinghourshistory as $whh) {
$histWH = [];
$whh_hours = json_decode($whh->workinghours, true);
foreach ($whh_hours as $h) {
if (!isset($histWH[$h['day']])) $histWH[$h['day']] = 0;
$histWH[$h['day']] += (strtotime("2000-01-01 " . $h['end'] . ":00") - strtotime("2000-01-01 " . $h['start'] . ":00"));
}
$userWorkingHoursHistory[$whh->enddate] = $histWH;
}
ksort($userWorkingHoursHistory);
}
// Ist
$timerecordings = TimerecordingModel::search(['user_id' => $user_id, 'start' => $month_start, 'end' => $month_end]);
$istPerDay = [];
foreach ($timerecordings as $tr) {
$cat = $tr->timerecordingCategory;
if ($cat->hourday == 1 || $cat->hourday == 7) {
$day = date('Y-m-d', $tr->start);
if (!isset($istPerDay[$day])) $istPerDay[$day] = 0;
$seconds = $tr->end - $tr->start;
$istPerDay[$day] += $seconds;
} else if ($cat->hourday == 6 || $cat->hourday == 10) {
$day = date('Y-m-d', $tr->start);
if (!isset($istPerDay[$day])) $istPerDay[$day] = 0;
// Zeitausgleich/Abzug wird hier POSITIV angerechnet um das Soll zu füllen
$seconds = $tr->end - $tr->start;
$istPerDay[$day] += $seconds;
} else if ($cat->hourday == 2 || $cat->hourday == 3) {
$calcstart = max($tr->start, $month_start);
$calcend = $tr->end ? min($tr->end, $month_end) : min(time(), $month_end);
for ($t = $calcstart; $t <= $calcend; $t += 86400) {
$dDate = date('Y-m-d', $t);
if (isset($holiDay[$dDate])) continue;
$dDay = date('w', $t);
$activeWH = $userWorkingHours;
if ($userWorkingHoursHistory) {
foreach ($userWorkingHoursHistory as $whkey => $whdata) {
if (strtotime(date('Y-m-d 23:59:59', $whkey)) >= $t) {
$activeWH = $whdata;
break;
}
}
}
if (isset($activeWH[$dDay])) {
if (!isset($istPerDay[$dDate])) $istPerDay[$dDate] = 0;
$istPerDay[$dDate] += $activeWH[$dDay];
}
}
}
}
// Loop Days
for ($i = 0; $i < $daycount; $i++) {
$t = strtotime("+$i days", $month_start);
$dDate = date('Y-m-d', $t);
$dDay = date('w', $t);
$activeWH = $userWorkingHours;
if ($userWorkingHoursHistory) {
foreach ($userWorkingHoursHistory as $whkey => $whdata) {
if (strtotime(date('Y-m-d 23:59:59', $whkey)) >= $t) {
$activeWH = $whdata;
break;
}
}
}
$soll = 0;
if (!isset($holiDay[$dDate]) && $t >= $timerecordingsEmployee->startdate && (!$timerecordingsEmployee->enddate || $t <= $timerecordingsEmployee->enddate)) {
$soll = $activeWH[$dDay] ?? 0;
}
$ist = $istPerDay[$dDate] ?? 0;
if ($soll > 0 || $ist > 0) {
$diff = $ist - $soll;
$sheet->setCellValue('A' . $rowIdx, date("m-Y", $month_start));
$sheet->setCellValue('B' . $rowIdx, $user->name);
$sheet->setCellValue('C' . $rowIdx, date("d.m.Y", $t));
// Zeitwerte als Excel-Zeit (Sekunden / 86400)
$sheet->setCellValue('D' . $rowIdx, $soll / 86400);
$sheet->setCellValue('E' . $rowIdx, $ist / 86400);
$sheet->setCellValue('F' . $rowIdx, $diff / 86400);
$rowIdx++;
}
}
}
// Styling & Formate
$sheet->getStyle('A1:F1')->getFont()->setBold(true);
// Zeitformat [hh]:mm für die Spalten D, E und F
$sheet->getStyle('D2:F' . ($rowIdx - 1))->getNumberFormat()->setFormatCode('[hh]:mm');
foreach (range('A', 'F') as $col) {
$sheet->getColumnDimension($col)->setAutoSize(true);
}
$filename = "workdays_detail_" . $month . ".xlsx";
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $filename . '"');
header('Cache-Control: max-age=0');
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
exit;
}
protected function generateBmdExport($month, $nlz = 0, $export = 1) protected function generateBmdExport($month, $nlz = 0, $export = 1)
{ {
//create and download csv file //create and download csv file

View File

@@ -26,6 +26,172 @@ class TimerecordingReportExportController extends mfBaseController
$this->layout()->setTemplate("TimerecordingReportExport/Index"); $this->layout()->setTemplate("TimerecordingReportExport/Index");
} }
protected function generateworkdaysdetailAction()
{
$r = $this->request;
$month = $r->month; // can be m.Y or YYYY-MM
if (!$month) {
$month = date("m.Y");
}
// Handle YYYY-MM from <input type="month">
if (strpos($month, '-') !== false) {
$month = date("m.Y", strtotime($month . "-01"));
}
// Aktiviert das 1904-Datumssystem global für dieses Script, um negative Zeiten zu unterstützen
\PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar(\PhpOffice\PhpSpreadsheet\Shared\Date::CALENDAR_MAC_1904);
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$headerarray = ["Monat", "Mitarbeiter", "Datum", "Soll", "Ist", "Differenz"];
$column = 'A';
foreach ($headerarray as $header) {
$sheet->setCellValue($column . '1', $header);
$column++;
}
$month_start = strtotime("01." . $month);
$month_end = strtotime("last day of this month", $month_start);
$month_end = strtotime("23:59:59", $month_end);
$daycount = date("t", $month_start);
$holidays = TimerecordingHolidayModel::getAll();
$holiDay = [];
foreach ($holidays as $holiday) {
$holiDay[date('Y-m-d', $holiday->timestamp)] = $holiday->timestamp;
}
$rowIdx = 2;
$timerecordingsEmployees = TimerecordingEmployeeModel::getAll();
foreach ($timerecordingsEmployees as $timerecordingsEmployee) {
if ($timerecordingsEmployee->bmd_active == 0 || $timerecordingsEmployee->startdate > $month_end || ($timerecordingsEmployee->enddate && $timerecordingsEmployee->enddate < $month_start)) continue;
$user = new User($timerecordingsEmployee->user_id);
$user_id = $user->id;
// Schedule
$workinghours = TimerecordingEmployeeWorkingHourModel::search(['user_id' => $user_id]);
$userWorkingHours = [];
foreach ($workinghours as $wh) {
if (!isset($userWorkingHours[$wh->day])) $userWorkingHours[$wh->day] = 0;
$userWorkingHours[$wh->day] += (strtotime("2000-01-01 " . $wh->end . ":00") - strtotime("2000-01-01 " . $wh->start . ":00"));
}
$workinghourshistory = TimerecordingEmployeeWorkingHourHistoryModel::search(['user_id' => $user_id]);
$userWorkingHoursHistory = [];
if ($workinghourshistory) {
$userWorkingHoursHistory[9732489200] = $userWorkingHours;
foreach ($workinghourshistory as $whh) {
$histWH = [];
$whh_hours = json_decode($whh->workinghours, true);
foreach ($whh_hours as $h) {
if (!isset($histWH[$h['day']])) $histWH[$h['day']] = 0;
$histWH[$h['day']] += (strtotime("2000-01-01 " . $h['end'] . ":00") - strtotime("2000-01-01 " . $h['start'] . ":00"));
}
$userWorkingHoursHistory[$whh->enddate] = $histWH;
}
ksort($userWorkingHoursHistory);
}
// Ist
$timerecordings = TimerecordingModel::search(['user_id' => $user_id, 'start' => $month_start, 'end' => $month_end]);
$istPerDay = [];
foreach ($timerecordings as $tr) {
$cat = $tr->timerecordingCategory;
if ($cat->hourday == 1 || $cat->hourday == 7) {
$day = date('Y-m-d', $tr->start);
if (!isset($istPerDay[$day])) $istPerDay[$day] = 0;
$seconds = $tr->end - $tr->start;
$istPerDay[$day] += $seconds;
} else if ($cat->hourday == 6 || $cat->hourday == 10) {
$day = date('Y-m-d', $tr->start);
if (!isset($istPerDay[$day])) $istPerDay[$day] = 0;
$seconds = $tr->end - $tr->start;
$istPerDay[$day] += $seconds;
} else if ($cat->hourday == 2 || $cat->hourday == 3) {
$calcstart = max($tr->start, $month_start);
$calcend = $tr->end ? min($tr->end, $month_end) : min(time(), $month_end);
for ($t = $calcstart; $t <= $calcend; $t += 86400) {
$dDate = date('Y-m-d', $t);
if (isset($holiDay[$dDate])) continue;
$dDay = date('w', $t);
$activeWH = $userWorkingHours;
if ($userWorkingHoursHistory) {
foreach ($userWorkingHoursHistory as $whkey => $whdata) {
if (strtotime(date('Y-m-d 23:59:59', $whkey)) >= $t) {
$activeWH = $whdata;
break;
}
}
}
if (isset($activeWH[$dDay])) {
if (!isset($istPerDay[$dDate])) $istPerDay[$dDate] = 0;
$istPerDay[$dDate] += $activeWH[$dDay];
}
}
}
}
// Loop Days
for ($i = 0; $i < $daycount; $i++) {
$t = strtotime("+$i days", $month_start);
$dDate = date('Y-m-d', $t);
$dDay = date('w', $t);
$activeWH = $userWorkingHours;
if ($userWorkingHoursHistory) {
foreach ($userWorkingHoursHistory as $whkey => $whdata) {
if (strtotime(date('Y-m-d 23:59:59', $whkey)) >= $t) {
$activeWH = $whdata;
break;
}
}
}
$soll = 0;
if (!isset($holiDay[$dDate]) && $t >= $timerecordingsEmployee->startdate && (!$timerecordingsEmployee->enddate || $t <= $timerecordingsEmployee->enddate)) {
$soll = $activeWH[$dDay] ?? 0;
}
$ist = $istPerDay[$dDate] ?? 0;
if ($soll > 0 || $ist > 0) {
$diff = $ist - $soll;
$sheet->setCellValue('A' . $rowIdx, date("m-Y", $month_start));
$sheet->setCellValue('B' . $rowIdx, $user->name);
$sheet->setCellValue('C' . $rowIdx, date("d.m.Y", $t));
// Zeitwerte als Excel-Zeit (Sekunden / 86400)
$sheet->setCellValue('D' . $rowIdx, $soll / 86400);
$sheet->setCellValue('E' . $rowIdx, $ist / 86400);
$sheet->setCellValue('F' . $rowIdx, $diff / 86400);
$rowIdx++;
}
}
}
// Styling & Formate
$sheet->getStyle('A1:F1')->getFont()->setBold(true);
// Zeitformat [hh]:mm für die Spalten D, E und F
$sheet->getStyle('D2:F' . ($rowIdx - 1))->getNumberFormat()->setFormatCode('[hh]:mm');
foreach (range('A', 'F') as $col) {
$sheet->getColumnDimension($col)->setAutoSize(true);
}
$filename = "workdays_detail_" . $month . ".xlsx";
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $filename . '"');
header('Cache-Control: max-age=0');
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
exit;
}
protected function exportdeadlineAction() protected function exportdeadlineAction()
{ {
$r = $this->request; $r = $this->request;
@@ -62,7 +228,7 @@ class TimerecordingReportExportController extends mfBaseController
$headers = [ $headers = [
'Stichtag', 'Pers. Nr.', 'Mitarbeiter', 'Urlaub', 'Mehrstunden', 'Gutstunden' 'Stichtag', 'Pers. Nr.', 'Mitarbeiter', 'Urlaub', 'Mehrstunden', 'Gutstunden', 'M25', 'Ü50', 'Ü100', 'NZ'
]; ];
if ($this->me->superexpertEnabled()) { if ($this->me->superexpertEnabled()) {
$headers[] = 'Black P. St.'; $headers[] = 'Black P. St.';
@@ -106,6 +272,14 @@ class TimerecordingReportExportController extends mfBaseController
$sheet->setCellValue('D' . $row, $holidays[$timerecordingbillingsemployee->timerecordingEmployee->user_id]); $sheet->setCellValue('D' . $row, $holidays[$timerecordingbillingsemployee->timerecordingEmployee->user_id]);
$sheet->setCellValue('E' . $row, round(($timerecordingbillingsemployee->plushours_all + $timerecordingbillingsemployee->transfer_plushours) / 3600, 2)); $sheet->setCellValue('E' . $row, round(($timerecordingbillingsemployee->plushours_all + $timerecordingbillingsemployee->transfer_plushours) / 3600, 2));
$sheet->setCellValue('F' . $row, round(($timerecordingbillingsemployee->timerecordingEmployee->overtime_now + $overtimediff) / 3600, 2)); $sheet->setCellValue('F' . $row, round(($timerecordingbillingsemployee->timerecordingEmployee->overtime_now + $overtimediff) / 3600, 2));
$sheet->setCellValue('G' . $row, round($timerecordingbillingsemployee->plushours25 / 3600, 2));
$sheet->setCellValue('H' . $row, round($timerecordingbillingsemployee->overtime50free / 3600, 2));
$sheet->setCellValue('I' . $row, round($timerecordingbillingsemployee->overtime100free / 3600, 2));
$sheet->setCellValue('J' . $row, round($timerecordingbillingsemployee->night_allowance / 3600, 2));
if ($this->me->superexpertEnabled()) {
$sheet->setCellValue('K' . $row, round(($timerecordingbillingsemployee->timerecordingEmployee->bpahours + $bpadiff) / 3600, 2));
}
$oldEmployee_id = $timerecordingbillingsemployee->timerecordingEmployee_id; $oldEmployee_id = $timerecordingbillingsemployee->timerecordingEmployee_id;
$row++; $row++;
@@ -115,7 +289,6 @@ class TimerecordingReportExportController extends mfBaseController
$sheet->getStyle('A2:A' . $row)->getNumberFormat()->setFormatCode('@'); $sheet->getStyle('A2:A' . $row)->getNumberFormat()->setFormatCode('@');
$sheet->getStyle('C2:C' . $row)->getNumberFormat()->setFormatCode($number_format_code);
$sheet->getStyle('E2:E' . $row)->getNumberFormat()->setFormatCode($number_format_code); $sheet->getStyle('E2:E' . $row)->getNumberFormat()->setFormatCode($number_format_code);
$sheet->getStyle('F2:F' . $row)->getNumberFormat()->setFormatCode($number_format_code); $sheet->getStyle('F2:F' . $row)->getNumberFormat()->setFormatCode($number_format_code);
$sheet->getStyle('G2:G' . $row)->getNumberFormat()->setFormatCode($number_format_code); $sheet->getStyle('G2:G' . $row)->getNumberFormat()->setFormatCode($number_format_code);