265 lines
8.0 KiB
PHP
265 lines
8.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Service\Contracts;
|
|
|
|
use App\Entity\Contract;
|
|
use App\Entity\Employee;
|
|
use App\Enum\ContractNature;
|
|
use App\Repository\EmployeeContractPeriodRepository;
|
|
use DateTimeImmutable;
|
|
|
|
readonly class EmployeeContractResolver
|
|
{
|
|
public function __construct(
|
|
private EmployeeContractPeriodRepository $periodRepository,
|
|
) {}
|
|
|
|
public function resolveForEmployeeAndDate(Employee $employee, DateTimeImmutable $date): ?Contract
|
|
{
|
|
$period = $this->periodRepository->findOneCoveringDate($employee, $date);
|
|
|
|
return $period?->getContract();
|
|
}
|
|
|
|
/**
|
|
* @return null|array<int, int> workDaysHours (iso day → minutes) for the contract period active on $date
|
|
*/
|
|
public function resolveWorkDaysMinutesForEmployeeAndDate(Employee $employee, DateTimeImmutable $date): ?array
|
|
{
|
|
$period = $this->periodRepository->findOneCoveringDate($employee, $date);
|
|
$raw = $period?->getWorkDaysHours();
|
|
if (null === $raw) {
|
|
return null;
|
|
}
|
|
|
|
return $this->normalizeWorkDaysMinutes($raw);
|
|
}
|
|
|
|
public function resolveIsDriverForEmployeeAndDate(Employee $employee, DateTimeImmutable $date): bool
|
|
{
|
|
$period = $this->periodRepository->findOneCoveringDate($employee, $date);
|
|
|
|
return $period?->getIsDriver() ?? false;
|
|
}
|
|
|
|
/**
|
|
* @param list<Employee> $employees
|
|
* @param list<string> $days
|
|
*
|
|
* @return array<int, array<string, bool>>
|
|
*/
|
|
public function resolveIsDriverForEmployeesAndDays(array $employees, array $days): array
|
|
{
|
|
$resolved = [];
|
|
if ([] === $employees || [] === $days) {
|
|
return $resolved;
|
|
}
|
|
|
|
foreach ($employees as $employee) {
|
|
$employeeId = $employee->getId();
|
|
if (!$employeeId) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($days as $day) {
|
|
$resolved[$employeeId][$day] = false;
|
|
}
|
|
}
|
|
|
|
$from = new DateTimeImmutable(min($days));
|
|
$to = new DateTimeImmutable(max($days));
|
|
$periods = $this->periodRepository->findByEmployeesAndDateRange($employees, $from, $to);
|
|
foreach ($periods as $period) {
|
|
$employeeId = $period->getEmployee()?->getId();
|
|
if (!$employeeId) {
|
|
continue;
|
|
}
|
|
|
|
$start = $period->getStartDate()->format('Y-m-d');
|
|
$end = $period->getEndDate()?->format('Y-m-d') ?? '9999-12-31';
|
|
$isDriver = $period->getIsDriver();
|
|
foreach ($days as $day) {
|
|
if ($day < $start || $day > $end) {
|
|
continue;
|
|
}
|
|
$resolved[$employeeId][$day] = $isDriver;
|
|
}
|
|
}
|
|
|
|
return $resolved;
|
|
}
|
|
|
|
public function resolveNatureForEmployeeAndDate(Employee $employee, DateTimeImmutable $date): ContractNature
|
|
{
|
|
$period = $this->periodRepository->findOneCoveringDate($employee, $date);
|
|
|
|
return $period?->getContractNatureEnum() ?? ContractNature::CDI;
|
|
}
|
|
|
|
/**
|
|
* @param list<Employee> $employees
|
|
* @param list<string> $days
|
|
*
|
|
* @return array<int, array<string, null|array<int, int>>>
|
|
*/
|
|
public function resolveWorkDaysMinutesForEmployeesAndDays(array $employees, array $days): array
|
|
{
|
|
$resolved = [];
|
|
if ([] === $employees || [] === $days) {
|
|
return $resolved;
|
|
}
|
|
|
|
foreach ($employees as $employee) {
|
|
$employeeId = $employee->getId();
|
|
if (!$employeeId) {
|
|
continue;
|
|
}
|
|
foreach ($days as $day) {
|
|
$resolved[$employeeId][$day] = null;
|
|
}
|
|
}
|
|
|
|
$from = new DateTimeImmutable(min($days));
|
|
$to = new DateTimeImmutable(max($days));
|
|
$periods = $this->periodRepository->findByEmployeesAndDateRange($employees, $from, $to);
|
|
foreach ($periods as $period) {
|
|
$employeeId = $period->getEmployee()?->getId();
|
|
if (!$employeeId) {
|
|
continue;
|
|
}
|
|
|
|
$raw = $period->getWorkDaysHours();
|
|
if (null === $raw) {
|
|
continue;
|
|
}
|
|
|
|
$normalized = $this->normalizeWorkDaysMinutes($raw);
|
|
$start = $period->getStartDate()->format('Y-m-d');
|
|
$end = $period->getEndDate()?->format('Y-m-d') ?? '9999-12-31';
|
|
foreach ($days as $day) {
|
|
if ($day < $start || $day > $end) {
|
|
continue;
|
|
}
|
|
$resolved[$employeeId][$day] = $normalized;
|
|
}
|
|
}
|
|
|
|
return $resolved;
|
|
}
|
|
|
|
/**
|
|
* @param list<Employee> $employees
|
|
* @param list<string> $days
|
|
*
|
|
* @return array<int, array<string, ?Contract>>
|
|
*/
|
|
public function resolveForEmployeesAndDays(array $employees, array $days): array
|
|
{
|
|
$resolved = [];
|
|
if ([] === $employees || [] === $days) {
|
|
return $resolved;
|
|
}
|
|
|
|
foreach ($employees as $employee) {
|
|
$employeeId = $employee->getId();
|
|
if (!$employeeId) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($days as $day) {
|
|
$resolved[$employeeId][$day] = null;
|
|
}
|
|
}
|
|
|
|
$from = new DateTimeImmutable(min($days));
|
|
$to = new DateTimeImmutable(max($days));
|
|
$periods = $this->periodRepository->findByEmployeesAndDateRange($employees, $from, $to);
|
|
foreach ($periods as $period) {
|
|
$employeeId = $period->getEmployee()?->getId();
|
|
$contract = $period->getContract();
|
|
if (!$employeeId || null === $contract) {
|
|
continue;
|
|
}
|
|
|
|
$start = $period->getStartDate()->format('Y-m-d');
|
|
$end = $period->getEndDate()?->format('Y-m-d') ?? '9999-12-31';
|
|
foreach ($days as $day) {
|
|
if ($day < $start || $day > $end) {
|
|
continue;
|
|
}
|
|
$resolved[$employeeId][$day] = $contract;
|
|
}
|
|
}
|
|
|
|
return $resolved;
|
|
}
|
|
|
|
/**
|
|
* @param list<Employee> $employees
|
|
* @param list<string> $days
|
|
*
|
|
* @return array<int, array<string, ContractNature>>
|
|
*/
|
|
public function resolveNaturesForEmployeesAndDays(array $employees, array $days): array
|
|
{
|
|
$resolved = [];
|
|
if ([] === $employees || [] === $days) {
|
|
return $resolved;
|
|
}
|
|
|
|
foreach ($employees as $employee) {
|
|
$employeeId = $employee->getId();
|
|
if (!$employeeId) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($days as $day) {
|
|
$resolved[$employeeId][$day] = ContractNature::CDI;
|
|
}
|
|
}
|
|
|
|
$from = new DateTimeImmutable(min($days));
|
|
$to = new DateTimeImmutable(max($days));
|
|
$periods = $this->periodRepository->findByEmployeesAndDateRange($employees, $from, $to);
|
|
foreach ($periods as $period) {
|
|
$employeeId = $period->getEmployee()?->getId();
|
|
if (!$employeeId) {
|
|
continue;
|
|
}
|
|
|
|
$start = $period->getStartDate()->format('Y-m-d');
|
|
$end = $period->getEndDate()?->format('Y-m-d') ?? '9999-12-31';
|
|
$nature = $period->getContractNatureEnum();
|
|
foreach ($days as $day) {
|
|
if ($day < $start || $day > $end) {
|
|
continue;
|
|
}
|
|
$resolved[$employeeId][$day] = $nature;
|
|
}
|
|
}
|
|
|
|
return $resolved;
|
|
}
|
|
|
|
/**
|
|
* @param array<int|string, mixed> $raw
|
|
*
|
|
* @return array<int, int>
|
|
*/
|
|
private function normalizeWorkDaysMinutes(array $raw): array
|
|
{
|
|
$result = [];
|
|
foreach ($raw as $key => $value) {
|
|
$iso = (int) $key;
|
|
if ($iso < 1 || $iso > 5) {
|
|
continue;
|
|
}
|
|
$result[$iso] = (int) $value;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
}
|