vendor/bluue/sales-bundle/src/Entity/OrderLine.php line 38

Open in your IDE?
  1. <?php
  2. /**
  3.  * @author Quentin CHATELAIN (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\SalesBundle\Entity;
  9. use DateTime;
  10. use App\Entity\TaxRule;
  11. use Symfony\Component\Uid\Uuid;
  12. use Doctrine\ORM\Mapping as ORM;
  13. use Gedmo\Mapping\Annotation as Gedmo;
  14. use Doctrine\Common\Collections\Collection;
  15. use Doctrine\Common\Collections\ArrayCollection;
  16. use Bluue\SalesBundle\Repository\OrderLineRepository;
  17. use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
  18. use App\DoctrineExtensions\Cancelable\Traits\UserCancelableEntity;
  19. use App\DoctrineExtensions\Timestampable\Traits\UserTimestampableEntity;
  20. use App\DoctrineExtensions\SoftDeleteable\Traits\UserSoftDeleteableEntity;
  21. use Bluue\ProductsBundle\Entity\Declination;
  22. use Bluue\ProductsBundle\Entity\Product;
  23. /**
  24.  * @ORM\Entity(repositoryClass=OrderLineRepository::class)
  25.  * @ORM\Table(name="sales_bundle__order_line", indexes={
  26.  *  @ORM\Index(name="deleted_at", columns={"deleted_at"}),
  27.  *  @ORM\Index(name="created_at", columns={"created_at"}),
  28.  *  @ORM\Index(name="updated_at", columns={"updated_at"}),
  29.  *  @ORM\Index(name="canceled_at", columns={"canceled_at"})
  30.  * })
  31.  * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true)
  32.  */
  33. class OrderLine
  34. {
  35.     use UserTimestampableEntity;
  36.     use UserSoftDeleteableEntity;
  37.     use UserCancelableEntity;
  38.     /**
  39.      * @ORM\Id
  40.      * @ORM\Column(type="uuid")
  41.      * @ORM\GeneratedValue(strategy="CUSTOM")
  42.      * @ORM\CustomIdGenerator(class=UuidGenerator::class)
  43.      */
  44.     private ?Uuid $id null;
  45.     /**
  46.      * @ORM\ManyToOne(targetEntity=Order::class, inversedBy="lines")
  47.      * @ORM\JoinColumn(nullable=false)
  48.      */
  49.     private ?Order $order null;
  50.     /**
  51.      * @ORM\ManyToOne(targetEntity=LineType::class)
  52.      */
  53.     private ?LineType $line_type null;
  54.     /**
  55.      * @ORM\ManyToOne(targetEntity=TaxRule::class)
  56.      */
  57.     private ?TaxRule $tax_rule null;
  58.     /**
  59.      * @ORM\ManyToOne(targetEntity="OrderLine", inversedBy="childrens")
  60.      * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
  61.      */
  62.     private ?OrderLine $parent null;
  63.     /**
  64.      * @ORM\Column(type="boolean")
  65.      */
  66.     private bool $is_group false;
  67.     /**
  68.      * @ORM\ManyToOne(targetEntity="OrderLine", inversedBy="packChildrens")
  69.      * @ORM\JoinColumn(name="pack_parent_id", referencedColumnName="id")
  70.      */
  71.     private ?OrderLine $packParent null;
  72.     /**
  73.      * @ORM\Column(type="boolean")
  74.      */
  75.     private bool $is_pack false;
  76.     /**
  77.      * @ORM\Column(type="string", length=128, nullable="true")
  78.      */
  79.     private ?string $reference null;
  80.     /**
  81.      * @ORM\Column(type="string", length=128, nullable="true")
  82.      */
  83.     private ?string $referenceBrand null;
  84.     /**
  85.      * @ORM\Column(type="string", length=255, nullable="true")
  86.      */
  87.     private ?string $name null;
  88.     /**
  89.      * @ORM\Column(type="text", nullable="true")
  90.      */
  91.     private ?string $description null;
  92.     /**
  93.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  94.      */
  95.     private ?string $unit_price null;
  96.     /**
  97.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  98.      */
  99.     private ?string $unitPriceWithTax null;
  100.     /**
  101.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  102.      */
  103.     private ?string $quantity null;
  104.     /**
  105.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  106.      */
  107.     private ?string $quantity_delivered null;
  108.     /**
  109.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  110.      */
  111.     private ?string $wholesale_price null;
  112.     /**
  113.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  114.      */
  115.     private ?string $margin_ratio null;
  116.     /**
  117.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  118.      */
  119.     private ?string $percentage_discount_untaxed null;
  120.     /**
  121.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  122.      */
  123.     private ?string $total_discount_untaxed null;
  124.     /**
  125.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  126.      */
  127.     private ?string $totalDiscount null;
  128.     /**
  129.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  130.      */
  131.     private ?string $total_amount_no_discount_untaxed null;
  132.     /**
  133.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  134.      */
  135.     private ?string $totalAmountNoDiscount null;
  136.     /**
  137.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  138.      */
  139.     private ?string $total_amount_untaxed null;
  140.     /**
  141.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  142.      */
  143.     private ?string $total_tax_amount null;
  144.     /**
  145.      * @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
  146.      */
  147.     private ?string $total_amount null;
  148.     /**
  149.      * @ORM\Column(type="integer")
  150.      */
  151.     private ?int $position null;
  152.     /**
  153.      * @ORM\Column(type="json")
  154.      */
  155.     private array $options = [];
  156.     /**
  157.      * @ORM\OneToMany(targetEntity="OrderLine", mappedBy="parent", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
  158.      * @ORM\OrderBy({"position" = "ASC"})
  159.      */
  160.     private Collection $childrens;
  161.     /**
  162.      * @ORM\OneToMany(
  163.      *      targetEntity="OrderLine",
  164.      *      mappedBy="packParent",
  165.      *      cascade={"persist", "remove"},
  166.      *      fetch="EXTRA_LAZY"
  167.      * )
  168.      * @ORM\OrderBy({"position" = "ASC"})
  169.      */
  170.     private Collection $packChildrens;
  171.     private $stockOrderLine;
  172.     private bool $stockReserved false;
  173.     /**
  174.      * @ORM\ManyToOne(targetEntity=Product::class)
  175.      */
  176.     private ?Product $product null;
  177.     /**
  178.      * @ORM\ManyToOne(targetEntity=Declination::class)
  179.      */
  180.     private ?Declination $declination null;
  181.     public function __construct()
  182.     {
  183.         $this->childrens = new ArrayCollection();
  184.         $this->packChildrens = new ArrayCollection();
  185.     }
  186.     /**
  187.      * @return Uuid|null
  188.      */
  189.     public function getId(): ?Uuid
  190.     {
  191.         return $this->id;
  192.     }
  193.     /**
  194.      * @return OrderLine
  195.      */
  196.     public function setId(): self
  197.     {
  198.         $this->id null;
  199.         return $this;
  200.     }
  201.     /**
  202.      * @return Order|null
  203.      */
  204.     public function getOrder(): ?Order
  205.     {
  206.         return $this->order;
  207.     }
  208.     /**
  209.      * @param Order $order
  210.      * @return OrderLine
  211.      */
  212.     public function setOrder(Order $order): self
  213.     {
  214.         $this->order $order;
  215.         return $this;
  216.     }
  217.     /**
  218.      * @return LineType|null
  219.      */
  220.     public function getLineType(): ?LineType
  221.     {
  222.         return $this->line_type;
  223.     }
  224.     /**
  225.      * @param LineType|null $line_type
  226.      * @return OrderLine
  227.      */
  228.     public function setLineType(?LineType $line_type): self
  229.     {
  230.         $this->line_type $line_type;
  231.         return $this;
  232.     }
  233.     /**
  234.      * @return TaxRule|null
  235.      */
  236.     public function getTaxRule(): ?TaxRule
  237.     {
  238.         return $this->tax_rule;
  239.     }
  240.     /**
  241.      * @param TaxRule|null $tax_rule
  242.      * @return OrderLine
  243.      */
  244.     public function setTaxRule(?TaxRule $tax_rule): self
  245.     {
  246.         $this->tax_rule $tax_rule;
  247.         return $this;
  248.     }
  249.     /**
  250.      * @return OrderLine|null
  251.      */
  252.     public function getParent(): ?OrderLine
  253.     {
  254.         return $this->parent;
  255.     }
  256.     /**
  257.      * @param OrderLine|null $parent
  258.      * @return OrderLine
  259.      */
  260.     public function setParent(?OrderLine $parent): self
  261.     {
  262.         $this->parent $parent;
  263.         return $this;
  264.     }
  265.     /**
  266.      * @return bool
  267.      */
  268.     public function getIsGroup(): bool
  269.     {
  270.         return $this->is_group;
  271.     }
  272.     /**
  273.      * @param bool $is_group
  274.      * @return OrderLine
  275.      */
  276.     public function setIsGroup(bool $is_group): self
  277.     {
  278.         $this->is_group $is_group;
  279.         return $this;
  280.     }
  281.     /**
  282.      * @return OrderLine|null
  283.      */
  284.     public function getPackParent(): ?OrderLine
  285.     {
  286.         return $this->packParent;
  287.     }
  288.     /**
  289.      * @param OrderLine|null $packParent
  290.      * @return OrderLine
  291.      */
  292.     public function setPackParent(?OrderLine $packParent): self
  293.     {
  294.         $this->packParent $packParent;
  295.         return $this;
  296.     }
  297.     /**
  298.      * @return bool
  299.      */
  300.     public function getIsPack(): bool
  301.     {
  302.         return $this->is_pack;
  303.     }
  304.     /**
  305.      * @param bool $is_pack
  306.      * @return OrderLine
  307.      */
  308.     public function setIsPack(bool $is_pack): self
  309.     {
  310.         $this->is_pack $is_pack;
  311.         return $this;
  312.     }
  313.     /**
  314.      * @return string|null
  315.      */
  316.     public function getReference(): ?string
  317.     {
  318.         return $this->reference;
  319.     }
  320.     /**
  321.      * @param string|null $reference
  322.      * @return OrderLine
  323.      */
  324.     public function setReference(?string $reference): self
  325.     {
  326.         $this->reference $reference;
  327.         return $this;
  328.     }
  329.     /**
  330.      * @return string|null
  331.      */
  332.     public function getReferenceBrand(): ?string
  333.     {
  334.         return $this->referenceBrand;
  335.     }
  336.     /**
  337.      * @param string|null $referenceBrand
  338.      * @return OrderLine
  339.      */
  340.     public function setReferenceBrand(?string $referenceBrand): self
  341.     {
  342.         $this->referenceBrand $referenceBrand;
  343.         return $this;
  344.     }
  345.     /**
  346.      * @return string|null
  347.      */
  348.     public function getName(): ?string
  349.     {
  350.         return $this->name;
  351.     }
  352.     /**
  353.      * @param string|null $name
  354.      * @return OrderLine
  355.      */
  356.     public function setName(?string $name): self
  357.     {
  358.         $this->name $name;
  359.         return $this;
  360.     }
  361.     /**
  362.      * @return string|null
  363.      */
  364.     public function getDescription(): ?string
  365.     {
  366.         return $this->description;
  367.     }
  368.     /**
  369.      * @param string|null $description
  370.      * @return OrderLine
  371.      */
  372.     public function setDescription(?string $description): self
  373.     {
  374.         $this->description $description;
  375.         return $this;
  376.     }
  377.     /**
  378.      * @return string|null
  379.      */
  380.     public function getUnitPrice(): ?string
  381.     {
  382.         return $this->unit_price;
  383.     }
  384.     /**
  385.      * @param string|null $unit_price
  386.      * @return OrderLine
  387.      */
  388.     public function setUnitPrice(?string $unit_price): self
  389.     {
  390.         $this->unit_price $unit_price;
  391.         return $this;
  392.     }
  393.     /**
  394.      * @return string|null
  395.      */
  396.     public function getUnitPriceWithTax(): ?string
  397.     {
  398.         return $this->unitPriceWithTax;
  399.     }
  400.     /**
  401.      * @param string|null $unitPriceWithTax
  402.      * @return OrderLine
  403.      */
  404.     public function setUnitPriceWithTax(?string $unitPriceWithTax): OrderLine
  405.     {
  406.         $this->unitPriceWithTax $unitPriceWithTax;
  407.         return $this;
  408.     }
  409.     /**
  410.      * @return string|null
  411.      */
  412.     public function getQuantity(): ?string
  413.     {
  414.         return $this->quantity;
  415.     }
  416.     /**
  417.      * @param string|null $quantity
  418.      * @return OrderLine
  419.      */
  420.     public function setQuantity(?string $quantity): self
  421.     {
  422.         $this->quantity $quantity;
  423.         return $this;
  424.     }
  425.     /**
  426.      * @return string|null
  427.      */
  428.     public function getQuantityDelivered(): ?string
  429.     {
  430.         return $this->quantity_delivered;
  431.     }
  432.     /**
  433.      * @param string|null $quantity_delivered
  434.      * @return OrderLine
  435.      */
  436.     public function setQuantityDelivered(?string $quantity_delivered): self
  437.     {
  438.         $this->quantity_delivered $quantity_delivered;
  439.         return $this;
  440.     }
  441.     /**
  442.      * @param bool $virtual
  443.      * @return string|null
  444.      */
  445.     public function getRemainingQuantity(bool $virtual false): ?string
  446.     {
  447.         if ($this->isCanceled()) {
  448.             return '0';
  449.         }
  450.         $quantity = (int) $this->quantity - (int) $this->quantity_delivered;
  451.         if ($virtual && !empty($this->options['product']['virtual_quantity'])) {
  452.             return (string) ($quantity $this->options['product']['virtual_quantity']);
  453.         } else {
  454.             return (string) $quantity;
  455.         }
  456.     }
  457.     /**
  458.      * @return string|null
  459.      */
  460.     public function getWholesalePrice(): ?string
  461.     {
  462.         return $this->wholesale_price;
  463.     }
  464.     /**
  465.      * @param string|null $wholesale_price
  466.      * @return OrderLine
  467.      */
  468.     public function setWholesalePrice(?string $wholesale_price): self
  469.     {
  470.         $this->wholesale_price $wholesale_price;
  471.         return $this;
  472.     }
  473.     /**
  474.      * @return string|null
  475.      */
  476.     public function getMarginRatio(): ?string
  477.     {
  478.         return $this->margin_ratio;
  479.     }
  480.     /**
  481.      * @param string|null $margin_ratio
  482.      * @return OrderLine
  483.      */
  484.     public function setMarginRatio(?string $margin_ratio): self
  485.     {
  486.         $this->margin_ratio $margin_ratio;
  487.         return $this;
  488.     }
  489.     /**
  490.      * @param bool $calcWithPackaging
  491.      * @return float|null
  492.      */
  493.     public function getTotalMargin(bool $calcWithPackaging false): ?float
  494.     {
  495.         if ($this->wholesale_price === null) {
  496.             return 0;
  497.         }
  498.         if ($calcWithPackaging && !empty($this->options['unitQuantity'])) {
  499.             $quantity = (float) $this->options['unitQuantity'];
  500.         } else {
  501.             $quantity $this->isCanceled() ? (int) $this->quantity_delivered : (int) $this->quantity;
  502.         }
  503.         $sellPrice = (float) $this->total_amount_untaxed;
  504.         if (!empty($this->options['ecoPart']) && !empty($this->options['ecoPart']['amount'])) {
  505.             $sellPrice -= $this->options['ecoPart']['amount']  * $quantity;
  506.         }
  507.         return $sellPrice - (float) $this->wholesale_price $quantity;
  508.     }
  509.     /**
  510.      * @return string|null
  511.      */
  512.     public function getPercentageDiscountUntaxed(): ?string
  513.     {
  514.         return $this->percentage_discount_untaxed;
  515.     }
  516.     /**
  517.      * @param string|null $percentage_discount_untaxed
  518.      * @return OrderLine
  519.      */
  520.     public function setPercentageDiscountUntaxed(?string $percentage_discount_untaxed): self
  521.     {
  522.         $this->percentage_discount_untaxed $percentage_discount_untaxed;
  523.         return $this;
  524.     }
  525.     /**
  526.      * @return string|null
  527.      */
  528.     public function getTotalDiscountUntaxed(): ?string
  529.     {
  530.         return $this->total_discount_untaxed;
  531.     }
  532.     /**
  533.      * @param string|null $total_discount_untaxed
  534.      * @return OrderLine
  535.      */
  536.     public function setTotalDiscountUntaxed(?string $total_discount_untaxed): self
  537.     {
  538.         $this->total_discount_untaxed $total_discount_untaxed;
  539.         return $this;
  540.     }
  541.     /**
  542.      * @return string|null
  543.      */
  544.     public function getTotalDiscount(): ?string
  545.     {
  546.         return $this->totalDiscount;
  547.     }
  548.     /**
  549.      * @param string|null $totalDiscount
  550.      * @return OrderLine
  551.      */
  552.     public function setTotalDiscount(?string $totalDiscount): OrderLine
  553.     {
  554.         $this->totalDiscount $totalDiscount;
  555.         return $this;
  556.     }
  557.     /**
  558.      * @return string|null
  559.      */
  560.     public function getTotalAmountNoDiscountUntaxed(): ?string
  561.     {
  562.         return $this->total_amount_no_discount_untaxed;
  563.     }
  564.     /**
  565.      * @param string|null $total_amount_no_discount_untaxed
  566.      * @return OrderLine
  567.      */
  568.     public function setTotalAmountNoDiscountUntaxed(?string $total_amount_no_discount_untaxed): self
  569.     {
  570.         $this->total_amount_no_discount_untaxed $total_amount_no_discount_untaxed;
  571.         return $this;
  572.     }
  573.     /**
  574.      * @return string|null
  575.      */
  576.     public function getTotalAmountNoDiscount(): ?string
  577.     {
  578.         return $this->totalAmountNoDiscount;
  579.     }
  580.     /**
  581.      * @param string|null $totalAmountNoDiscount
  582.      * @return OrderLine
  583.      */
  584.     public function setTotalAmountNoDiscount(?string $totalAmountNoDiscount): OrderLine
  585.     {
  586.         $this->totalAmountNoDiscount $totalAmountNoDiscount;
  587.         return $this;
  588.     }
  589.     /**
  590.      * @return string|null
  591.      */
  592.     public function getTotalAmountUntaxed(): ?string
  593.     {
  594.         return $this->total_amount_untaxed;
  595.     }
  596.     /**
  597.      * @param string|null $total_amount_untaxed
  598.      * @return OrderLine
  599.      */
  600.     public function setTotalAmountUntaxed(?string $total_amount_untaxed): self
  601.     {
  602.         $this->total_amount_untaxed $total_amount_untaxed;
  603.         return $this;
  604.     }
  605.     /**
  606.      * @return string|null
  607.      */
  608.     public function getTotalTaxAmount(): ?string
  609.     {
  610.         return $this->total_tax_amount;
  611.     }
  612.     /**
  613.      * @param string|null $total_tax_amount
  614.      * @return OrderLine
  615.      */
  616.     public function setTotalTaxAmount(?string $total_tax_amount): self
  617.     {
  618.         $this->total_tax_amount $total_tax_amount;
  619.         return $this;
  620.     }
  621.     /**
  622.      * @return string|null
  623.      */
  624.     public function getTotalAmount(): ?string
  625.     {
  626.         return $this->total_amount;
  627.     }
  628.     /**
  629.      * @param string|null $total_amount
  630.      * @return OrderLine
  631.      */
  632.     public function setTotalAmount(?string $total_amount): self
  633.     {
  634.         $this->total_amount $total_amount;
  635.         return $this;
  636.     }
  637.     /**
  638.      * @return int|null
  639.      */
  640.     public function getPosition(): ?int
  641.     {
  642.         return $this->position;
  643.     }
  644.     /**
  645.      * @param int|null $position
  646.      * @return OrderLine
  647.      */
  648.     public function setPosition(?int $position): self
  649.     {
  650.         $this->position $position;
  651.         return $this;
  652.     }
  653.     /**
  654.      * @return array
  655.      */
  656.     public function getOptions(): array
  657.     {
  658.         return $this->options;
  659.     }
  660.     /**
  661.      * @param array $options
  662.      * @return OrderLine
  663.      */
  664.     public function setOptions(array $options): self
  665.     {
  666.         $this->options $options;
  667.         return $this;
  668.     }
  669.     /**
  670.      * @param array $options
  671.      * @return OrderLine
  672.      */
  673.     public function addOptions(array $options): self
  674.     {
  675.         return $this->setOptions(array_merge($this->options$options));
  676.     }
  677.     /**
  678.      * @return Collection|OrderLine[]
  679.      */
  680.     public function getChildrens(): Collection
  681.     {
  682.         return $this->childrens;
  683.     }
  684.     /**
  685.      * @param OrderLine $line
  686.      * @return OrderLine
  687.      */
  688.     public function addChildren(OrderLine $line): self
  689.     {
  690.         if (!$this->childrens->contains($line)) {
  691.             $this->childrens[] = $line;
  692.             $line->setParent($this);
  693.             if ($line->getOrder() !== $this->getOrder()) {
  694.                 $line->setOrder($this->getOrder());
  695.             }
  696.         }
  697.         return $this;
  698.     }
  699.     /**
  700.      * @return Collection|OrderLine[]
  701.      */
  702.     public function getPackChildrens(): Collection
  703.     {
  704.         return $this->packChildrens;
  705.     }
  706.     /**
  707.      * @param OrderLine $line
  708.      * @return $this
  709.      */
  710.     public function addPackChildren(OrderLine $line): self
  711.     {
  712.         if (!$this->packChildrens->contains($line)) {
  713.             $this->packChildrens[] = $line;
  714.             $line->setPackParent($this);
  715.             if ($line->getOrder() !== $this->getOrder()) {
  716.                 $line->setOrder($this->getOrder());
  717.             }
  718.         }
  719.         return $this;
  720.     }
  721.     /**
  722.      * @return Order|null
  723.      */
  724.     public function getDocument(): ?Order
  725.     {
  726.         return $this->getOrder();
  727.     }
  728.     /**
  729.      * @param Order $order
  730.      * @return OrderLine
  731.      */
  732.     public function duplicate(Order $order): OrderLine
  733.     {
  734.         if ($this->id) {
  735.             $clone = clone $this;
  736.             $clone->setId();
  737.             $clone->setOrder($order);
  738.             $clone->setQuantityDelivered(null);
  739.             $clone->setCreatedAt(new DateTime());
  740.             $clone->setCreatedBy(null);
  741.             $clone->setUpdatedAt(new DateTime());
  742.             $clone->setUpdatedBy(null);
  743.             $clone->childrens = new ArrayCollection();
  744.             foreach ($this->getChildrens() as $children) {
  745.                 $clone_children $children->duplicate($order);
  746.                 $clone->addChildren($clone_children);
  747.                 $children->packChildrens = new ArrayCollection();
  748.                 foreach ($children->getPackChildrens() as $packChildren) {
  749.                     $clone_pack_children $packChildren->duplicate($order);
  750.                     $children->addPackChildren($clone_pack_children);
  751.                 }
  752.             }
  753.             $clone->packChildrens = new ArrayCollection();
  754.             foreach ($this->getPackChildrens() as $packChildren) {
  755.                 $clone_pack_children $packChildren->duplicate($order);
  756.                 $clone->addPackChildren($clone_pack_children);
  757.             }
  758.             return $clone;
  759.         }
  760.         return $this;
  761.     }
  762.     /**
  763.      * @return false|string
  764.      */
  765.     public function getProductOptionUniqueKey()
  766.     {
  767.         if ($this->hasProductLinked()) {
  768.             return $this->options['product']['id']
  769.                 . ($this->hasDeclinationLinked() ? $this->options['product']['declination_id'] : '');
  770.         }
  771.         return false;
  772.     }
  773.     /**
  774.      * @return bool
  775.      */
  776.     public function isProduct(): bool
  777.     {
  778.         $options $this->getOptions();
  779.         return !empty($options['product']) && !empty($options['product']['id']);
  780.     }
  781.     /**
  782.      * @return bool
  783.      */
  784.     public function isDeclination(): bool
  785.     {
  786.         return $this->isProduct() && !empty($this->getOptions()['product']['declination_id']);
  787.     }
  788.     /**
  789.      * @return bool
  790.      */
  791.     public function hasProductLinked(): bool
  792.     {
  793.         if (!empty($this->options['product']) && !empty($this->options['product']['id'])) {
  794.             return true;
  795.         }
  796.         return false;
  797.     }
  798.     /**
  799.      * @return bool
  800.      */
  801.     public function hasDeclinationLinked(): bool
  802.     {
  803.         if (!empty($this->options['product']) && !empty($this->options['product']['declination_id'])) {
  804.             return true;
  805.         }
  806.         return false;
  807.     }
  808.     /**
  809.      * @return mixed|null
  810.      */
  811.     public function getProductId()
  812.     {
  813.         if ($this->hasProductLinked()) {
  814.             return $this->options['product']['id'];
  815.         } else {
  816.             return null;
  817.         }
  818.     }
  819.     /**
  820.      * @return mixed|null
  821.      */
  822.     public function getDeclinationId()
  823.     {
  824.         if ($this->hasDeclinationLinked()) {
  825.             return $this->options['product']['declination_id'];
  826.         } else {
  827.             return null;
  828.         }
  829.     }
  830.     /**
  831.      * @return mixed|null
  832.      */
  833.     public function getElementId()
  834.     {
  835.         if ($this->hasDeclinationLinked()) {
  836.             return $this->options['product']['declination_id'];
  837.         } elseif ($this->hasProductLinked()) {
  838.             return $this->options['product']['id'];
  839.         } else {
  840.             return null;
  841.         }
  842.     }
  843.     /**
  844.      * @return mixed
  845.      */
  846.     public function getStockOrderLine()
  847.     {
  848.         return $this->stockOrderLine;
  849.     }
  850.     public function setStockOrderLine($stockOrderLine): self
  851.     {
  852.         $this->stockOrderLine $stockOrderLine;
  853.         return $this;
  854.     }
  855.     /**
  856.      * @return bool
  857.      */
  858.     public function isStockReserved(): bool
  859.     {
  860.         return $this->stockReserved;
  861.     }
  862.     /**
  863.      * @param bool $stockReserved
  864.      * @return OrderLine
  865.      */
  866.     public function setStockReserved(bool $stockReserved): OrderLine
  867.     {
  868.         $this->stockReserved $stockReserved;
  869.         return $this;
  870.     }
  871.     /**
  872.      * @return bool
  873.      */
  874.     public function isCancelable(): bool
  875.     {
  876.         return $this->getRemainingQuantity() > && !$this->isCanceled();
  877.     }
  878.     /**
  879.      * @return string|null
  880.      */
  881.     public function getUnitPriceWithDiscount(): ?string
  882.     {
  883.         if ($this->getDocument()->isEditPricesWithTax()) {
  884.             $unitDiscount = (float) ($this->getOptions()['unitDiscount'] ?? 0);
  885.             return (string) ((float) $this->getUnitPriceWithTax() - $unitDiscount);
  886.         } else {
  887.             $unitDiscountUntaxed = (float) ($this->getOptions()['unitDiscountUntaxed'] ?? 0);
  888.             return (string) ((float) $this->getUnitPrice() - $unitDiscountUntaxed);
  889.         }
  890.     }
  891.     /**
  892.      * @return Product|null
  893.      */
  894.     public function getProduct(): ?Product
  895.     {
  896.         return $this->product;
  897.     }
  898.     /**
  899.      * @param Product|null $Product
  900.      * @return $this
  901.      */
  902.     public function setProduct(?Product $Product): self
  903.     {
  904.         $this->product $Product;
  905.         return $this;
  906.     }
  907.     /**
  908.      * @return Declination|null
  909.      */
  910.     public function getDeclination(): ?Declination
  911.     {
  912.         return $this->declination;
  913.     }
  914.     /**
  915.      * @param Declination|null $declination
  916.      * @return $this
  917.      */
  918.     public function setDeclination(?Declination $declination): self
  919.     {
  920.         $this->declination $declination;
  921.         return $this;
  922.     }
  923. }