src/Entity/CalendarEvent.php line 16

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Enum\CalendarEvent\Status;
  4. use App\Enum\CalendarEvent\Type;
  5. use App\Library\Utils\DateUtils;
  6. use App\Repository\CalendarEventRepository;
  7. use Doctrine\Common\Collections\ArrayCollection;
  8. use Doctrine\Common\Collections\Collection;
  9. use Doctrine\ORM\Mapping as ORM;
  10. /**
  11.  * @ORM\Entity(repositoryClass=CalendarEventRepository::class)
  12.  */
  13. class CalendarEvent
  14. {
  15.     /**
  16.      * @ORM\Id
  17.      * @ORM\GeneratedValue
  18.      * @ORM\Column(type="integer")
  19.      */
  20.     private $id;
  21.     /**
  22.      * @ORM\Column(type="string", length=255, nullable=true)
  23.      */
  24.     private $name;
  25.     /**
  26.      * @ORM\Column(type="date")
  27.      */
  28.     private $startDate;
  29.     /**
  30.      * @ORM\Column(type="date")
  31.      */
  32.     private $endDate;
  33.     /**
  34.      * @ORM\Column(type="integer", nullable=true)
  35.      */
  36.     private $price;
  37.     /**
  38.      * @ORM\Column(type="smallint", nullable=true)
  39.      */
  40.     private $fromLevel;
  41.     /**
  42.      * @ORM\Column(type="smallint", nullable=true)
  43.      */
  44.     private $earnLevel;
  45.     /**
  46.      * @ORM\Column(type="time")
  47.      */
  48.     private $startTime;
  49.     /**
  50.      * @ORM\Column(type="time")
  51.      */
  52.     private $endTime;
  53.     /**
  54.      * @ORM\Column(type="enum", options={"values"="calendar_event_enum"})
  55.      */
  56.     private $type Type::TYPE_COURSE;
  57.     /**
  58.      * @ORM\Column(type="boolean", nullable=true)
  59.      */
  60.     private $isCandidateReviewRequired true;
  61.     /**
  62.     * @ORM\ManyToOne(targetEntity=PaymentRequisites::class)
  63.     * @ORM\JoinColumn(nullable=true)
  64.      */
  65.     private $paymentRequisites;
  66.     /**
  67.      * @ORM\Column(type="string", length=255, nullable=true)
  68.      */
  69.     private $telegramChannelUrl;
  70.     /**
  71.      * @ORM\Column(type="string", length=100, nullable=true)
  72.      */
  73.     private $telegramChannelId;
  74.     /**
  75.      * @ORM\ManyToMany(targetEntity=CalendarEvent::class)
  76.      */
  77.     private $requireCalendarEventsParticipations;
  78.     /**
  79.      * @ORM\Column(type="boolean", nullable=true)
  80.      */
  81.     private $eventDatesApproximate;
  82.     /**
  83.      * @ORM\Column(type="enum", options={"values"="calendar_event_enum", "default"="active"}))
  84.      */
  85.     private $status Status::STATUS_ACTIVE;
  86.     /**
  87.      * @ORM\ManyToMany(targetEntity=CalendarEvent::class)
  88.      * @ORM\JoinTable(name="calendar_event_deny_participations",
  89.      *       joinColumns={@ORM\JoinColumn(name="calendar_event_id", referencedColumnName="id")},
  90.      *       inverseJoinColumns={@ORM\JoinColumn(name="deny_calendar_event_id", referencedColumnName="id")}
  91.      *  )
  92.      */
  93.     private $denyCalendarEventsParticipations;
  94.     /**
  95.      * @ORM\Column(type="smallint", nullable=true)
  96.      */
  97.     private $toLevel;
  98.     /**
  99.      * @ORM\Column(nullable=true)
  100.      */
  101.     private $requireStudentStatus;
  102.     /**
  103.      * @ORM\ManyToOne(targetEntity=CalendarEvent::class, inversedBy="connectedCalendarEvents")
  104.      * @ORM\JoinColumn(nullable=true)
  105.      */
  106.     private $connectingCalendarEvent;
  107.     /**
  108.      * @ORM\OneToMany(targetEntity=CalendarEvent::class, mappedBy="connectingCalendarEvent")
  109.      */
  110.     private $connectedCalendarEvents;
  111.     /**
  112.      * @ORM\ManyToMany(targetEntity=TelegramCampaignMessage::class)
  113.      */
  114.     private $approvedCandidatesCampaignMessages;
  115.     /**
  116.      * @ORM\ManyToOne(targetEntity=CalendarEventKind::class)
  117.      */
  118.     private $kind;
  119.     /**
  120.      * @ORM\Column(type="boolean", nullable=true)
  121.      */
  122.     private $connectingEventForAccountant;
  123.     /**
  124.      * @var bool|null
  125.      */
  126.     private $isEndDateSame;
  127.     /**
  128.      * @ORM\Column(type="boolean", nullable=true)
  129.      */
  130.     private $isTelegramChannelConfigurated;
  131.     /**
  132.      * @ORM\Column(type="datetime", nullable=true)
  133.      */
  134.     private $createdAt;
  135.     /**
  136.      * @ORM\Column(type="datetime", nullable=true)
  137.      */
  138.     private $updatedAt;
  139.     public function __construct()
  140.     {
  141.         $this->createdAt = new \DateTime();
  142.         $this->updatedAt = new \DateTime();
  143.         $this->startDate = new \DateTime();
  144.         $this->endDate = new \DateTime();
  145.         $this->startTime = new \DateTime('10:00:00');
  146.         $this->endTime = new \DateTime('13:00:00');
  147.         $this->requireCalendarEventsParticipations = new ArrayCollection();
  148.         $this->approvedCandidatesCampaignMessages = new ArrayCollection();
  149.         $this->denyCalendarEventsParticipations = new ArrayCollection();
  150.         $this->connectedCalendarEvents = new ArrayCollection();
  151.     }
  152.     public function __toString()
  153.     {
  154.         return $this->getNameText();
  155.     }
  156.     public function getShortInfo(): string
  157.     {
  158.         return $this->getName() . " " . ($this->getStartDate() ? $this->getStartDate()->format('d.m.Y') : "") .
  159.             ($this->getFromLevel() ? " (с " $this->getFromLevel() . " ур.)" " (все ур.)");
  160.     }
  161.     public function getText(array $options null)
  162.     {
  163.         $options array_merge([
  164.             "quotes" => false,
  165.         ], $options ?? []);
  166.         $result = ($options['quotes'] ? $this->getNameText() : $this->getName());
  167.         return $result;
  168.     }
  169.     public function getNameText(): string
  170.     {
  171.         return $this->getTypeText() . " «" $this->getName() . "»";
  172.     }
  173.     public function getOnTypeText(): string
  174.     {
  175.         $typeText null;
  176.         switch ($this->getType()) {
  177.             case Type::TYPE_COURSE:
  178.                 $typeText "курс";
  179.                 break;
  180.             case Type::TYPE_OPEN_MEETING:
  181.                 $typeText "открытую встречу";
  182.                 break;
  183.             case Type::TYPE_MEETING:
  184.                 $typeText "конференцию";
  185.                 break;
  186.             case Type::TYPE_PERSONAL_CONSULTATION:
  187.                 $typeText "личную консультациию";
  188.                 break;
  189.             default:
  190.                 $typeText $this->getTypeText();
  191.                 break;
  192.         }
  193.         return $typeText;
  194.     }
  195.     public function getOfTypeText(): string
  196.     {
  197.         $typeText null;
  198.         switch ($this->getType()) {
  199.             case Type::TYPE_COURSE:
  200.                 $typeText "курса";
  201.                 break;
  202.                 case Type::TYPE_OPEN_MEETING:
  203.                 $typeText "открытой встречи";
  204.                 break;
  205.             case Type::TYPE_MEETING:
  206.                 $typeText "конференции";
  207.                 break;
  208.             case Type::TYPE_PERSONAL_CONSULTATION:
  209.                 $typeText "личной консультации";
  210.                 break;
  211.             default:
  212.                 $typeText $this->getTypeText();
  213.                 break;
  214.         }
  215.         return $typeText;
  216.     }
  217.     public function getOnNameText(): string
  218.     {
  219.         $typeText $this->getOnTypeText();
  220.         return $typeText " «" $this->getName() . "»";
  221.     }
  222.     public function getOfNameText(): string
  223.     {
  224.         $typeText $this->getOfTypeText();
  225.         return $typeText " «" $this->getName() . "»";
  226.     }
  227.     public function getId(): ?int
  228.     {
  229.         return $this->id;
  230.     }
  231.     public function getName(): ?string
  232.     {
  233.         return $this->name;
  234.     }
  235.     public function setName(?string $name): self
  236.     {
  237.         $this->name $name;
  238.         return $this;
  239.     }
  240.     public function getStartDate(): ?\DateTimeInterface
  241.     {
  242.         return $this->startDate;
  243.     }
  244.     public function setStartDate(\DateTimeInterface $startDate): self
  245.     {
  246.         $this->startDate $startDate;
  247.         return $this;
  248.     }
  249.     public function getEndDate(): ?\DateTimeInterface
  250.     {
  251.         return $this->endDate;
  252.     }
  253.     public function setEndDate(\DateTimeInterface $endDate): self
  254.     {
  255.         $this->endDate $endDate;
  256.         return $this;
  257.     }
  258.     private function _getPrice($isFirstCall false): ?int
  259.     {
  260.         if ($isFirstCall) {
  261.             if (!$this->_getPrice() && $this->getConnectedCalendarEvents()->count()) {
  262.                 $isAllPricesEqual true;
  263.                 $price null;
  264.                 foreach ($this->getConnectedCalendarEvents() as $connectedEvent) {
  265.                     if ($connectedEvent->_getPrice()) {
  266.                         if ($price === null) {
  267.                             $price $connectedEvent->_getPrice();
  268.                         } elseif ($price != $connectedEvent->_getPrice()) {
  269.                             $isAllPricesEqual false;
  270.                             break;
  271.                         }
  272.                     }
  273.                 }
  274.                 if ($isAllPricesEqual) {
  275.                     return $price;
  276.                 }
  277.             }
  278.         }
  279.         return $this->price;
  280.     }
  281.     public function getPrice(): ?int
  282.     {
  283.       return $this->_getPrice(true);
  284.     }
  285.     public function isPriceNotNull(): bool
  286.     {
  287.         return $this->getPrice() === || $this->getPrice();
  288.     }
  289.     public function setPrice(?int $price): self
  290.     {
  291.         $this->price $price;
  292.         return $this;
  293.     }
  294.     public function getFromLevel(): ?int
  295.     {
  296.         return $this->fromLevel;
  297.     }
  298.     public function getFromLevelEmoji(): string
  299.     {
  300.         $level $this->getFromLevel();
  301.         if ($level === null || $level === 0) {
  302.             return "🔢";
  303.         }
  304.         $emojiNumbers = [
  305.             '0' => '0️⃣',
  306.             '1' => '1️⃣',
  307.             '2' => '2️⃣',
  308.             '3' => '3️⃣',
  309.             '4' => '4️⃣',
  310.             '5' => '5️⃣',
  311.             '6' => '6️⃣',
  312.             '7' => '7️⃣',
  313.             '8' => '8️⃣',
  314.             '9' => '9️⃣',
  315.         ];
  316.         $levelStr = (string)$level;
  317.         return $emojiNumbers[$levelStr[0]] . ($levelStr[1] ?? '');
  318.     }
  319.     public function getFromLevelText(): string
  320.     {
  321.         if ($this->getFromLevel() === null) {
  322.             return "";
  323.         }
  324.         if ($this->getFromLevel() === && $this->getToLevel() === null) {
  325.             return "все ур.";
  326.         }
  327.         return ($this->getFromLevel() === $this->getToLevel() ? "для " "с")
  328. //            . StringUtils::getEnding($this->getFromLevel(),
  329. //                "", "о", "",
  330. //                "")
  331.             " " $this->getFromLevelNumberText()
  332.             . ($this->getToLevel() === null || $this->getFromLevel() === $this->getToLevel() ? "" "–" $this->getToLevelNumberText())
  333.             . " ур.";
  334.     }
  335.     public function getFromLevelNumberText(): ?string
  336.     {
  337.         if ($this->getFromLevel() === 0) {
  338.             return "баз.";
  339.         }
  340.         return $this->getFromLevel();
  341.     }
  342.     public function getToLevelNumberText(): ?string
  343.     {
  344.         if ($this->getToLevel() === 0) {
  345.             return "баз.";
  346.         }
  347.         return $this->getToLevel();
  348.     }
  349.     public function setFromLevel(?int $fromLevel): self
  350.     {
  351.         $this->fromLevel $fromLevel;
  352.         return $this;
  353.     }
  354.     public function getEarnLevel(): ?int
  355.     {
  356.         return $this->earnLevel;
  357.     }
  358.     public function setEarnLevel(?int $level): self
  359.     {
  360.         $this->earnLevel $level;
  361.         return $this;
  362.     }
  363.     public function getStartTime(): ?\DateTimeInterface
  364.     {
  365.         return $this->startTime;
  366.     }
  367.     public function setStartTime(\DateTimeInterface $startTime): self
  368.     {
  369.         $this->startTime $startTime;
  370.         return $this;
  371.     }
  372.     public function getEndTime(): ?\DateTimeInterface
  373.     {
  374.         return $this->endTime;
  375.     }
  376.     public function setEndTime(\DateTimeInterface $endTime): self
  377.     {
  378.         $this->endTime $endTime;
  379.         return $this;
  380.     }
  381.     public function getType()
  382.     {
  383.         return $this->type;
  384.     }
  385.     public function getTypeText(): string
  386.     {
  387.         return Type::getText($this->getType());
  388.     }
  389.     public function setType($type): self
  390.     {
  391.         $this->type $type;
  392.         return $this;
  393.     }
  394.     public function getTopic(): string
  395.     {
  396.         if ($this->type === Type::TYPE_COURSE) {
  397.             return "Курс «" $this->getName() . "»";
  398.         } elseif ($this->type === Type::TYPE_MEETING) {
  399.             return "Конференция «" $this->getName() . "»";
  400.         } elseif ($this->type === Type::TYPE_OPEN_MEETING) {
  401.             return "Открытая встреча «" $this->getName() . "»";
  402.         } else {
  403.             return $this->getTypeText() . " «" $this->getName() . "»";
  404.         }
  405.     }
  406.     public function isIsCandidateReviewRequired(): ?bool
  407.     {
  408.         return $this->isCandidateReviewRequired;
  409.     }
  410.     public function setIsCandidateReviewRequired(?bool $isCandidateReviewRequired): self
  411.     {
  412.         $this->isCandidateReviewRequired $isCandidateReviewRequired;
  413.         return $this;
  414.     }
  415.     public function getPaymentRequisites(): ?PaymentRequisites
  416.     {
  417.         return $this->paymentRequisites;
  418.     }
  419.     public function isForFree(): bool
  420.     {
  421.         return $this->getPrice() === 0;
  422.     }
  423.     public function checkPaymentRequisites(): bool
  424.     {
  425.         return $this->isPriceNotNull() && ($this->isForFree() || $this->getPaymentRequisites());
  426.     }
  427.     public function canCreateTelegramCampaign(): bool
  428.     {
  429.         return $this->isPriceNotNull() && $this->checkPaymentRequisites();
  430.     }
  431.     public function setPaymentRequisites(?PaymentRequisites $paymentRequisites): self
  432.     {
  433.         $this->paymentRequisites $paymentRequisites;
  434.         return $this;
  435.     }
  436.     public function getNameWithCode(): string
  437.     {
  438.         return "Код " $this->getPrice() . " – " $this->getShortInfo();
  439.     }
  440.     public function isFinished(): bool
  441.     {
  442.         if (!$this->getFullEndDate()) {
  443.             return true;
  444.         }
  445.         $now = new \DateTime();
  446.         return $this->getFullEndDate() < $now;
  447.     }
  448.     public function isInProgress(): bool
  449.     {
  450.         return $this->isStarted() && !$this->isFinished();
  451.     }
  452.     public function isUpcoming(): bool
  453.     {
  454.         if (!$this->getFullStartDate()) {
  455.             return false;
  456.         }
  457.         $now = new \DateTime();
  458.         return $this->getFullStartDate() > $now;
  459.     }
  460.     public function getFullStartDate(): ?\DateTime
  461.     {
  462.         $startDate $this->getStartDate();
  463.         if (!$startDate) {
  464.             return null;
  465.         }
  466.         $startTime $this->getStartTime();
  467.         if ($startTime) {
  468.             $startDate = (clone $startDate)->setTime($startTime->format('H'), $startTime->format('i'), $startTime->format('s'));
  469.         }
  470.         return $startDate;
  471.     }
  472.     public function getFullEndDate(): ?\DateTime
  473.     {
  474.         $endDate $this->getEndDate();
  475.         if (!$endDate) {
  476.             return null;
  477.         }
  478.         $endTime $this->getEndTime();
  479.         if ($endTime) {
  480.             $endDate = (clone $endDate)->setTime($endTime->format('H'), $endTime->format('i'), $endTime->format('s'));
  481.         }
  482.         return $endDate;
  483.     }
  484.     public function isStarted(int $addDaysToStartDate null): bool
  485.     {
  486.         if (!$this->getStartDate() || $this->isFinished()) {
  487.             return false;
  488.         }
  489.         $now = (new \DateTime())->setTime(000);
  490.         $startDate = (clone $this->getStartDate())->setTime(000);
  491.         if ($addDaysToStartDate) {
  492.             $startDate $startDate->modify("+$addDaysToStartDate days");
  493.         }
  494.         return $startDate <= $now;
  495.     }
  496.     public function isRegistrationOpen(): bool
  497.     {
  498.         return !$this->isStarted(-2);
  499.     }
  500.     public function getLastRegistrationDate(): ?\DateTime
  501.     {
  502.         if (!$this->getStartDate()) {
  503.             return null;
  504.         }
  505.         $lastRegistrationDate = (clone $this->getStartDate())->modify("-3 days");
  506.         $weekendDays 0;
  507.         if (in_array((int)$lastRegistrationDate->format('N'), [67])) {
  508.             $weekendDays = (int)$lastRegistrationDate->format('N') - 5;
  509.         }
  510.         if ($weekendDays 0) {
  511.             $lastRegistrationDate $lastRegistrationDate->modify("-$weekendDays days");
  512.         }
  513.         return $lastRegistrationDate;
  514.     }
  515.     public function getHoursLeftBeforeStart(): int
  516.     {
  517.         return (int)ceil((($this->getStartDate()->getTimestamp() - (new \DateTime())->getTimestamp()) / 3600));
  518.     }
  519.     public function getTelegramChannelUrl(): ?string
  520.     {
  521.         return $this->telegramChannelUrl;
  522.     }
  523.     public function setTelegramChannelUrl(?string $telegramChannelUrl): self
  524.     {
  525.         $this->telegramChannelUrl $telegramChannelUrl;
  526.         if (!$telegramChannelUrl) {
  527.             $this->setIsTelegramChannelConfigurated(false);
  528.         }
  529.         return $this;
  530.     }
  531.     public function getTelegramChannelId(): ?string
  532.     {
  533.         return $this->telegramChannelId;
  534.     }
  535.     public function setTelegramChannelId(?string $telegramChannelId): self
  536.     {
  537.         $this->telegramChannelId $telegramChannelId;
  538.         if (!$telegramChannelId) {
  539.             $this->setIsTelegramChannelConfigurated(false);
  540.         }
  541.         return $this;
  542.     }
  543.     /**
  544.      * @return Collection<int, self>
  545.      */
  546.     public function getRequireCalendarEventsParticipations(): Collection
  547.     {
  548.         return $this->requireCalendarEventsParticipations;
  549.     }
  550.     public function getRequireCalendarEventsParticipationsText(): string
  551.     {
  552.         $texts = [];
  553.         foreach ($this->getRequireCalendarEventsParticipations() as $event) {
  554.             $texts[] = mb_lcfirst($event->getNameText(), 'UTF-8');
  555.         }
  556.         return implode(", "$texts);
  557.     }
  558.     public function getDenyCalendarEventsParticipationsText(): string
  559.     {
  560.         $texts = [];
  561.         foreach ($this->getDenyCalendarEventsParticipations() as $event) {
  562.             $texts[] = mb_lcfirst($event->getNameText(), 'UTF-8');
  563.         }
  564.         return implode(", "$texts);
  565.     }
  566.     public function addRequireCalendarEventsParticipation(self $requireCalendarEventsParticipation): self
  567.     {
  568.         if (!$this->requireCalendarEventsParticipations->contains($requireCalendarEventsParticipation)) {
  569.             $this->requireCalendarEventsParticipations[] = $requireCalendarEventsParticipation;
  570.         }
  571.         return $this;
  572.     }
  573.     public function removeRequireCalendarEventsParticipation(self $requireCalendarEventsParticipation): self
  574.     {
  575.         $this->requireCalendarEventsParticipations->removeElement($requireCalendarEventsParticipation);
  576.         return $this;
  577.     }
  578.     public function isStudentLevelCorrespond(?Person $person): bool
  579.     {
  580.         if (!$person) {
  581.             return false;
  582.         }
  583.         $eventLevel $this->getFromLevel();
  584.         if ($eventLevel === null) {
  585.             return true;
  586.         }
  587.         if (!$person->getStudent() || $person->getStudent()->getLevel() === null) {
  588.             return false;
  589.         }
  590.         return $person->getStudent()->getLevel() >= $eventLevel;
  591.     }
  592.     public function isEventDatesApproximate(): ?bool
  593.     {
  594.         return $this->eventDatesApproximate;
  595.     }
  596.     public function setEventDatesApproximate(?bool $eventDatesApproximate): self
  597.     {
  598.         $this->eventDatesApproximate $eventDatesApproximate;
  599.         return $this;
  600.     }
  601. //    /**
  602. //     * @return Collection<int, TelegramCampaignMessage>
  603. //     */
  604. //    public function getApprovedCandidatesCampaignMessages(): Collection
  605. //    {
  606. //        return $this->approvedCandidatesCampaignMessages;
  607. //    }
  608. //
  609. //    public function addApprovedCandidatesCampaignMessage(TelegramCampaignMessage $approvedCandidatesCampaignMessage): self
  610. //    {
  611. //        if (!$this->approvedCandidatesCampaignMessages->contains($approvedCandidatesCampaignMessage)) {
  612. //            $this->approvedCandidatesCampaignMessages[] = $approvedCandidatesCampaignMessage;
  613. //        }
  614. //
  615. //        return $this;
  616. //    }
  617. //
  618. //    public function removeApprovedCandidatesCampaignMessage(TelegramCampaignMessage $approvedCandidatesCampaignMessage): self
  619. //    {
  620. //        $this->approvedCandidatesCampaignMessages->removeElement($approvedCandidatesCampaignMessage);
  621. //
  622. //        return $this;
  623. //    }
  624.     public function getStatus()
  625.     {
  626.         return $this->status;
  627.     }
  628.     public function setStatus($status): self
  629.     {
  630.         $this->status $status;
  631.         return $this;
  632.     }
  633.     public function getStatusText(): ?string
  634.     {
  635.         return Status::getText($this->getStatus());
  636.     }
  637.     public function getStatusCssClass($prefix null): ?string
  638.     {
  639.         return Status::getCssClass($this->getStatus(), $prefix);
  640.     }
  641.     /**
  642.      * @return Collection<int, self>
  643.      */
  644.     public function getDenyCalendarEventsParticipations(): Collection
  645.     {
  646.         return $this->denyCalendarEventsParticipations;
  647.     }
  648.     public function addDenyCalendarEventsParticipation(self $denyCalendarEventsParticipation): self
  649.     {
  650.         if (!$this->denyCalendarEventsParticipations->contains($denyCalendarEventsParticipation)) {
  651.             $this->denyCalendarEventsParticipations[] = $denyCalendarEventsParticipation;
  652.         }
  653.         return $this;
  654.     }
  655.     public function removeDenyCalendarEventsParticipation(self $denyCalendarEventsParticipation): self
  656.     {
  657.         $this->denyCalendarEventsParticipations->removeElement($denyCalendarEventsParticipation);
  658.         return $this;
  659.     }
  660.     public function getToLevel(): ?int
  661.     {
  662.         return $this->toLevel;
  663.     }
  664.     public function setToLevel(?int $toLevel): self
  665.     {
  666.         $this->toLevel $toLevel;
  667.         return $this;
  668.     }
  669.     public function getRequireStudentStatus()
  670.     {
  671.         return $this->requireStudentStatus;
  672.     }
  673.     public function getRequireStudentStatusText(): string
  674.     {
  675.         return \App\Enum\Student\Status::getText($this->getRequireStudentStatus());
  676.     }
  677.     public function setRequireStudentStatus($requireStudentStatus): self
  678.     {
  679.         $this->requireStudentStatus $requireStudentStatus;
  680.         return $this;
  681.     }
  682.     public function getConnectingCalendarEvent(): ?self
  683.     {
  684.         return $this->connectingCalendarEvent;
  685.     }
  686.     public function setConnectingCalendarEvent(?self $connectingCalendarEvent): self
  687.     {
  688.         $this->connectingCalendarEvent $connectingCalendarEvent;
  689.         return $this;
  690.     }
  691.     /**
  692.      * @return Collection<int, self>
  693.      */
  694.     public function getConnectedCalendarEvents(): Collection
  695.     {
  696.         return $this->connectedCalendarEvents;
  697.     }
  698.     public function addConnectedCalendarEvent(self $connectedCalendarEvent): self
  699.     {
  700.         if (!$this->connectedCalendarEvents->contains($connectedCalendarEvent)) {
  701.             $this->connectedCalendarEvents[] = $connectedCalendarEvent;
  702.             $connectedCalendarEvent->setConnectingCalendarEvent($this);
  703.         }
  704.         return $this;
  705.     }
  706.     public function removeConnectedCalendarEvent(self $connectedCalendarEvent): self
  707.     {
  708.         if ($this->connectedCalendarEvents->removeElement($connectedCalendarEvent)) {
  709.             // set the owning side to null (unless already changed)
  710.             if ($connectedCalendarEvent->getConnectingCalendarEvent() === $this) {
  711.                 $connectedCalendarEvent->setConnectingCalendarEvent(null);
  712.             }
  713.         }
  714.         return $this;
  715.     }
  716.     public function getKind(): ?CalendarEventKind
  717.     {
  718.         return $this->kind;
  719.     }
  720.     public function setKind(?CalendarEventKind $kind): self
  721.     {
  722.         $this->kind $kind;
  723.         return $this;
  724.     }
  725.     public function getFinanceCategory(): ?FinanceCategory
  726.     {
  727.         $ceKind $this->getKind();
  728.         return $ceKind $ceKind->getFinanceCategory() : null;
  729.     }
  730.     public function isSameFinanceCategory(FinanceCategory $financeCategory): bool
  731.     {
  732.         $ceFinanceCategory $this->getFinanceCategory();
  733.         if (!$ceFinanceCategory) {
  734.             return false;
  735.         }
  736.         return $ceFinanceCategory->getId() === $financeCategory->getId();
  737.     }
  738.     public function isConnectingType(): bool
  739.     {
  740.         return $this->getType() == Type::TYPE_CONNECTING_EVENT;
  741.     }
  742.     public function isConnectingEventForAccountant(): ?bool
  743.     {
  744.         return $this->connectingEventForAccountant;
  745.     }
  746.     public function setConnectingEventForAccountant(?bool $connectingEventForAccountant): self
  747.     {
  748.         $this->connectingEventForAccountant $connectingEventForAccountant;
  749.         return $this;
  750.     }
  751.     public function getIsEndDateSame(): ?bool
  752.     {
  753.         $result $this->getStartDate()->format("d.m.Y") == $this->getEndDate()->format("d.m.Y");
  754.         return $result;
  755.     }
  756.     public function setIsEndDateSame(?bool $isEndDateSame): self
  757.     {
  758.         $this->isEndDateSame $isEndDateSame;
  759.         return $this;
  760.     }
  761.     public function isIsTelegramChannelConfigurated(): ?bool
  762.     {
  763.         return $this->isTelegramChannelConfigurated;
  764.     }
  765.     public function setIsTelegramChannelConfigurated(?bool $isTelegramChannelConfigurated): self
  766.     {
  767.         $this->isTelegramChannelConfigurated $isTelegramChannelConfigurated;
  768.         return $this;
  769.     }
  770.     public function getDaysUntilStart(): int
  771.     {
  772.         if (!$this->getStartDate()) {
  773.             throw new \Exception("Start date is not set");
  774.         }
  775.         if (new \DateTime() >= $this->getStartDate()) {
  776.             return 0;
  777.         } else {
  778.             return floor(DateUtils::getDateDiff($this->getStartDate(), null"d"));
  779.         }
  780.     }
  781.     public function shouldAskReceipt(): bool
  782.     {
  783.         return $this->getDaysUntilStart() <= 1;
  784.     }
  785.     public function getCreatedAt(): ?\DateTimeInterface
  786.     {
  787.         return $this->createdAt;
  788.     }
  789.     public function setCreatedAt(?\DateTimeInterface $createdAt): self
  790.     {
  791.         $this->createdAt $createdAt;
  792.         return $this;
  793.     }
  794.     public function getUpdatedAt(): ?\DateTime
  795.     {
  796.         return $this->updatedAt;
  797.     }
  798.     public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
  799.     {
  800.         $this->updatedAt $updatedAt;
  801.         return $this;
  802.     }
  803.     public function isUpdatedRecently(): bool
  804.     {
  805.         if (!$this->getUpdatedAt()) {
  806.             return false;
  807.         }
  808.         if (new \DateTime() < (clone $this->getUpdatedAt())->modify("+3 minutes")) {
  809.             return true;
  810.         }
  811.         return false;
  812.     }
  813. }