vendor/bluue/products-bundle/src/Entity/Declination.php line 46

Open in your IDE?
  1. <?php
  2. /**
  3.  * @author Leo BANNHOLTZER (contact@scaledev.fr)
  4.  * @copyright 2021 - ScaleDEV SAS, 12 RUE CHARLES MORET, 10120 ST ANDRE LES VERGERS
  5.  * @license commercial
  6.  */
  7. declare(strict_types=1);
  8. namespace Bluue\ProductsBundle\Entity;
  9. use App\Entity\Context;
  10. use App\Entity\TaxRule;
  11. use App\Entity\Currency;
  12. use App\Entity\Traits\EntityManagerServiceEntity;
  13. use App\Entity\UnitMeasure;
  14. use App\Services\SoftdeleteFilter;
  15. use Doctrine\ORM\NonUniqueResultException;
  16. use Symfony\Component\Uid\Uuid;
  17. use Doctrine\ORM\Mapping as ORM;
  18. use Gedmo\Mapping\Annotation as Gedmo;
  19. use App\Entity\Traits\ContextServiceEntity;
  20. use Doctrine\Common\Collections\Collection;
  21. use Bluue\ProductsBundle\Entity\PackProduct;
  22. use App\Entity\Traits\TranslatorServiceEntity;
  23. use Doctrine\Common\Collections\ArrayCollection;
  24. use Bluue\ProductsBundle\Entity\DeclinationImage;
  25. use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
  26. use Bluue\ProductsBundle\Repository\DeclinationRepository;
  27. use App\DoctrineExtensions\Timestampable\Traits\UserTimestampableEntity;
  28. use App\DoctrineExtensions\SoftDeleteable\Traits\UserSoftDeleteableEntity;
  29. /**
  30.  * @ORM\Entity(repositoryClass=DeclinationRepository::class)
  31.  * @ORM\Table(name="products_bundle__declination", indexes={
  32.  *  @ORM\Index(name="initial_unit", columns={"initial_unit"}),
  33.  *  @ORM\Index(name="weight", columns={"weight"}),
  34.  *  @ORM\Index(name="energy_code", columns={"energy_code"}),
  35.  *  @ORM\Index(name="deleted_at", columns={"deleted_at"}),
  36.  *  @ORM\Index(name="created_at", columns={"created_at"}),
  37.  *  @ORM\Index(name="updated_at", columns={"updated_at"})
  38.  * })
  39.  * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=false)
  40.  */
  41. class Declination
  42. {
  43.     use UserTimestampableEntity;
  44.     use UserSoftDeleteableEntity;
  45.     use TranslatorServiceEntity;
  46.     use ContextServiceEntity;
  47.     use EntityManagerServiceEntity;
  48.     public const ATTRIBUTE_SEPARATOR ':';
  49.     public const SEPARATOR_BETWEEN_NAME_AND_ATTRIBUTE '-';
  50.     /**
  51.      * @ORM\Id
  52.      * @ORM\Column(type="uuid")
  53.      * @ORM\GeneratedValue(strategy="CUSTOM")
  54.      * @ORM\CustomIdGenerator(class=UuidGenerator::class)
  55.      */
  56.     private ?Uuid $id null;
  57.     /**
  58.      * @ORM\ManyToOne(targetEntity=Product::class, inversedBy="declinations")
  59.      * @ORM\JoinColumn(nullable=false)
  60.      */
  61.     private Product $product;
  62.     /**
  63.      * @ORM\OneToMany(
  64.      *  targetEntity=Ean13::class,
  65.      *  mappedBy="declination",
  66.      *  fetch="EXTRA_LAZY",
  67.      *  cascade={"persist", "remove"})
  68.      * )
  69.      */
  70.     private Collection $ean13s;
  71.     /**
  72.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable=true)
  73.      */
  74.     private ?string $initial_unit;
  75.     /**
  76.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable=true)
  77.      */
  78.     private ?string $weight;
  79.     /**
  80.      * @ORM\ManyToOne(targetEntity=Declination::class, inversedBy="virtualDeclinations")
  81.      */
  82.     private ?Declination $virtualParent null;
  83.     /**
  84.      * @ORM\Column(type="integer", nullable=true)
  85.      */
  86.     private ?int $virtualQuantity null;
  87.     /**
  88.      * @ORM\Column(type="string", nullable=true)
  89.      */
  90.     private ?string $energyCode null;
  91.     /**
  92.      * @ORM\OneToMany(
  93.      *     targetEntity=Declination::class,
  94.      *     mappedBy="virtualParent",
  95.      *     fetch="EXTRA_LAZY"
  96.      * )
  97.      */
  98.     private Collection $virtualDeclinations;
  99.     /**
  100.      * @ORM\OneToMany(
  101.      *  targetEntity=DeclinationAttribute::class,
  102.      *  mappedBy="declination",
  103.      *  cascade={"remove"},
  104.      *  fetch="EXTRA_LAZY"
  105.      * )
  106.      */
  107.     private Collection $declinationAttributes;
  108.     /**
  109.      * @ORM\ManyToOne(targetEntity=UnitMeasure::class)
  110.      */
  111.     private ?UnitMeasure $unit_measure null;
  112.     /**
  113.      * @ORM\OneToMany(
  114.      *  targetEntity=DeclinationContext::class,
  115.      *  mappedBy="declination",
  116.      *  cascade={"remove"},
  117.      *  fetch="EXTRA_LAZY"
  118.      * )
  119.      */
  120.     private Collection $declinationContexts;
  121.     /**
  122.      * @ORM\OneToMany(targetEntity="DeclinationImage", mappedBy="declination", cascade={"remove"}, fetch="EXTRA_LAZY")
  123.      */
  124.     private Collection $declinationImages;
  125.     /**
  126.      * @ORM\OneToMany(targetEntity=PackProduct::class, mappedBy="declination", cascade={"remove"}, fetch="EXTRA_LAZY")
  127.      * @ORM\OrderBy({"position" = "ASC"})
  128.      */
  129.     private Collection $packProducts;
  130.     /**
  131.      * @ORM\OneToMany(
  132.      *  targetEntity=PackProduct::class,
  133.      *  mappedBy="parentDeclination",
  134.      *  cascade={"remove"},
  135.      *  fetch="EXTRA_LAZY"
  136.      * )
  137.      * @ORM\OrderBy({"position" = "ASC"})
  138.      */
  139.     private Collection $packProductsWithParentDeclination;
  140.     private ?Context $context null;
  141.     /**
  142.      * @ORM\Column(type="json")
  143.      */
  144.     private array $options = [];
  145.     // For stock bundle
  146.     private Collection $stockProducts;
  147.     private ?object $stockProductRoot null;
  148.     public $quantity_real null;
  149.     public $quantity_virtual null;
  150.     // For suppliers
  151.     private Collection $product_suppliers;
  152.     public function __construct()
  153.     {
  154.         $this->virtualDeclinations = new ArrayCollection();
  155.         $this->declinationAttributes = new ArrayCollection();
  156.         $this->declinationContexts = new ArrayCollection();
  157.         $this->declinationImages = new ArrayCollection();
  158.         $this->packProducts = new ArrayCollection();
  159.         $this->packProductsWithParentDeclination = new ArrayCollection();
  160.         $this->stockProducts = new ArrayCollection();
  161.         $this->ean13s = new ArrayCollection();
  162.         $this->product_suppliers = new ArrayCollection();
  163.     }
  164.     /**
  165.      * @return Uuid|null
  166.      */
  167.     public function getId(): ?Uuid
  168.     {
  169.         return $this->id;
  170.     }
  171.     /**
  172.      * @return Product|null
  173.      * @throws NonUniqueResultException
  174.      */
  175.     public function getProduct(): ?Product
  176.     {
  177.         if ($this->em) {
  178.             SoftdeleteFilter::disable($this->em, [Product::class]);
  179.             $product $this->em->getRepository(Product::class)
  180.                 ->createQueryBuilder('p')
  181.                 ->where('p.id = :productId')
  182.                 ->setParameter('productId'$this->product->getId()->toBinary())
  183.                 ->getQuery()
  184.                 ->getOneOrNullResult();
  185.             SoftdeleteFilter::enable($this->em, [Product::class]);
  186.             return $product;
  187.         }
  188.         return $this->product;
  189.     }
  190.     /**
  191.      * @param Product|null $product
  192.      * @return $this
  193.      */
  194.     public function setProduct(?Product $product): self
  195.     {
  196.         $this->product $product;
  197.         return $this;
  198.     }
  199.     /**
  200.      * Exemple : Nom Produit - Quantité : 50g
  201.      * @param ?bool $withProductName
  202.      * @param Context|null $context
  203.      * @return string|null
  204.      * @throws NonUniqueResultException
  205.      */
  206.     public function getName(?bool $withProductName true, ?Context $context null): ?string
  207.     {
  208.         $return $withProductName $this->getProduct()->getName($context) : '';
  209.         foreach ($this->getDeclinationAttributes() as $declinationAttribute) {
  210.             // ordonner par attribute groupe name
  211.             $return .= ' ' self::SEPARATOR_BETWEEN_NAME_AND_ATTRIBUTE ' ';
  212.             $attribute $declinationAttribute->getAttribute();
  213.             $return .= $attribute->getAttributeGroup()->getName() . ' ' self::ATTRIBUTE_SEPARATOR ' ';
  214.             $return .= $declinationAttribute->getAttribute()->getName();
  215.         }
  216.         return $return;
  217.     }
  218.     /**
  219.      * @return Collection|Ean13[]
  220.      */
  221.     public function getEan13s(): Collection
  222.     {
  223.         return $this->ean13s;
  224.     }
  225.     /**
  226.      * @param Ean13 $ean13
  227.      * @return $this
  228.      */
  229.     public function addEan13(Ean13 $ean13): self
  230.     {
  231.         if (!$this->ean13s->contains($ean13)) {
  232.             $this->ean13s[] = $ean13;
  233.             $ean13->setDeclination($this);
  234.         }
  235.         return $this;
  236.     }
  237.     /**
  238.      * @param Ean13 $ean13
  239.      * @return $this
  240.      */
  241.     public function removeEan13(Ean13 $ean13): self
  242.     {
  243.         $this->ean13s->removeElement($ean13);
  244.         return $this;
  245.     }
  246.     /**
  247.      * @return $this
  248.      */
  249.     public function removeAllEan13(): self
  250.     {
  251.         $this->ean13s->slice(0);
  252.         return $this;
  253.     }
  254.     public function getDefaultEan13()
  255.     {
  256.         $ean13 $this->ean13s->filter(function ($item) {
  257.             return $item->getIsDefault();
  258.         });
  259.         return count($ean13) ? $ean13->first() : false;
  260.     }
  261.     public function showDefaultEan13(): string
  262.     {
  263.         $default_ean13 $this->getDefaultEan13();
  264.         return $default_ean13 && !empty($default_ean13->getValue()) ? $default_ean13->getValue() : '';
  265.     }
  266.     /**
  267.      * @return string|null
  268.      */
  269.     public function getInitialUnit(): ?string
  270.     {
  271.         if ($this->isVirtual()) {
  272.             return (string) ((float) $this->virtualParent->getInitialUnit() * $this->virtualQuantity);
  273.         } else {
  274.             return $this->initial_unit;
  275.         }
  276.     }
  277.     /**
  278.      * @param string|null $initial_unit
  279.      * @return $this
  280.      */
  281.     public function setInitialUnit(?string $initial_unit): self
  282.     {
  283.         $this->initial_unit $initial_unit;
  284.         return $this;
  285.     }
  286.     /**
  287.      * @return string|null
  288.      */
  289.     public function getWeight(): ?string
  290.     {
  291.         if ($this->isVirtual()) {
  292.             return (string) ((float) $this->virtualParent->getWeight() * $this->virtualQuantity);
  293.         } else {
  294.             return $this->weight;
  295.         }
  296.     }
  297.     /**
  298.      * @param string|null $weight
  299.      * @return $this
  300.      */
  301.     public function setWeight(?string $weight): self
  302.     {
  303.         $this->weight $weight;
  304.         return $this;
  305.     }
  306.     /**
  307.      * @return Collection|Declination[]
  308.      */
  309.     public function getVirtualDeclinations(): Collection
  310.     {
  311.         return $this->virtualDeclinations;
  312.     }
  313.     /**
  314.      * @return Collection|DeclinationAttribute[]
  315.      */
  316.     public function getDeclinationAttributes(): Collection
  317.     {
  318.         return $this->declinationAttributes;
  319.     }
  320.     /**
  321.      * @param DeclinationAttribute $declinationAttribute
  322.      * @return $this
  323.      */
  324.     public function addDeclinationAttribute(DeclinationAttribute $declinationAttribute): self
  325.     {
  326.         if (!$this->declinationAttributes->contains($declinationAttribute)) {
  327.             $this->declinationAttributes[] = $declinationAttribute;
  328.             $declinationAttribute->setDeclination($this);
  329.         }
  330.         return $this;
  331.     }
  332.     /**
  333.      * @param DeclinationAttribute $declinationAttribute
  334.      * @return $this
  335.      */
  336.     public function removeDeclinationAttribute(DeclinationAttribute $declinationAttribute): self
  337.     {
  338.         if ($this->declinationAttributes->removeElement($declinationAttribute)) {
  339.             if ($declinationAttribute->getDeclination() === $this) {
  340.                 $declinationAttribute->setDeclination(null);
  341.             }
  342.         }
  343.         return $this;
  344.     }
  345.     /**
  346.      * @return UnitMeasure|null
  347.      */
  348.     public function getUnitMeasure(): ?UnitMeasure
  349.     {
  350.         if ($this->isVirtual() && $this->virtualParent->getUnitMeasure()) {
  351.             return $this->virtualParent->getUnitMeasure();
  352.         } elseif (!$this->unit_measure) {
  353.             return $this->product->getUnitMeasure();
  354.         }
  355.         return $this->unit_measure;
  356.     }
  357.     /**
  358.      * @param UnitMeasure|null $unit_measure
  359.      * @return $this
  360.      */
  361.     public function setUnitMeasure(?UnitMeasure $unit_measure): self
  362.     {
  363.         $this->unit_measure $unit_measure;
  364.         return $this;
  365.     }
  366.     /**
  367.      * @return array
  368.      */
  369.     public function getOptions(): array
  370.     {
  371.         return $this->options;
  372.     }
  373.     /**
  374.      * @param array $options
  375.      * @return $this
  376.      */
  377.     public function setOptions(array $options): self
  378.     {
  379.         $this->options $options;
  380.         return $this;
  381.     }
  382.     /**
  383.      * @param array $options
  384.      * @return $this
  385.      */
  386.     public function addOptions(array $options): self
  387.     {
  388.         return $this->setOptions(array_merge($this->options$options));
  389.     }
  390.     /**
  391.      * @return Collection|DeclinationContext[]
  392.      */
  393.     public function getDeclinationContexts(): Collection
  394.     {
  395.         return $this->declinationContexts;
  396.     }
  397.     /**
  398.      * @param DeclinationContext $declinationContext
  399.      * @return $this
  400.      */
  401.     public function addDeclinationContext(DeclinationContext $declinationContext): self
  402.     {
  403.         if (!$this->declinationContexts->contains($declinationContext)) {
  404.             $this->declinationContexts[] = $declinationContext;
  405.             $declinationContext->setDeclination($this);
  406.         }
  407.         return $this;
  408.     }
  409.     /**
  410.      * @param DeclinationContext $declinationContext
  411.      * @return $this
  412.      */
  413.     public function removeDeclinationContext(DeclinationContext $declinationContext): self
  414.     {
  415.         if ($this->declinationContexts->removeElement($declinationContext)) {
  416.             if ($declinationContext->getDeclination() === $this) {
  417.                 $declinationContext->setDeclination(null);
  418.             }
  419.         }
  420.         return $this;
  421.     }
  422.     /**
  423.      * @param ?Context $context
  424.      * @return DeclinationContext|null
  425.      */
  426.     public function getDeclinationContext(?Context $context null): ?DeclinationContext
  427.     {
  428.         $value null;
  429.         if ($this->getId()) {
  430.             if (!$this->context) {
  431.                 $this->context $context ?: $this->contextService->getActualOrDefault();
  432.             } elseif ($context && $context != $this->context) {
  433.                 $this->context $context;
  434.             }
  435.             foreach ($this->getDeclinationContexts() as $dc) {
  436.                 if ($dc->getContext() == $this->context) {
  437.                     $value $dc;
  438.                 }
  439.             }
  440.         }
  441.         return $value;
  442.     }
  443.     /**
  444.      * @return Collection|DeclinationImage[]
  445.      */
  446.     public function getDeclinationImages(): Collection
  447.     {
  448.         return $this->declinationImages;
  449.     }
  450.     /**
  451.      * @param ?Context $context
  452.      * @return ProductImage|null
  453.      */
  454.     public function getCoverImage(?Context $context null): ?ProductImage
  455.     {
  456.         $image null;
  457.         if ($this->getId() && $this->getProduct()) {
  458.             $image $this->getProduct()->getCoverImageOfProductContext($context);
  459.             $decliImages $this->getDeclinationImages($context)->getValues();
  460.             usort($decliImages, function (DeclinationImage $aDeclinationImage $b) {
  461.                 return $b->getProductImage()->getPosition() <=> $a->getProductImage()->getPosition();
  462.             });
  463.             foreach ($decliImages as $di) {
  464.                 $image $di->getProductImage();
  465.                 if ($di->getProductImage()->getIsCover()) {
  466.                     break;
  467.                 }
  468.             }
  469.         }
  470.         return $image;
  471.     }
  472.     /**
  473.      * @return Collection|PackProduct[]
  474.      */
  475.     public function getPackProducts(): Collection
  476.     {
  477.         return $this->packProducts;
  478.     }
  479.     /**
  480.      * @return Collection|PackProduct[]
  481.      */
  482.     public function getPackProductsWithParentDeclination(): Collection
  483.     {
  484.         return $this->packProductsWithParentDeclination;
  485.     }
  486.     /**
  487.      * @param ?Context $context
  488.      * @return string|null
  489.      */
  490.     public function getReference(?Context $context null): ?string
  491.     {
  492.         if (!$this->context) {
  493.             $this->context $context ?: $this->contextService->getActualOrDefault();
  494.         } elseif ($context && $context != $this->context) {
  495.             $this->context $context;
  496.         }
  497.         $value null;
  498.         foreach ($this->getDeclinationContexts() as $dc) {
  499.             if ($dc->getContext() == $this->context) {
  500.                 $value $dc->getReference();
  501.             }
  502.         }
  503.         return $value;
  504.     }
  505.     /**
  506.      * @param ?Context $context
  507.      * @return string|null
  508.      */
  509.     public function getWholesalePrice(?Context $context null): ?string
  510.     {
  511.         if (!$this->context) {
  512.             $this->context $context ?: $this->contextService->getActualOrDefault();
  513.         } elseif ($context && $context != $this->context) {
  514.             $this->context $context;
  515.         }
  516.         $value null;
  517.         foreach ($this->getDeclinationContexts() as $dc) {
  518.             if ($dc->getContext() == $this->context) {
  519.                 $value $dc->getWholesalePrice();
  520.             }
  521.         }
  522.         return $value;
  523.     }
  524.     /**
  525.      * @param ?Context $context
  526.      * @return string|null
  527.      */
  528.     public function getSellPrice(?Context $context null): ?string
  529.     {
  530.         if (!$this->context) {
  531.             $this->context $context ?: $this->contextService->getActualOrDefault();
  532.         } elseif ($context && $context != $this->context) {
  533.             $this->context $context;
  534.         }
  535.         $value null;
  536.         foreach ($this->getDeclinationContexts() as $dc) {
  537.             if ($dc->getContext() == $this->context) {
  538.                 $value $dc->getSellPrice();
  539.             }
  540.         }
  541.         return $value;
  542.     }
  543.     /**
  544.      * @param ?Context $context
  545.      * @return bool|null
  546.      */
  547.     public function getIsActive(?Context $context null): ?bool
  548.     {
  549.         if (!$this->context) {
  550.             $this->context $context ?: $this->contextService->getActualOrDefault();
  551.         } elseif ($context && $context != $this->context) {
  552.             $this->context $context;
  553.         }
  554.         $value null;
  555.         foreach ($this->getDeclinationContexts() as $dc) {
  556.             if ($dc->getContext() == $this->context) {
  557.                 $value $dc->getIsActive();
  558.             }
  559.         }
  560.         return $value;
  561.     }
  562.     /**
  563.      * @param ?Context $context
  564.      * @return bool|null
  565.      */
  566.     public function getIsDefault(?Context $context null): ?bool
  567.     {
  568.         if (!$this->context) {
  569.             $this->context $context ?: $this->contextService->getActualOrDefault();
  570.         } elseif ($context && $context != $this->context) {
  571.             $this->context $context;
  572.         }
  573.         $value null;
  574.         foreach ($this->getDeclinationContexts() as $dc) {
  575.             if ($dc->getContext() == $this->context) {
  576.                 $value $dc->getIsDefault();
  577.             }
  578.         }
  579.         return $value;
  580.     }
  581.     /**
  582.      * @param ?Context $context
  583.      * @param ?bool $withProductName
  584.      * @param bool $withRef
  585.      * @return string
  586.      */
  587.     public function getChoiceLabel(
  588.         ?Context $context null,
  589.         ?bool $withProductName true,
  590.         bool $withRef true
  591.     ): string {
  592.         if (
  593.             !$context
  594.             && !$this->getDeclinationContexts()->isEmpty()
  595.             && !$this->getDeclinationContext($this->context ?: $this->contextService->getActualOrDefault())
  596.         ) {
  597.             $context $this->getDeclinationContexts()->first()->getContext();
  598.         }
  599.         $label '';
  600.         if ($withRef && $ref $this->getReference($context)) {
  601.             $label .= '[' $ref '] ';
  602.         }
  603.         $label .= $this->getName($withProductName$context);
  604.         if (empty($this->getDeclinationAttributes()->getValues())) {
  605.             $label .= ' - ' $this->translatorService->trans('No attributes', [], 'ProductsBundle');
  606.         }
  607.         return $label;
  608.     }
  609.     // For stock bundle
  610.     /**
  611.      * @param Uuid|null $warehouseId
  612.      * @param Context|null $context
  613.      * @return Collection
  614.      */
  615.     public function getStockProducts(?Uuid $warehouseId null, ?Context $context null): Collection
  616.     {
  617.         if ($context) {
  618.             $stockProducts $this->stockProducts->filter(function ($stockProduct) use ($context) {
  619.                 return $stockProduct->getStockProductRootContexts()->filter(
  620.                     function ($stockProductRootContext) use ($context) {
  621.                         return $stockProductRootContext->getContext() == $context;
  622.                     }
  623.                 )->count() > 0;
  624.             });
  625.         } else {
  626.             $stockProducts $this->stockProducts;
  627.         }
  628.         if ($warehouseId) {
  629.             return $stockProducts->filter(function ($stockProduct) use ($warehouseId) {
  630.                 return $stockProduct->getWarehouse()->getId() == $warehouseId;
  631.             });
  632.         }
  633.         return $stockProducts;
  634.     }
  635.     /**
  636.      * @return object|null
  637.      */
  638.     public function getStockProductRoot(): ?object
  639.     {
  640.         return $this->stockProductRoot;
  641.     }
  642.     /**
  643.      * @param Context|null $context
  644.      * @return object|null
  645.      */
  646.     public function getStockProductRootContext(?Context $context null): ?object
  647.     {
  648.         if (!$this->context) {
  649.             $this->context $context ?: $this->contextService->getActualOrDefault();
  650.         } elseif ($context && $context != $this->context) {
  651.             $this->context $context;
  652.         }
  653.         return $this->getStockProductRoot() ?
  654.             $this->getStockProductRoot()->getStockProductRootContext($this->context) : null
  655.         ;
  656.     }
  657.     /**
  658.      * @param Uuid|null $warehouseId
  659.      * @return int
  660.      */
  661.     public function getStockProductsFinalQuantity(?Uuid $warehouseId null): int
  662.     {
  663.         $quantity 0;
  664.         if ($warehouseId) {
  665.             foreach ($this->getStockProducts($warehouseId) as $stock_product) {
  666.                 $quantity += $stock_product->getQuantityAvailable();
  667.             }
  668.         } else {
  669.             $quantity += $this->getStockProductRoot() ? $this->getStockProductRoot()->getQuantityAvailable() : 0;
  670.         }
  671.         return $quantity;
  672.     }
  673.     /**
  674.      * @param $stockProducts
  675.      * @return Declination
  676.      */
  677.     public function setStockProducts($stockProducts): self
  678.     {
  679.         $this->stockProducts $stockProducts;
  680.         return $this;
  681.     }
  682.     /**
  683.      * @return Declination|null
  684.      */
  685.     public function getVirtualParent(): ?Declination
  686.     {
  687.         return $this->virtualParent;
  688.     }
  689.     /**
  690.      * @param Declination|null $virtualParent
  691.      * @return Declination
  692.      */
  693.     public function setVirtualParent(?Declination $virtualParent): self
  694.     {
  695.         $this->virtualParent $virtualParent;
  696.         return $this;
  697.     }
  698.     /**
  699.      * @return int|null
  700.      */
  701.     public function getVirtualQuantity(): ?int
  702.     {
  703.         return $this->virtualQuantity;
  704.     }
  705.     /**
  706.      * @param int|null $virtualQuantity
  707.      * @return Declination
  708.      */
  709.     public function setVirtualQuantity(?int $virtualQuantity): self
  710.     {
  711.         $this->virtualQuantity $virtualQuantity;
  712.         return $this;
  713.     }
  714.     /**
  715.      * @return bool
  716.      */
  717.     public function isVirtual(): bool
  718.     {
  719.         return $this->virtualQuantity && $this->virtualParent;
  720.     }
  721.     /**
  722.      * @return string|null
  723.      */
  724.     public function getEnergyCode(): ?string
  725.     {
  726.         return $this->energyCode;
  727.     }
  728.     /**
  729.      * @param string|null $energyCode
  730.      * @return Declination
  731.      */
  732.     public function setEnergyCode(?string $energyCode): Declination
  733.     {
  734.         $this->energyCode $energyCode;
  735.         return $this;
  736.     }
  737.     /**
  738.      * @return bool|null
  739.      */
  740.     public function getIsPack(): ?bool
  741.     {
  742.         return count($this->getPackProductsWithParentDeclination()->getValues()) > 0;
  743.     }
  744.     /**
  745.      * @param Context|null $context
  746.      * @return Currency|null
  747.      */
  748.     public function getCurrency(?Context $context null): ?Currency
  749.     {
  750.         return $this->getProduct()->getCurrency($context);
  751.     }
  752.     /**
  753.      * @return TaxRule|null
  754.      */
  755.     public function getTaxRule(): ?TaxRule
  756.     {
  757.         return $this->getProduct()->getTaxRule();
  758.     }
  759.     /**
  760.      * @return void
  761.      */
  762.     public function removeContextFromEntity(): void
  763.     {
  764.         $this->context null;
  765.     }
  766. }