Untitled

mail@pastecode.io avatar
unknown
plain_text
5 months ago
5.3 kB
5
Indexable
function prepareWorkingHoursEntries($selectedDate, $startTime, $endTime, $previous_entries = [])
{
    $workingHours = [];
    $breaks = [];
    $oldBreaks = [];

    $reqStartTime = $startTime;

    $takenBreak = 0;
    $workHours = 0;
    if (!empty($previous_entries)) {
        foreach ($previous_entries as $key => $previous_entry) {
            $startDateTime = DateTime::createFromFormat('H:i:s', $previous_entry['start']);
            $endDateTime = DateTime::createFromFormat('H:i:s', $previous_entry['end']);
            $interval = $startDateTime->diff($endDateTime);
            $workingHours[] = $previous_entry;
            if ($previous_entry['type'] == "break") {
                $takenBreak = $takenBreak + (($interval->h * 60) + $interval->i);
                $oldBreaks[] = addBreak($startDateTime->format('H:i:s'), 0, (($interval->h * 60) + $interval->i));
            } else {
                $workHours = $workHours + (($interval->h * 60) + $interval->i);
            }

            if ($key == 0) {
                $startTime = $startDateTime->format('H:i:s');
            }
        }
    }

    $totalHours = calculateTotalHours($reqStartTime, $endTime);

    $totalHours = $totalHours + $workHours;

    $compulsorBreaks = [
        [
            'hour' => '120',
            'min'  => '15',
        ],
        [
            'hour' => '240',
            'min'  => '30',
        ],
        [
            'hour' => '420',
            'min'  => '15',
        ]
    ];

    $requiredBreak = 0;
    $oldBreak = 0;
    foreach ($compulsorBreaks as $compulsorBreak) {
        if ($totalHours >= ((int) $compulsorBreak['hour'] + $oldBreak)) {
            $requiredBreak = $requiredBreak + (int) $compulsorBreak['min'];
        }
    }

    $remBreak = 0;

    if ($takenBreak < $requiredBreak) {
        $remBreak = $requiredBreak - $takenBreak;
    }

    if ($workHours == 0) {
        $oldBreak = 0;
        foreach ($compulsorBreaks as $compulsorBreak) {
            if ($totalHours >= ((int) $compulsorBreak['hour'] + $oldBreak)) {
                $breaks[] = addBreak(
                    $reqStartTime,
                    (int) $compulsorBreak['hour'] / 60,
                    (int) $compulsorBreak['min'],
                    $oldBreak
                );
                $oldBreak = $oldBreak + (int) $compulsorBreak['min'];
            }
        }
    } else {
        if ($remBreak > 0) {
            $newStartTimeForBreak = DateTime::createFromFormat('H:i:s', $endTime)->sub(
                new DateInterval("PT0H{$remBreak}M")
            );
            $breaks[] = addBreak($newStartTimeForBreak->format('H:i:s'), 0, $remBreak);
        }
    }

    // Add working hours entries
    $currentStartTime = $reqStartTime;
    foreach ($breaks as $break) {
        $workingHours[] = addWorkingHoursEntry($currentStartTime, $break['start'], $breaks);
        $currentStartTime = $break['end'];
    }
    if ($endTime > $currentStartTime) {
        $workingHours[] = addWorkingHoursEntry($currentStartTime, $endTime, []);
    }

    // Add break entries
    foreach ($breaks as $break) {
        $workingHours[] = $break;
    }

    $workingHours = array_filter($workingHours, function ($val) {
        return !empty($val);
    });

    // Sort the output by start time
    usort($workingHours, function ($a, $b) {
        return strtotime($a['start']) - strtotime($b['start']);
    });

    return $workingHours;
}

function calculateTotalHours($startTime, $endTime)
{
    $startDateTime = DateTime::createFromFormat('H:i:s', $startTime);
    $endDateTime = DateTime::createFromFormat('H:i:s', $endTime);
    $interval = $startDateTime->diff($endDateTime);
    return ($interval->h * 60) + $interval->i;
}

/**
 * @throws Exception
 */
function addBreak($startTime, $hours, $minutes, $addMinutesStartTime = 0)
{
    $breakStart = DateTime::createFromFormat('H:i:s', $startTime)->add(new DateInterval("PT0H{$addMinutesStartTime}M"));
    $breakStart->add(new DateInterval('PT' . $hours . 'H'));
    $breakEnd = clone $breakStart;
    $breakEnd->add(new DateInterval('PT' . $minutes . 'M'));

    return [
        'start' => $breakStart->format('H:i:s'),
        'end'   => $breakEnd->format('H:i:s'),
        'type'  => 'break'
    ];
}

function addWorkingHoursEntry($startTime, $endTime, $breaks)
{
    $startDateTime = DateTime::createFromFormat('H:i:s', $startTime);
    $endDateTime = DateTime::createFromFormat('H:i:s', $endTime);
    if ($startDateTime < $endDateTime) {
        $workingHoursEntry = [
            'start' => $startDateTime->format('H:i:s'),
            'end'   => $endDateTime->format('H:i:s'),
            'type'  => 'working'
        ];

        // Check if end time is within a break period
        foreach ($breaks as $break) {
            if ($endDateTime >= DateTime::createFromFormat(
                    'H:i',
                    $break['start']
                ) && $endDateTime < DateTime::createFromFormat('H:i:s', $break['end'])) {
                $workingHoursEntry['end'] = $break['start'];
                break;
            }
        }
    }
    return $workingHoursEntry ?? [];
}
Leave a Comment