work_time-1.0.x-dev/modules/fingerprint/src/ProcessTimeService.php
modules/fingerprint/src/ProcessTimeService.php
<?php
namespace Drupal\fingerprint;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\work_time\WorkTimeHoliday;
/**
* Class Calculate Service Fingerprint.
*
* @package Drupal\fingerprint\Services
*/
class ProcessTimeService {
use StringTranslationTrait;
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Work time holiday service.
*
* @var \Drupal\work_time\WorkTimeHoliday
*/
protected $holiday;
/**
* Constructs a new GroupAdminRouteSubscriber.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\work_time\WorkTimeHoliday $holiday
* Work time holiday service.
*/
public function __construct(ConfigFactoryInterface $config_factory, WorkTimeHoliday $holiday) {
$this->configFactory = $config_factory;
$this->holiday = $holiday;
}
/**
* Process time records by user from fingerprint machine.
*
* {@inheritdoc}
*/
public function processTimeRecords($timeRecords, $shifts, $margin) {
$result = $dayRecords = [];
// 8h working a day, 12h max working a day for overtime.
$frameWorkingHour = [
'normal' => 8 * 3600 + $margin,
'overtime' => 12 * 3600 + $margin,
];
$n = count($timeRecords);
for ($i = 0; $i < $n; $i++) {
$timeRecord = $timeRecords[$i];
$date = date('Y-m-d', $timeRecord);
$dayRecords[$date][] = $timeRecord;
if ($i < $n) {
for ($next = $i + 1; $next < $n; $next++) {
// Check working hour in the frame.
if ($timeRecords[$next] < $timeRecord + $frameWorkingHour['overtime']) {
$dayRecords[$date][] = $timeRecords[$next];
}
else {
break;
}
}
$i = $next - 1;
}
else {
$dayRecords[$date][] = $timeRecord;
}
}
foreach ($dayRecords as $date => $dayRecord) {
$result[$date] = $this->getData($dayRecord, $shifts);
}
return $result;
}
/**
* Process data fingerprint machine.
*
* {@inheritdoc}
*/
public function getData($timeRecords, $workingHour) {
$status = [];
$first = array_shift($timeRecords);
$config = $this->configFactory->getEditable('work_time.settings');
$hoursWork = $config->get('hours');
$holidays = $this->holiday->getHolidays('', date('Y', $first));
$config = $this->configFactory->getEditable('fingerprint.settings');
$nightShift = $config->get('shift_night');
if ($first > $workingHour['start']) {
$status[] = $this->t('late');
}
$checkIn = date('H:i', $first);
$total = $totalDisplay = $last = $lunch = $break = $checkOut = $night = '';
$sunday = $holiday = '';
if (!empty($timeRecords)) {
$last = array_pop($timeRecords);
$checkOut = date('H:i', $last);
if ($last < $workingHour['end']) {
$status[] = $this->t('early');
}
}
if (empty($last)) {
$status[] = $this->t('not checkout');
}
if (!empty($first) && !empty($last)) {
$total = $last - $first;
$totalDisplay = round($total / 3600, 1);
}
if (!empty($timeRecords)) {
foreach ($timeRecords as $index => &$time) {
$time = date('H:i', $time);
if (!$index) {
$lunch = $time;
}
}
$break = implode(', ', $timeRecords);
}
else {
$status[] = $this->t('no lunch');
}
if ($timeRecords < $workingHour['start_margin'] || $timeRecords > $workingHour['end_margin']) {
$status[] = $this->t('undefined');
}
$overtime = $totalDisplay > $hoursWork ? $totalDisplay - $hoursWork : '';
if (!empty($last)) {
$nightShiftHour = date('Y-m-d', $last) . ' ' . $nightShift;
if ($last > $nightShiftHour) {
$night = $totalDisplay;
$totalDisplay = '';
}
}
if (!date('w', $first)) {
$sunday = $totalDisplay;
$totalDisplay = '';
}
if (!empty($holidays) && in_array(date('Y-m-d', $first), $holidays)) {
$holiday = $totalDisplay;
$totalDisplay = '';
}
return [
'created' => $first,
'stopped' => $last,
'checkin' => $checkIn,
'checkout' => $checkOut,
'lunch' => $lunch,
'total' => $totalDisplay,
'break' => $lunch != $break ? $break : '',
'time_total' => $total,
'night' => $night,
'over_time' => $overtime,
'sunday' => $sunday,
'holiday' => $holiday,
'description' => implode(', ', $status),
];
}
/**
* {@inheritdoc}
*/
public function getShifts() {
$config = $this->configFactory->getEditable('fingerprint.settings');
$workingHours = explode(',', $config->get('shift'));
foreach ($workingHours as &$workingHour) {
[$startHour, $endHour] = explode('-', str_replace(' ', '', $workingHour));
$start = new \DateTime($startHour);
$end = new \DateTime($endHour);
$countNewDay = $end < $start;
$workingHour = [
'start' => $startHour,
'end' => !empty($countNewDay) ? '-1 day' : $endHour,
'new_day' => $countNewDay,
];
}
return $workingHours;
}
/**
* Check which shift match which time checkin. Margin 30 minutes.
*
* {@inheritdoc}
*/
public function getShift($timestamp, $workingHours = [], $margin = 1800) {
$date = date('Y-m-d', $timestamp);
$workingHour = FALSE;
if (empty($workingHours)) {
$workingHours = $this->getShifts();
}
if (empty($workingHours)) {
return FALSE;
}
foreach ($workingHours as $workingHour) {
$startHour = $workingHour['start'];
$endHour = $workingHour['end'];
$workingHour = [
'start' => strtotime($date . ' ' . $startHour),
'end' => strtotime($date . ' ' . $endHour),
'start_margin' => strtotime($date . ' ' . $startHour) - $margin,
'end_margin' => strtotime($date . ' ' . $startHour) + $margin,
];
if ($timestamp >= $workingHour['start_margin'] && $timestamp <= $workingHour['end_margin']) {
break;
}
}
return $workingHour;
}
}
