<?php
namespace App\Entity\PointsCatalog;
use App\Annotation\SiteAware;
use App\Entity\AbstractBase;
use App\Entity\Garages\Garage;
use App\Entity\Interfaces\SiteInterface;
use App\Entity\MiniAbstractBase;
use App\Entity\Traits\DescriptionTrait;
use App\Entity\Traits\GarageTrait;
use App\Entity\Traits\SiteTrait;
use App\Entity\User;
use App\Exception\PointsLimitException;
use App\Repository\PointsCatalog\CatalogPointMovementRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @ORM\Table(name="vulco_points_catalog_point_movement", indexes={@ORM\Index(name="catalog_point_movement_site_idx", columns={"site"})})
*
* @ORM\Entity(repositoryClass=CatalogPointMovementRepository::class)
*
* @Gedmo\SoftDeleteable(fieldName="removedAt", timeAware=false)
*
* @SiteAware(siteFieldName="site")
*/
class CatalogPointMovement extends AbstractBase implements SiteInterface
{
use DescriptionTrait;
use GarageTrait;
use SiteTrait;
public const TYPE_POSITIVE = 'positive';
public const TYPE_NEGATIVE = 'negative';
public const TYPE_EXPIRED = 'expired';
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private ?string $description = null;
/**
* @ORM\Column(type="date", nullable=false)
*/
private \DateTimeInterface $date;
/**
* @ORM\Column(type="date", nullable=true)
*/
private ?\DateTimeInterface $expiredAt = null;
/**
* @ORM\Column(type="float", nullable=false)
*/
private float $points;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="pointMovements")
*
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private User $user;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Garages\Garage")
*
* @ORM\JoinColumn(name="garage_id", referencedColumnName="id")
*/
private Garage $garage;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\PointsCatalog\CatalogConversionFormula")
*
* @ORM\JoinColumn(name="conversion_formula_id", referencedColumnName="id")
*/
private CatalogConversionFormula $conversionFormula;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\PointsCatalog\CatalogGiftProvider")
*
* @ORM\JoinColumn(name="provider_id", referencedColumnName="id")
*/
private ?CatalogGiftProvider $provider = null;
/**
* @ORM\Column(type="boolean", nullable=false, options={"default": 0})
*/
private bool $returnMovement = false;
public function getDate(): \DateTimeInterface
{
return $this->date;
}
public function getDateString(): string
{
return $this->getDateAsString($this->getDate());
}
public function setDate(\DateTimeInterface $date): self
{
$this->date = $date;
return $this;
}
public function getExpiredAt(): ?\DateTimeInterface
{
return $this->expiredAt;
}
public function setExpiredAt(?\DateTimeInterface $date): self
{
$this->expiredAt = $date;
return $this;
}
public function getPoints(): float
{
return $this->points;
}
/**
* @throws \RuntimeException
* @throws PointsLimitException
*/
public function setPoints(float $points, bool $isReturnMovement): self
{
if (!$this->getDate() instanceof \DateTimeInterface) {
throw new \RuntimeException('Invalid date');
}
// Si son puntos positivos (los que gasta son negativos) y no es una devolucion
// (IMP: EL LIMITE DE PUNTOS SE REFIERE A LOS PUNTOS QUE PUEDE CONSEGUIR, NO AL BALANCE)
// => comprobamos que no sobrepase el limite de puntos que puede conseguir en un año natural
if (!$isReturnMovement && ($points > 0.00001)) {
// https://www.php.net/manual/en/language.types.float.php
$earnedGaragePoints = $this->garage->getOwner()->getGarageEarnedPointsWithinCalendarYear($this->garage, $this->date);
$pointsSum = $earnedGaragePoints + $points;
if ($pointsSum > $this->garage->getPointsLimit()) {
// we assign it only the points to reach the limit.
$this->points = $this->garage->getPointsLimit() - $earnedGaragePoints;
throw new PointsLimitException();
}
}
$this->points = $points;
return $this;
}
// only for fixtures purpouses
public function setFakedPoints(float $points): self
{
$this->points = $points;
return $this;
}
public function getUser(): User
{
return $this->user;
}
public function setUser(User $user): self
{
$this->user = $user;
return $this;
}
public function getConversionFormula(): CatalogConversionFormula
{
return $this->conversionFormula;
}
public function setConversionFormula(CatalogConversionFormula $conversionFormula): self
{
$this->conversionFormula = $conversionFormula;
return $this;
}
public function getProvider(): ?CatalogGiftProvider
{
return $this->provider;
}
public function setProvider(?CatalogGiftProvider $provider): self
{
$this->provider = $provider;
return $this;
}
public function isReturnMovement(): bool
{
return $this->returnMovement;
}
public function setReturnMovement(bool $returnMovement): self
{
$this->returnMovement = $returnMovement;
return $this;
}
public function type(): string
{
if (!$this->expiredAt) {
// https://www.php.net/manual/en/language.types.float.php
return $this->points > 0.00001 ? self::TYPE_POSITIVE : self::TYPE_NEGATIVE;
}
return self::TYPE_EXPIRED;
}
public function __toString(): string
{
return $this->id ? $this->getId().' # '.$this->getDateAsString($this->getDate()).' # '.$this->getPoints() : MiniAbstractBase::DEFAULT_EMPTY_STRING;
}
}