src/Entity/CRM/LeaveRequest.php line 15

  1. <?php
  2. namespace App\Entity\CRM;
  3. use App\Repository\LeaveRequestRepository;
  4. use DateTime;
  5. use Doctrine\Common\Collections\ArrayCollection;
  6. use Doctrine\Common\Collections\Collection;
  7. use Doctrine\DBAL\Types\Types;
  8. use Doctrine\ORM\Mapping as ORM;
  9. use Symfony\Component\Validator\Context\ExecutionContextInterface;
  10. use Symfony\Component\Validator\Constraints as Assert;
  11. #[ORM\Entity(repositoryClassLeaveRequestRepository::class)]
  12. class LeaveRequest
  13. {
  14.     #[ORM\Id]
  15.     #[ORM\GeneratedValue]
  16.     #[ORM\Column]
  17.     private ?int $id null;
  18.     #[ORM\ManyToOne(inversedBy'leaveRequests')]
  19.     #[ORM\JoinColumn(nullabletrue)]
  20.     private ?Consultant $consultant null;
  21.     #[ORM\Column(typeTypes::DATETIME_MUTABLE)]
  22.     private ?\DateTimeInterface $startTime null;
  23.     #[ORM\Column(typeTypes::DATETIME_MUTABLE)]
  24.     private ?\DateTimeInterface $endTime null;
  25.     #[ORM\Column]
  26.     private ?bool $accepted null;
  27.     #[ORM\ManyToOne(inversedBy'acceptedLeaveRequests')]
  28.     private ?Admin $acceptedBy null;
  29.     #[ORM\Column]
  30.     private ?bool $rejected null;
  31.     #[ORM\ManyToOne(inversedBy'rejectedLeaveRequests')]
  32.     private ?Admin $rejectedBy null;
  33.     #[ORM\ManyToOne(inversedBy'LeaveRequest')]
  34.     private ?LeaveRequestType $leaveRequestType null;
  35.     #[ORM\Column]
  36.     private ?bool $acceptedByHr false;
  37.     #[ORM\ManyToOne]
  38.     private ?Admin $acceptedByHrBy null;
  39.     #[ORM\Column(typeTypes::DATETIME_MUTABLEnullabletrue)]
  40.     private ?\DateTimeInterface $addedDate null;
  41.     #[ORM\Column]
  42.     private ?int $leaveCategory 1;
  43.     #[ORM\ManyToOne(inversedBy'leaveRequests')]
  44.     private ?Admin $admin null;
  45.     #[ORM\OneToMany(mappedBy'leaveRequest'targetEntityLeaveRequestAllocation::class, cascade: ['persist''remove'])]
  46.     private Collection $leaveRequestAllocations;
  47.     #[ORM\Column(length255nullabletrue)]
  48.     private ?string $workTimeSettlement null;
  49.     public function __construct()
  50.     {
  51.         $this->consultant null;
  52.         $this->admin null;
  53.         $this->accepted false;
  54.         $this->rejected false;
  55.         $this->acceptedByHr false;
  56.         $this->addedDate = new DateTime();
  57.         $this->leaveRequestAllocations = new ArrayCollection();
  58.         $this->workTimeSettlement NULL;
  59.     }
  60.     public function getId(): ?int
  61.     {
  62.         return $this->id;
  63.     }
  64.     public function getConsultant(): ?Consultant
  65.     {
  66.         return $this->consultant;
  67.     }
  68.     public function setConsultant(?Consultant $consultant): static
  69.     {
  70.         $this->consultant $consultant;
  71.         return $this;
  72.     }
  73.     public function getStartTime(): ?\DateTimeInterface
  74.     {
  75.         return $this->startTime;
  76.     }
  77.     public function setStartTime(\DateTimeInterface $startTime): static
  78.     {
  79.         $this->startTime $startTime;
  80.         return $this;
  81.     }
  82.     public function getEndTime(): ?\DateTimeInterface
  83.     {
  84.         return $this->endTime;
  85.     }
  86.     public function setEndTime(\DateTimeInterface $endTime): static
  87.     {
  88.         $this->endTime $endTime;
  89.         return $this;
  90.     }
  91.     public function isAccepted(): ?bool
  92.     {
  93.         return $this->accepted;
  94.     }
  95.     public function setAccepted(bool $accepted): static
  96.     {
  97.         $this->accepted $accepted;
  98.         return $this;
  99.     }
  100.     public function getAcceptedBy(): ?Admin
  101.     {
  102.         return $this->acceptedBy;
  103.     }
  104.     public function setAcceptedBy(?Admin $acceptedBy): static
  105.     {
  106.         $this->acceptedBy $acceptedBy;
  107.         return $this;
  108.     }
  109.     public function isRejected(): ?bool
  110.     {
  111.         return $this->rejected;
  112.     }
  113.     public function setRejected(bool $rejected): static
  114.     {
  115.         $this->rejected $rejected;
  116.         return $this;
  117.     }
  118.     public function getRejectedBy(): ?Admin
  119.     {
  120.         return $this->rejectedBy;
  121.     }
  122.     public function setRejectedBy(?Admin $rejectedBy): static
  123.     {
  124.         $this->rejectedBy $rejectedBy;
  125.         return $this;
  126.     }
  127.     public function getLeaveRequestType(): ?LeaveRequestType
  128.     {
  129.         return $this->leaveRequestType;
  130.     }
  131.     public function setLeaveRequestType(?LeaveRequestType $leaveRequestType): static
  132.     {
  133.         $this->leaveRequestType $leaveRequestType;
  134.         return $this;
  135.     }
  136.     public function getDuration(): string
  137.     {
  138.         //method doesn't count public holidays, suitable for daily(leaveCategory == 2) leave requests
  139.         if (!$this->getStartTime() || !$this->getEndTime()) {
  140.             return 'N/A';
  141.         }
  142.         $category $this->getLeaveCategory();
  143.         // Kategoria 1: Dzienne — zwracaj liczbę dni roboczych (bez weekendów), bez jednostki
  144.         if ($category === 1) {
  145.             $startTime = clone $this->getStartTime();
  146.             $endTime = clone $this->getEndTime();
  147.             // Ustaw tylko datę, aby liczyć pełne dni
  148.             $currentDay = (clone $startTime)->setTime(000);
  149.             $lastDay = (clone $endTime)->setTime(000);
  150.             // Jeśli zakres jest odwrócony
  151.             if ($lastDay $currentDay) {
  152.                 return '0';
  153.             }
  154.             $workingDays 0;
  155.             while ($currentDay <= $lastDay) {
  156.                 $dayOfWeek = (int)$currentDay->format('N'); // 1=pon, ..., 7=niedz
  157.                 if ($dayOfWeek !== && $dayOfWeek !== 7) {
  158.                     $workingDays++;
  159.                 }
  160.                 $currentDay = (clone $currentDay)->modify('+1 day');
  161.             }
  162.             return (string)$workingDays.' dni';
  163.         }
  164.         // Kategoria 2: Godzinowe — zwracaj różnicę czasu jako "Xh Ym"
  165.         if ($category === 2) {
  166.             $start $this->getStartTime();
  167.             $end $this->getEndTime();
  168.             if ($end $start) {
  169.                 return '0 godz.';
  170.             }
  171.             $diffSeconds $end->getTimestamp() - $start->getTimestamp();
  172.             $totalMinutes = (int)floor($diffSeconds 60);
  173.             $hours intdiv($totalMinutes60);
  174.             $minutes $totalMinutes 60;
  175.             if ($hours && $minutes 0) {
  176.                 return sprintf('%d godz. %dm'$hours$minutes);
  177.             }
  178.             if ($hours 0) {
  179.                 return sprintf('%d godz.'$hours);
  180.             }
  181.             return sprintf('%d godz.'$minutes);
  182.         }
  183.         // Fallback: licz dni robocze jak w kategorii dziennej
  184.         $startTime = clone $this->getStartTime();
  185.         $endTime = clone $this->getEndTime();
  186.         $currentDay = (clone $startTime)->setTime(000);
  187.         $lastDay = (clone $endTime)->setTime(000);
  188.         if ($lastDay $currentDay) {
  189.             return '0';
  190.         }
  191.         $workingDays 0;
  192.         while ($currentDay <= $lastDay) {
  193.             $dayOfWeek = (int)$currentDay->format('N');
  194.             if ($dayOfWeek !== && $dayOfWeek !== 7) {
  195.                 $workingDays++;
  196.             }
  197.             $currentDay = (clone $currentDay)->modify('+1 day');
  198.         }
  199.         return (string)$workingDays.' dni';
  200.     }
  201.     public function getAcceptedOrRejected():string{
  202.         if($this->isRejected()){
  203.             return 'Odrzucone';
  204.         }
  205.         if($this->isAccepted()){
  206.             return 'Zaakceptowany';
  207.         }
  208.         return 'w trakcie';
  209.     }
  210.     public function isAcceptedByHr(): ?bool
  211.     {
  212.         return $this->acceptedByHr;
  213.     }
  214.     public function getAcceptedByHr(): bool
  215.     {
  216.         return $this->acceptedByHr;
  217.     }
  218.     public function setAcceptedByHr(bool $acceptedByHr): static
  219.     {
  220.         $this->acceptedByHr $acceptedByHr;
  221.         return $this;
  222.     }
  223.     public function getAcceptedByHrBy(): ?Admin
  224.     {
  225.         return $this->acceptedByHrBy;
  226.     }
  227.     public function setAcceptedByHrBy(?Admin $acceptedByHrBy): static
  228.     {
  229.         $this->acceptedByHrBy $acceptedByHrBy;
  230.         return $this;
  231.     }
  232.     public function getAddedDate(): ?\DateTimeInterface
  233.     {
  234.         return $this->addedDate;
  235.     }
  236.     public function setAddedDate(?\DateTimeInterface $addedDate): static
  237.     {
  238.         $this->addedDate $addedDate;
  239.         return $this;
  240.     }
  241.     public function getLeaveCategory(): ?int
  242.     {
  243.         return $this->leaveCategory;
  244.     }
  245.     public function setLeaveCategory(int $leaveCategory): static
  246.     {
  247.         $this->leaveCategory $leaveCategory;
  248.         return $this;
  249.     }
  250.     public function getAdmin(): ?Admin
  251.     {
  252.         return $this->admin;
  253.     }
  254.     public function setAdmin(?Admin $admin): static
  255.     {
  256.         $this->admin $admin;
  257.         return $this;
  258.     }
  259.     /**
  260.      * @return Collection<int, LeaveRequestAllocation>
  261.      */
  262.     public function getLeaveRequestAllocations(): Collection
  263.     {
  264.         return $this->leaveRequestAllocations;
  265.     }
  266.     public function getLeaveRequestPlannedMinutes(): int
  267.     {
  268.         return (int) (($this->endTime->getTimestamp() - $this->startTime->getTimestamp()) / 60);
  269.     }
  270.     public function getLeaveRequestUsedMinutes()
  271.     {
  272.         $sum 0;
  273.         foreach ($this->leaveRequestAllocations as $allocation) {
  274.             $sum += $allocation->getMinutesUsed();
  275.         }
  276.         return $sum;
  277.     }
  278.     public function getLeaveRequestRemainingMinutes(): int
  279.     {
  280.         return $this->getLeaveRequestPlannedMinutes() - $this->getLeaveRequestUsedMinutes();
  281.     }
  282.     public function addLeaveRequestAllocation(LeaveRequestAllocation $leaveRequestAllocation): static
  283.     {
  284.         if (!$this->leaveRequestAllocations->contains($leaveRequestAllocation)) {
  285.             $this->leaveRequestAllocations->add($leaveRequestAllocation);
  286.             $leaveRequestAllocation->setLeaveRequest($this);
  287.         }
  288.         return $this;
  289.     }
  290.     public function removeLeaveRequestAllocation(LeaveRequestAllocation $leaveRequestAllocation): static
  291.     {
  292.         if ($this->leaveRequestAllocations->removeElement($leaveRequestAllocation)) {
  293.             // set the owning side to null (unless already changed)
  294.             if ($leaveRequestAllocation->getLeaveRequest() === $this) {
  295.                 $leaveRequestAllocation->setLeaveRequest(null);
  296.             }
  297.         }
  298.         return $this;
  299.     }
  300.     public function getWorkTimeSettlement(): ?string
  301.     {
  302.         return $this->workTimeSettlement;
  303.     }
  304.     public function setWorkTimeSettlement(?string $workTimeSettlement): static
  305.     {
  306.         $this->workTimeSettlement $workTimeSettlement;
  307.         return $this;
  308.     }
  309.     #[Assert\Callback]
  310.     public function validateMinDailyDuration(ExecutionContextInterface $context): void
  311.     {
  312.         $start $this->getStartTime();
  313.         $end   $this->getEndTime();
  314.         if (!$start || !$end) {
  315.             return;
  316.         }
  317.         $user $this->getAdmin() ?? $this->getConsultant();
  318.         $nominalHours $user?->getNominalWorkTime()?->getEmploymentFactor() ?? 8;
  319.         if (($end->getTimestamp() - $start->getTimestamp()) < ($nominalHours 3600)) {
  320.             $context->buildViolation('Wniosek urlopowy musi obejmować co najmniej {{ h }} godzin, aby pokryć nominalny czas pracy.')
  321.                 ->setParameter('{{ h }}', (string)$nominalHours)
  322.                 ->atPath('endTime')
  323.                 ->addViolation();
  324.         }
  325.     }
  326. }