vendor/bluue/sales-bundle/src/Entity/Quotation.php line 52

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