src/Entity/CourseOccurrence.php line 18

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Entity\VenueRoom;
  4. use App\Entity\OrderItem;
  5. use Doctrine\ORM\Mapping as ORM;
  6. use JMS\Serializer\Annotation as JMS;
  7. use Doctrine\Common\Collections\Collection;
  8. use Menke\UserBundle\Entity\Client;
  9. use Menke\CommonsBundle\Entity\GenericEntity;
  10. use Doctrine\Common\Collections\ArrayCollection;
  11. /**
  12.  * @ORM\Entity(repositoryClass="App\Repository\CourseOccurrenceRepository")
  13.  * @JMS\ExclusionPolicy("all")
  14.  */
  15. class CourseOccurrence extends GenericEntity
  16. {
  17.     /**
  18.      * @ORM\ManyToOne(targetEntity="App\Entity\Venue")
  19.      * @ORM\JoinColumn(name="venueId", referencedColumnName="id")
  20.      * @JMS\Expose
  21.      * @JMS\Groups({"public"})
  22.      */
  23.     protected $venue;
  24.     /**
  25.      * @ORM\ManyToOne(targetEntity="VenueRoom")
  26.      * @ORM\JoinColumn(name="venueRoomId", referencedColumnName="id", nullable=true)
  27.      * @JMS\Expose
  28.      * @JMS\Groups({"public"})
  29.      */
  30.     protected $venueRoom;
  31.     /**
  32.      * @ORM\ManyToOne(targetEntity="Course", inversedBy="occurrences")
  33.      * @ORM\JoinColumn(name="courseId", referencedColumnName="id")
  34.      */
  35.     protected $course;
  36.     /**
  37.      * @ORM\OneToMany(targetEntity="App\Entity\CourseOccurrenceTime", mappedBy="occurrence", orphanRemoval=true, cascade={"all"})
  38.      * @ORM\OrderBy({"start" = "ASC"})
  39.      * @JMS\Expose
  40.      * @JMS\Groups({"public"})
  41.      */
  42.     protected $times;
  43.     /**
  44.      * @ORM\ManyToMany(targetEntity="App\Entity\Person", mappedBy="courses")
  45.      */
  46.     protected $customers;
  47.     /**
  48.      * @ORM\ManyToMany(targetEntity="App\Entity\Speaker")
  49.      * @JMS\Expose
  50.      * @JMS\Groups({"public"})
  51.      */
  52.     protected $speakers;
  53.     /**
  54.      * @ORM\Column(type="boolean")
  55.      */
  56.     protected $published false;
  57.     /**
  58.      * @ORM\Column(type="datetime")
  59.      * @JMS\Expose
  60.      * @JMS\Groups({"public"})
  61.      */
  62.     protected $start;
  63.     /**
  64.      * @ORM\Column(type="datetime")
  65.      * @JMS\Expose
  66.      * @JMS\Groups({"public"})
  67.      */
  68.     protected $end;
  69.     /**
  70.      * @ORM\Column(type="integer")
  71.      * @JMS\Expose
  72.      * @JMS\Groups({"public"})
  73.      */
  74.     protected $slots;
  75.     /**
  76.      * @ORM\Column(type="string", length=255, nullable=true)
  77.      * @JMS\Expose
  78.      * @JMS\Groups({"public"})
  79.      */
  80.     protected $code;
  81.     /**
  82.      * @ORM\Column(type="boolean")
  83.      * @JMS\Expose
  84.      * @JMS\Groups({"public"})
  85.      */
  86.     protected $reservationAllowed false;
  87.     /**
  88.      * @ORM\Column(type="integer")
  89.      */
  90.     protected $bookedSlots 0;
  91.     protected $pendingBookings 0;
  92.     /**
  93.      * @ORM\OneToMany(targetEntity="App\Entity\WaitItem", mappedBy="courseOccurrence")
  94.      */
  95.     protected $waitItems;
  96.     /**
  97.      * @ORM\OneToMany(targetEntity="App\Entity\OrderItem", mappedBy="courseOccurrence")
  98.      */
  99.     protected $orderItems;
  100.     public function __construct()
  101.     {
  102.         $this->times = new ArrayCollection();
  103.         $this->speakers = new ArrayCollection();
  104.         $this->waitItems = new ArrayCollection();
  105.     }
  106.     /**
  107.      * @return Venue|null
  108.      */
  109.     public function getVenue(): ?Venue
  110.     {
  111.         return $this->venue;
  112.     }
  113.     /**
  114.      * @param Venue|null $venue
  115.      * @return CourseOccurrence
  116.      */
  117.     public function setVenue(?Venue $venue): self
  118.     {
  119.         $this->venue $venue;
  120.         return $this;
  121.     }
  122.     /**
  123.      * @return VenueRoom|null
  124.      */
  125.     public function getVenueRoom(): ?VenueRoom
  126.     {
  127.         return $this->venueRoom;
  128.     }
  129.     /**
  130.      * @param VenueRoom|null $venue
  131.      * @return CourseOccurrence
  132.      */
  133.     public function setVenueRoom(?VenueRoom $venueRoom): self
  134.     {
  135.         $this->venueRoom $venueRoom;
  136.         return $this;
  137.     }
  138.     /**
  139.      * @return Course
  140.      */
  141.     public function getCourse(): ?Course
  142.     {
  143.         return $this->course;
  144.     }
  145.     /**
  146.      * @param Course $course
  147.      * @return CourseOccurrence
  148.      */
  149.     public function setCourse(?Course $course)
  150.     {
  151.         $this->course $course;
  152.         return $this;
  153.     }
  154.     /**
  155.      * @return Collection|CourseOccurrenceTime[]
  156.      */
  157.     public function getTimes(): Collection
  158.     {
  159.         return $this->times;
  160.     }
  161.     /**
  162.      * @param mixed $times
  163.      * @return CourseOccurrence
  164.      */
  165.     public function setTimes($times)
  166.     {
  167.         $this->times $times;
  168.         return $this;
  169.     }
  170.     /**
  171.      * @param CourseOccurrenceTime $time
  172.      * @return CourseOccurrence
  173.      */
  174.     public function addTime(CourseOccurrenceTime $time): self
  175.     {
  176.         if (!$this->times->contains($time)) {
  177.             $this->times[] = $time;
  178.             $time->setOccurrence($this);
  179.         }
  180.         return $this;
  181.     }
  182.     /**
  183.      * @param CourseOccurrenceTime $time
  184.      * @return CourseOccurrence
  185.      */
  186.     public function removeTime(CourseOccurrenceTime $time): self
  187.     {
  188.         if ($this->times->contains($time)) {
  189.             $this->times->removeElement($time);
  190.             if ($time->getOccurrence() === $this) {
  191.                 $time->setOccurrence(null);
  192.             }
  193.         }
  194.         return $this;
  195.     }
  196.     /**
  197.      * @return Collection|Speaker[]
  198.      */
  199.     public function getSpeakers(): Collection
  200.     {
  201.         return $this->speakers;
  202.     }
  203.     /**
  204.      * @param Speaker $speaker
  205.      * @return CourseOccurrence
  206.      */
  207.     public function addSpeaker(Speaker $speaker): self
  208.     {
  209.         if (!$this->speakers->contains($speaker)) {
  210.             $this->speakers[] = $speaker;
  211.         }
  212.         return $this;
  213.     }
  214.     /**
  215.      * @param Speaker $speaker
  216.      * @return CourseOccurrence
  217.      */
  218.     public function removeSpeaker(Speaker $speaker): self
  219.     {
  220.         if ($this->speakers->contains($speaker)) {
  221.             $this->speakers->removeElement($speaker);
  222.         }
  223.         return $this;
  224.     }
  225.     /**
  226.      * @return null|string
  227.      */
  228.     public function getTitle(): ?string
  229.     {
  230.         return $this->getCourse()->getTitle();
  231.     }
  232.     /**
  233.      * @return Category|null
  234.      */
  235.     public function getCategory(): ?Category
  236.     {
  237.         return $this->getCourse()->getCategory();
  238.     }
  239.     /**
  240.      * @return float|null
  241.      */
  242.     public function getPrice(): ?float
  243.     {
  244.         return $this->getCourse()->getPrice();
  245.     }
  246.     /**
  247.      * @return null|string
  248.      */
  249.     public function getFullCaption(): ?string
  250.     {
  251.         $categoryName $this->checkIfValueExists('categoryName');
  252.         $venue $this->checkIfValueExists('venue');
  253.         $venueRoom $this->checkIfValueExists('venueRoom');
  254.         if ($venue && $venueRoom) {
  255.             $place $venue ' ' $venueRoom;
  256.         } else {
  257.             $place $venue ?? $venueRoom;
  258.         }
  259.        
  260.         $category = ($categoryName) ? ' Kategorie: ' $categoryName '';
  261.         return $this->getTitle() . ' (' $this->getStart()->format('d.m.Y H:i') . ') ' ."; Ort: "str_replace('<br>'' '$place) ."; "$category;
  262.     }
  263.     private function checkIfValueExists($value)
  264.     {
  265.         try {
  266.             switch ($value) {
  267.                 case 'categoryName':
  268.                     $result =
  269.                         $this->getCourse()->getCategory()->getName();
  270.                     break;
  271.                 case 'venue':
  272.                     $result =
  273.                     '<br>'.$this->getVenue()->getName().'<br>'$this->getVenue()->getStreet().' '.$this->getVenue()->getStreetNumber().'<br>';
  274.                     break;
  275.                 case 'venueRoom':
  276.                     $result =
  277.                     $this->getVenueRoom()->getName().' '.$this->getVenueRoom()->getNumber().'; '.$this->getVenueRoom()->getBuilding().'; '.$this->getVenueRoom()->getFloor().'<br>'.$this->getVenue()->getPostalcodeCity().'<br>';
  278.                     break;
  279.             }
  280.         } catch (\Throwable $th) {
  281.             $result '';
  282.         }
  283.         return $result;
  284.     }
  285.     /**
  286.      * @return bool|null
  287.      */
  288.     public function getPublished(): ?bool
  289.     {
  290.         return $this->published;
  291.     }
  292.     /**
  293.      * @param bool $published
  294.      * @return CourseOccurrence
  295.      */
  296.     public function setPublished(bool $published): self
  297.     {
  298.         $this->published $published;
  299.         return $this;
  300.     }
  301.     /**
  302.      * @return bool
  303.      */
  304.     public function isAvailable(): bool
  305.     {
  306.         // Check if occurrence is published
  307.         if (!$this->getPublished()) {
  308.             return false;
  309.         }
  310.         // Check if end date of course is past
  311.         $now = new \DateTime('now');
  312.         if ($this->getEnd()->format('U') < $now->format('U')) {
  313.             return false;
  314.         }
  315.         return true;
  316.     }
  317.     /**
  318.      * @return mixed
  319.      */
  320.     public function getStart()
  321.     {
  322.         return $this->start;
  323.     }
  324.     /**
  325.      * @param \DateTimeInterface $start
  326.      * @return CourseOccurrence
  327.      */
  328.     public function setStart(\DateTimeInterface $start): self
  329.     {
  330.         $this->start $start;
  331.         return $this;
  332.     }
  333.     /**
  334.      * @return mixed
  335.      */
  336.     public function getEnd()
  337.     {
  338.         return $this->end;
  339.     }
  340.     /**
  341.      * @param \DateTimeInterface $end
  342.      * @return CourseOccurrence
  343.      */
  344.     public function setEnd(\DateTimeInterface $end): self
  345.     {
  346.         $this->end $end;
  347.         return $this;
  348.     }
  349.     /**
  350.      * @return bool
  351.      */
  352.     public function hasMultipleDays(): bool
  353.     {
  354.         return $this->getStart()->format('d.m.Y') !== $this->getEnd()->format('d.m.Y');
  355.     }
  356.     /**
  357.      * @return CourseOccurrence
  358.      */
  359.     public function clone()
  360.     {
  361.         $entity = new CourseOccurrence();
  362.         $entity->setId(null);
  363.         $entity->setVenue($this->getVenue());
  364.         $entity->setStart($this->getStart());
  365.         $entity->setEnd($this->getEnd());
  366.         $entity->setSlots($this->getSlots());
  367.         $entity->setCreated(new \Datetime());
  368.         foreach ($this->getSpeakers() as $speaker) {
  369.             $entity->addSpeaker($speaker);
  370.         }
  371.         foreach ($this->getTimes() as $time) {
  372.             $entity->addTime($time->clone());
  373.         }
  374.         return $entity;
  375.     }
  376.     /**
  377.      * Sets a new start date. Moves all other dates in relation to the new start date. This includes dates of related
  378.      * CourseOccurrenceTime entities.
  379.      *
  380.      * @param \DateTime $date
  381.      */
  382.     public function setDate(\DateTime $date)
  383.     {
  384.         $date->add(new \DateInterval('P1D'));
  385.         $difference $this->getStart()->diff($date);
  386.         $difference->0;
  387.         $difference->0;
  388.         $difference->0;
  389.         $this->getStart()->add($difference);
  390.         $this->getEnd()->add($difference);
  391.         foreach ($this->getTimes() as $time) {
  392.             $time->moveDate($difference);
  393.         }
  394.     }
  395.     /**
  396.      * @return Client|null
  397.      */
  398.     public function getClient(): ?Client
  399.     {
  400.         return $this->getCourse()->getClient();
  401.     }
  402.     /**
  403.      * @return null|string
  404.      */
  405.     public function getNumber()
  406.     {
  407.         return $this->getCourse()->getNumber();
  408.     }
  409.     /**
  410.      * @return null|string
  411.      */
  412.     public function getType()
  413.     {
  414.         return $this->getCourse()->getType();
  415.     }
  416.     /**
  417.      * @return Collection|CourseImage[]
  418.      */
  419.     public function getImages(): Collection
  420.     {
  421.         return $this->getCourse()->getImages();
  422.     }
  423.     /**
  424.      * @return float|null
  425.      */
  426.     public function getMaterialCost(): ?float
  427.     {
  428.         return $this->getCourse()->getMaterialCost();
  429.     }
  430.     /**
  431.      * @return int|null
  432.      */
  433.     public function getTargetAgeMin(): ?int
  434.     {
  435.         return $this->getCourse()->getTargetAgeMin();
  436.     }
  437.     /**
  438.      * @return int|null
  439.      */
  440.     public function getTargetAgeMax(): ?int
  441.     {
  442.         return $this->getCourse()->getTargetAgeMax();
  443.     }
  444.     /**
  445.      * @return bool
  446.      */
  447.     public function hasTargetAge(): bool
  448.     {
  449.         return !empty($this->getTargetAgeMin()) || !empty($this->getTargetAgeMax());
  450.     }
  451.     /**
  452.      * @return Collection|CourseText[]
  453.      */
  454.     public function getTexts(): Collection
  455.     {
  456.         return $this->getCourse()->getTexts();
  457.     }
  458.     /**
  459.      * @return null|string
  460.      */
  461.     public function getDescription(): ?string
  462.     {
  463.         return $this->getCourse()->getDescription();
  464.     }
  465.     /**
  466.      * @return int|null
  467.      */
  468.     public function getSlots(): ?int
  469.     {
  470.         return $this->slots;
  471.     }
  472.     /**
  473.      * @param int $slots
  474.      * @return CourseOccurrence
  475.      */
  476.     public function setSlots(int $slots): self
  477.     {
  478.         $this->slots $slots;
  479.         return $this;
  480.     }
  481.         /**
  482.      * @return null|string
  483.      */
  484.     public function getCode(): ?string
  485.     {
  486.         return $this->code;
  487.     }
  488.     /**
  489.      * @param string $code
  490.      * @return CourseOccurrence
  491.      */
  492.     public function setCode(string $code): self
  493.     {
  494.         $this->code $code;
  495.         return $this;
  496.     }
  497.     /**
  498.      * @return bool|null
  499.      */
  500.     public function getReservationAllowed(): ?bool
  501.     {
  502.         return $this->reservationAllowed;
  503.     }
  504.     /**
  505.      * @return bool|null
  506.      */
  507.     public function isReservationAllowed(): ?bool
  508.     {
  509.         return $this->getReservationAllowed();
  510.     }
  511.     /**
  512.      * @param bool $reservationAllowed
  513.      * @return CourseOccurrence
  514.      */
  515.     public function setReservationAllowed(bool $reservationAllowed): self
  516.     {
  517.         $this->reservationAllowed $reservationAllowed;
  518.         return $this;
  519.     }
  520.     /**
  521.      * /**
  522.      * @JMS\Expose
  523.      * @JMS\Groups({"public"})
  524.      * @JMS\VirtualProperty()
  525.      * @JMS\Type("int")
  526.      * @return int|null
  527.      */
  528.     public function getBookedSlots(): ?int
  529.     {
  530.         $bookedSlots 0;
  531.        if ($this->getOrderItems() !== null) {
  532.             foreach ($this->getOrderItems() as $item) {
  533.                 
  534.                     $order $item->getOrder();
  535.                     if(isset($order)){
  536.                         if (!$order->isCancelled() && !$item->isMaterialCost() ) {
  537.                             $bookedSlots += ($item->getQuantity()-$item->getCancelledQuantity());
  538.                         }
  539.                     } 
  540.                
  541.             }
  542.         }
  543.         return $bookedSlots;
  544.         
  545.        //  return $this->bookedSlots;
  546.     }
  547.     public function getBookedSlotsDirectly(): ?int
  548.     {
  549.         return $this->bookedSlots;
  550.     }
  551.     /**
  552.      * @param int $bookedSlots
  553.      * @return CourseOccurrence
  554.      */
  555.     public function setBookedSlots(int $bookedSlots): self
  556.     {
  557.         $this->bookedSlots $bookedSlots;
  558.         return $this;
  559.     }
  560.     /**
  561.      * @return int|null
  562.      */
  563.     public function getFreeSlots(bool $directBooked false): ?int
  564.     {
  565.         if ($directBooked === true) {
  566.             return $this->getSlots() - $this->getBookedSlotsDirectly();
  567.         } else {
  568.             return $this->getSlots() - $this->getBookedSlots();
  569.         }
  570.     }
  571.     /**
  572.      * @return null|string
  573.      */
  574.     public function getReservationStatus(): ?string
  575.     {
  576.         $freeSlots $this->getFreeSlots();
  577.         if ($freeSlots 0) {
  578.             return 'Plätze frei';
  579.         } else {
  580.             if ($this->getReservationAllowed()) {
  581.                 return 'ausgebucht - Reservierung möglich';
  582.             } else {
  583.                 return 'ausgebucht';
  584.             }
  585.         }
  586.     }
  587.     /**
  588.      * @param int $quantity
  589.      * @return CourseOccurrence
  590.      */
  591.     public function bookSlots(int $quantity): self
  592.     {
  593.         $this->pendingBookings += $quantity;
  594.         return $this;
  595.     }
  596.     /**
  597.      * @param int $quantity
  598.      * @return CourseOccurrence
  599.      */
  600.     public function cancelSlots(int $quantity): self
  601.     {
  602.         $this->pendingBookings -= $quantity;
  603.         return $this;
  604.     }
  605.     /**
  606.      * Actually book pending slots
  607.      */
  608.     public function flushBooking()
  609.     {
  610.         $bookedSlots 0;
  611.         foreach ($this->getOrderItems() as $item) {
  612.             if (!$item->getCourseItem() && !$item->getOrder()->isCancelled() && !$item->isCancelled()) {
  613.                 $bookedSlots += $item->getQuantity();
  614.             }
  615.         }
  616.         $this->bookedSlots $bookedSlots;
  617.     }
  618.     /**
  619.      * @param int $numberOfBookings
  620.      * @return bool
  621.      */
  622.     public function isBookable(int $numberOfBookings 0bool $directBooked false): bool
  623.     {
  624.         return $numberOfBookings <= $this->getFreeSlots($directBooked);
  625.     }
  626.     /**
  627.      * @return Collection|WaitItem[]
  628.      */
  629.     public function getWaitItems(): Collection
  630.     {
  631.         return $this->waitItems;
  632.     }
  633.     /**
  634.      * @param WaitItem $waitItem
  635.      * @return CourseOccurrence
  636.      */
  637.     public function addWaitItem(WaitItem $waitItem): self
  638.     {
  639.         if (!$this->waitItems->contains($waitItem)) {
  640.             $this->waitItems[] = $waitItem;
  641.             $waitItem->setCourseOccurrence($this);
  642.         }
  643.         return $this;
  644.     }
  645.     /**
  646.      * @param WaitItem $waitItem
  647.      * @return CourseOccurrence
  648.      */
  649.     public function removeWaitItem(WaitItem $waitItem): self
  650.     {
  651.         if ($this->waitItems->contains($waitItem)) {
  652.             $this->waitItems->removeElement($waitItem);
  653.             // set the owning side to null (unless already changed)
  654.             if ($waitItem->getCourseOccurrence() === $this) {
  655.                 $waitItem->setCourseOccurrence(null);
  656.             }
  657.         }
  658.         return $this;
  659.     }
  660.     /**
  661.      * @return int
  662.      */
  663.     public function getWaitItemCount(): int
  664.    {
  665.     ///// es werden nur die NICHTgecanccelte Wait Items gezählt /////// 
  666.         $bookedSlots 0;
  667.         foreach ($this->getWaitItems() as $item) {
  668.             if (!$item->getOrder()->isCancelled()) {
  669.                 $bookedSlots += $item->getQuantity();
  670.             }
  671.         }
  672.        
  673.         return $bookedSlots;
  674.        // return count($this->waitItems);
  675.     }
  676.     /**
  677.      * @return bool
  678.      */
  679.     public function hasWaitList(): bool
  680.     {
  681.         return $this->isReservationAllowed() && $this->getWaitItemCount() > 0;
  682.     }
  683.     /**
  684.      * @param CourseOccurrence $target
  685.      * @return CourseOccurrence
  686.      */
  687.     public function moveWaitListTo(CourseOccurrence $target): self
  688.     {
  689.         foreach ($this->getWaitItems() as $waitItem) {
  690.             $this->removeWaitItem($waitItem);
  691.             $target->addWaitItem($waitItem);
  692.         }
  693.         return $this;
  694.     }
  695.     /**
  696.      * @return array
  697.      */
  698.     public function getSpeakerNames()
  699.     {
  700.         $speakerNames = [];
  701.         foreach ($this->getSpeakers() as $speaker) {
  702.             $speakerNames[] = $speaker->getFullname();
  703.         }
  704.         return $speakerNames;
  705.     }
  706.     /**
  707.      * @return string
  708.      */
  709.     public function getCaption()
  710.     {
  711.         return $this->getTitle() . ' (' $this->getStart()->format('d.m.Y') . ')';
  712.     }
  713.     public function getKursstart()
  714.     {
  715.         return $this->getStart()->format('d.m.Y');
  716.     }
  717.     public function getKursende()
  718.     {
  719.         return $this->getEnd()->format('d.m.Y');
  720.     }
  721.     public function getTaxRate()
  722.     {
  723.         return $this->getCourse()->getTaxRate();
  724.     }
  725.     public function getKursstartendeuhrzeit()
  726.     {
  727.         return $this->getStart()->format('H:i') . ' bis ' $this->getEnd()->format('H:i') . ' Uhr';
  728.     }
  729.     /**
  730.      * @JMS\Expose
  731.      * @JMS\Groups({"public"})
  732.      * @JMS\VirtualProperty()
  733.      * @JMS\Type("int")
  734.      * @return int
  735.      */
  736.     public function getId(): ?int
  737.     {
  738.         return parent::getId();
  739.     }
  740.     /**
  741.      * @return OrderItem[]
  742.      */
  743.     public function getOrderItems()
  744.     {
  745.         return $this->orderItems;
  746.     }
  747.     /**
  748.      *
  749.      */
  750.     public function setOrderItems($orderItems)
  751.     {
  752.         $this->orderItems $orderItems;
  753.     }
  754. }