. */ declare(strict_types=1); namespace App\Entity\PriceInformations; use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Metadata\ApiProperty; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Delete; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Link; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use ApiPlatform\Serializer\Filter\PropertyFilter; use App\Entity\Attachments\Attachment; use App\Entity\Attachments\AttachmentTypeAttachment; use App\Entity\Parts\Footprint; use App\Repository\CurrencyRepository; use Doctrine\DBAL\Types\Types; use App\Entity\Attachments\CurrencyAttachment; use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Parameters\CurrencyParameter; use App\Validator\Constraints\BigDecimal\BigDecimalPositive; use Brick\Math\BigDecimal; use Brick\Math\RoundingMode; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; /** * This entity describes a currency that can be used for price information. * * @extends AbstractStructuralDBElement */ #[UniqueEntity('iso_code')] #[ORM\Entity(repositoryClass: CurrencyRepository::class)] #[ORM\Table(name: 'currencies')] #[ORM\Index(name: 'currency_idx_name', columns: ['name'])] #[ORM\Index(name: 'currency_idx_parent_name', columns: ['parent_id', 'name'])] #[ApiResource( operations: [ new Get(security: 'is_granted("read", object)'), new GetCollection(security: 'is_granted("@currencies.read")'), new Post(securityPostDenormalize: 'is_granted("create", object)'), new Patch(security: 'is_granted("edit", object)'), new Delete(security: 'is_granted("delete", object)'), ], normalizationContext: ['groups' => ['currency:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'], denormalizationContext: ['groups' => ['currency:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'], )] #[ApiResource( uriTemplate: '/currencies/{id}/children.{_format}', operations: [ new GetCollection(openapiContext: ['summary' => 'Retrieves the children elements of a currency.'], security: 'is_granted("@currencies.read")') ], uriVariables: [ 'id' => new Link(fromProperty: 'children', fromClass: Currency::class) ], normalizationContext: ['groups' => ['currency:read', 'api:basic:read'], 'openapi_definition_name' => 'Read'] )] #[ApiFilter(PropertyFilter::class)] class Currency extends AbstractStructuralDBElement { final public const PRICE_SCALE = 5; /** * @var BigDecimal|null The exchange rate between this currency and the base currency * (how many base units the current currency is worth) */ #[ORM\Column(type: 'big_decimal', precision: 11, scale: 5, nullable: true)] #[BigDecimalPositive()] #[Groups(['currency:read', 'currency:write'])] #[ApiProperty(readableLink: false, writableLink: false)] protected ?BigDecimal $exchange_rate = null; #[Groups(['currency:read', 'currency:write'])] protected string $comment = ""; /** * @var string the 3-letter ISO code of the currency */ #[Assert\Currency] #[Assert\NotBlank] #[Groups(['extended', 'full', 'import', 'currency:read', 'currency:write'])] #[ORM\Column(type: Types::STRING)] protected string $iso_code = ""; #[ORM\OneToMany(targetEntity: self::class, mappedBy: 'parent', cascade: ['persist'])] #[ORM\OrderBy(['name' => 'ASC'])] protected Collection $children; #[ORM\ManyToOne(targetEntity: self::class, inversedBy: 'children')] #[ORM\JoinColumn(name: 'parent_id')] #[Groups(['currency:read', 'currency:write'])] #[ApiProperty(readableLink: false, writableLink: false)] protected ?AbstractStructuralDBElement $parent = null; /** * @var Collection */ #[Assert\Valid] #[ORM\OneToMany(targetEntity: CurrencyAttachment::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['name' => 'ASC'])] #[Groups(['currency:read', 'currency:write'])] protected Collection $attachments; #[ORM\ManyToOne(targetEntity: CurrencyAttachment::class)] #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] #[Groups(['currency:read', 'currency:write'])] protected ?Attachment $master_picture_attachment = null; /** @var Collection */ #[Assert\Valid] #[ORM\OneToMany(targetEntity: CurrencyParameter::class, mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] #[Groups(['currency:read', 'currency:write'])] protected Collection $parameters; /** @var Collection */ #[ORM\OneToMany(targetEntity: Pricedetail::class, mappedBy: 'currency')] protected Collection $pricedetails; public function __construct() { $this->children = new ArrayCollection(); $this->attachments = new ArrayCollection(); $this->parameters = new ArrayCollection(); $this->pricedetails = new ArrayCollection(); parent::__construct(); } public function getPricedetails(): Collection { return $this->pricedetails; } /** * Returns the 3-letter ISO code of this currency. * * @return string */ public function getIsoCode(): string { return $this->iso_code; } public function setIsoCode(string $iso_code): self { $this->iso_code = $iso_code; return $this; } /** * Returns the inverse exchange rate (how many of the current currency the base unit is worth). */ #[Groups(['currency:read'])] public function getInverseExchangeRate(): ?BigDecimal { $tmp = $this->getExchangeRate(); if (!$tmp instanceof BigDecimal || $tmp->isZero()) { return null; } return BigDecimal::one()->dividedBy($tmp, $tmp->getScale(), RoundingMode::HALF_UP); } /** * Returns The exchange rate between this currency and the base currency * (how many base units the current currency is worth). */ public function getExchangeRate(): ?BigDecimal { return $this->exchange_rate; } /** * Sets the exchange rate of the currency. * * @param BigDecimal|null $exchange_rate The new exchange rate of the currency. * Set to null, if the exchange rate is unknown. */ public function setExchangeRate(?BigDecimal $exchange_rate): self { //If the exchange rate is null, set it to null and return. if ($exchange_rate === null) { $this->exchange_rate = null; return $this; } //Only change the object, if the value changes, so that doctrine does not detect it as changed. //Or if the current exchange rate is currently null, as we can not compare it then if ($this->exchange_rate === null || $exchange_rate->compareTo($this->exchange_rate) !== 0) { $this->exchange_rate = $exchange_rate; } return $this; } }