<?php
/**
* @author Quentin CHATELAIN (contact@scaledev.fr)
* @copyright 2021 - ScaleDEV SAS, 12 RUE CHARLES MORET, 10120 ST ANDRE LES VERGERS
* @license commercial
*/
declare(strict_types=1);
namespace Bluue\SalesBundle\Entity;
use App\Entity\Traits\EntityManagerServiceEntity;
use App\Services\SoftdeleteFilter;
use DateTime;
use App\Entity\TaxRule;
use Doctrine\ORM\NonUniqueResultException;
use Symfony\Component\Uid\Uuid;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
use Bluue\SalesBundle\Repository\CreditNoteLineRepository;
use App\DoctrineExtensions\Timestampable\Traits\UserTimestampableEntity;
use App\DoctrineExtensions\SoftDeleteable\Traits\UserSoftDeleteableEntity;
use Bluue\ProductsBundle\Entity\Declination;
use Bluue\ProductsBundle\Entity\Product;
/**
* @ORM\Entity(repositoryClass=CreditNoteLineRepository::class)
* @ORM\Table(name="sales_bundle__credit_note_line", indexes={
* @ORM\Index(name="deleted_at", columns={"deleted_at"}),
* @ORM\Index(name="created_at", columns={"created_at"}),
* @ORM\Index(name="updated_at", columns={"updated_at"})
* })
* @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=false)
*/
class CreditNoteLine
{
use UserTimestampableEntity;
use UserSoftDeleteableEntity;
use EntityManagerServiceEntity;
/**
* @ORM\Id
* @ORM\Column(type="uuid")
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class=UuidGenerator::class)
*/
private ?Uuid $id = null;
/**
* @ORM\ManyToOne(targetEntity=CreditNote::class, inversedBy="lines")
* @ORM\JoinColumn(nullable=false)
*/
private ?CreditNote $credit_note = null;
/**
* @ORM\ManyToOne(targetEntity=LineType::class)
*/
private ?LineType $line_type = null;
/**
* @ORM\ManyToOne(targetEntity=TaxRule::class)
*/
private ?TaxRule $tax_rule = null;
/**
* @ORM\ManyToOne(targetEntity="CreditNoteLine", inversedBy="childrens")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
*/
private ?CreditNoteLine $parent = null;
/**
* @ORM\Column(type="boolean")
*/
private bool $is_group = false;
/**
* @ORM\ManyToOne(targetEntity="CreditNoteLine", inversedBy="packChildrens")
* @ORM\JoinColumn(name="pack_parent_id", referencedColumnName="id")
*/
private ?CreditNoteLine $packParent = null;
/**
* @ORM\Column(type="boolean")
*/
private bool $is_pack = false;
/**
* @ORM\Column(type="string", length=128, nullable="true")
*/
private ?string $reference = null;
/**
* @ORM\Column(type="string", length=128, nullable="true")
*/
private ?string $referenceBrand = null;
/**
* @ORM\Column(type="string", length=255, nullable="true")
*/
private ?string $name = null;
/**
* @ORM\Column(type="text", nullable="true")
*/
private ?string $description = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $unit_price = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $unitPriceWithTax = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $quantity = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $wholesale_price = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $margin_ratio = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $total_amount_untaxed = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $total_tax_amount = null;
/**
* @ORM\Column(type="decimal", precision=20, scale=6, nullable="true")
*/
private ?string $total_amount = null;
/**
* @ORM\Column(type="integer")
*/
private ?int $position = null;
/**
* @ORM\Column(type="json")
*/
private array $options = [];
/**
* @ORM\OneToMany(
* targetEntity="CreditNoteLine",
* mappedBy="parent",
* cascade={"persist", "remove"},
* fetch="EXTRA_LAZY"
* )
* @ORM\OrderBy({"position" = "ASC"})
*/
private Collection $childrens;
/**
* @ORM\OneToMany(
* targetEntity="CreditNoteLine",
* mappedBy="packParent",
* cascade={"persist", "remove"},
* fetch="EXTRA_LAZY"
* )
* @ORM\OrderBy({"position" = "ASC"})
*/
private Collection $packChildrens;
/**
* @ORM\ManyToOne(targetEntity=Product::class)
*/
private ?Product $product = null;
/**
* @ORM\ManyToOne(targetEntity=Declination::class)
*/
private ?Declination $declination = null;
public function __construct()
{
$this->childrens = new ArrayCollection();
$this->packChildrens = new ArrayCollection();
}
/**
* @return Uuid|null
*/
public function getId(): ?Uuid
{
return $this->id;
}
/**
* @return CreditNoteLine
*/
public function setId(): self
{
$this->id = null;
return $this;
}
/**
* @return CreditNote|null
*/
public function getCreditNote(): ?CreditNote
{
return $this->credit_note;
}
/**
* @param CreditNote $credit_note
* @return CreditNoteLine
*/
public function setCreditNote(CreditNote $credit_note): self
{
$this->credit_note = $credit_note;
return $this;
}
/**
* @return LineType|null
*/
public function getLineType(): ?LineType
{
return $this->line_type;
}
/**
* @param LineType|null $line_type
* @return CreditNoteLine
*/
public function setLineType(?LineType $line_type): self
{
$this->line_type = $line_type;
return $this;
}
/**
* @return TaxRule|null
* @throws NonUniqueResultException
*/
public function getTaxRule(): ?TaxRule
{
if ($this->em && $this->tax_rule) {
SoftdeleteFilter::disable($this->em, [TaxRule::class]);
$taxRule = $this->em->getRepository(TaxRule::class)
->createQueryBuilder('tr')
->where('tr.id = :taxRuleId')
->setParameter('taxRuleId', $this->tax_rule->getId()->toBinary())
->getQuery()
->getOneOrNullResult();
SoftdeleteFilter::enable($this->em, [TaxRule::class]);
return $taxRule;
}
return $this->tax_rule;
}
/**
* @param TaxRule|null $tax_rule
* @return CreditNoteLine
*/
public function setTaxRule(?TaxRule $tax_rule): self
{
$this->tax_rule = $tax_rule;
return $this;
}
/**
* @return CreditNoteLine|null
*/
public function getParent(): ?CreditNoteLine
{
return $this->parent;
}
/**
* @param CreditNoteLine|null $parent
* @return CreditNoteLine
*/
public function setParent(?CreditNoteLine $parent): self
{
$this->parent = $parent;
return $this;
}
/**
* @return bool
*/
public function getIsGroup(): bool
{
return $this->is_group;
}
/**
* @param bool $is_group
* @return CreditNoteLine
*/
public function setIsGroup(bool $is_group): self
{
$this->is_group = $is_group;
return $this;
}
/**
* @return CreditNoteLine|null
*/
public function getPackParent(): ?CreditNoteLine
{
return $this->packParent;
}
/**
* @param CreditNoteLine|null $packParent
* @return CreditNoteLine
*/
public function setPackParent(?CreditNoteLine $packParent): self
{
$this->packParent = $packParent;
return $this;
}
/**
* @return bool
*/
public function getIsPack(): bool
{
return $this->is_pack;
}
/**
* @param bool $is_pack
* @return CreditNoteLine
*/
public function setIsPack(bool $is_pack): self
{
$this->is_pack = $is_pack;
return $this;
}
/**
* @return string|null
*/
public function getReference(): ?string
{
return $this->reference;
}
/**
* @param string|null $reference
* @return CreditNoteLine
*/
public function setReference(?string $reference): self
{
$this->reference = $reference;
return $this;
}
/**
* @return string|null
*/
public function getReferenceBrand(): ?string
{
return $this->referenceBrand;
}
/**
* @param string|null $referenceBrand
* @return CreditNoteLine
*/
public function setReferenceBrand(?string $referenceBrand): self
{
$this->referenceBrand = $referenceBrand;
return $this;
}
/**
* @return string|null
*/
public function getName(): ?string
{
return $this->name;
}
/**
* @param string|null $name
* @return CreditNoteLine
*/
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
/**
* @return string|null
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* @param string|null $description
* @return CreditNoteLine
*/
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
/**
* @return string|null
*/
public function getUnitPrice(): ?string
{
return $this->unit_price;
}
/**
* @param string|null $unit_price
* @return CreditNoteLine
*/
public function setUnitPrice(?string $unit_price): self
{
$this->unit_price = $unit_price;
return $this;
}
/**
* @return string|null
*/
public function getUnitPriceWithTax(): ?string
{
return $this->unitPriceWithTax;
}
/**
* @param string|null $unitPriceWithTax
* @return CreditNoteLine
*/
public function setUnitPriceWithTax(?string $unitPriceWithTax): CreditNoteLine
{
$this->unitPriceWithTax = $unitPriceWithTax;
return $this;
}
/**
* @return string|null
*/
public function getQuantity(): ?string
{
return $this->quantity;
}
/**
* @param string|null $quantity
* @return CreditNoteLine
*/
public function setQuantity(?string $quantity): self
{
$this->quantity = $quantity;
return $this;
}
/**
* @return string|null
*/
public function getWholesalePrice(): ?string
{
return $this->wholesale_price;
}
/**
* @param string|null $wholesale_price
* @return CreditNoteLine
*/
public function setWholesalePrice(?string $wholesale_price): self
{
$this->wholesale_price = $wholesale_price;
return $this;
}
/**
* @return string|null
*/
public function getMarginRatio(): ?string
{
return $this->margin_ratio;
}
/**
* @param string|null $margin_ratio
* @return CreditNoteLine
*/
public function setMarginRatio(?string $margin_ratio): self
{
$this->margin_ratio = $margin_ratio;
return $this;
}
/**
* @param bool $calcWithPackaging
* @return float|null
*/
public function getTotalMargin(bool $calcWithPackaging = false): ?float
{
if ($this->wholesale_price === null) {
return 0;
}
if ($calcWithPackaging && !empty($this->options['unitQuantity'])) {
$quantity = (float) $this->options['unitQuantity'];
} else {
$quantity = (int) $this->quantity;
}
$sellPrice = (float) $this->total_amount_untaxed;
if (!empty($this->options['ecoPart']) && !empty($this->options['ecoPart']['amount'])) {
$sellPrice -= $this->options['ecoPart']['amount'] * $quantity;
}
return $sellPrice - (float) $this->wholesale_price * $quantity;
}
/**
* @return string|null
*/
public function getTotalAmountUntaxed(): ?string
{
return $this->total_amount_untaxed;
}
/**
* @param string|null $total_amount_untaxed
* @return CreditNoteLine
*/
public function setTotalAmountUntaxed(?string $total_amount_untaxed): self
{
$this->total_amount_untaxed = $total_amount_untaxed;
return $this;
}
/**
* @return string|null
*/
public function getTotalTaxAmount(): ?string
{
return $this->total_tax_amount;
}
/**
* @param string|null $total_tax_amount
* @return CreditNoteLine
*/
public function setTotalTaxAmount(?string $total_tax_amount): self
{
$this->total_tax_amount = $total_tax_amount;
return $this;
}
/**
* @return string|null
*/
public function getTotalAmount(): ?string
{
return $this->total_amount;
}
/**
* @param string|null $total_amount
* @return CreditNoteLine
*/
public function setTotalAmount(?string $total_amount): self
{
$this->total_amount = $total_amount;
return $this;
}
/**
* @return int|null
*/
public function getPosition(): ?int
{
return $this->position;
}
/**
* @param int|null $position
* @return CreditNoteLine
*/
public function setPosition(?int $position): self
{
$this->position = $position;
return $this;
}
/**
* @return array
*/
public function getOptions(): array
{
return $this->options;
}
/**
* @param array $options
* @return CreditNoteLine
*/
public function setOptions(array $options): self
{
$this->options = $options;
return $this;
}
/**
* @param array $options
* @return CreditNoteLine
*/
public function addOptions(array $options): self
{
return $this->setOptions(array_merge($this->options, $options));
}
/**
* @return Collection|CreditNoteLine[]
*/
public function getChildrens(): Collection
{
return $this->childrens;
}
/**
* @param CreditNoteLine $line
* @return CreditNoteLine
*/
public function addChildren(CreditNoteLine $line): self
{
if (!$this->childrens->contains($line)) {
$this->childrens[] = $line;
$line->setParent($this);
if ($line->getCreditNote() !== $this->getCreditNote()) {
$line->setCreditNote($this->getCreditNote());
}
}
return $this;
}
/**
* @return Collection|CreditNoteLine[]
*/
public function getPackChildrens(): Collection
{
return $this->packChildrens;
}
/**
* @param CreditNoteLine $line
* @return $this
*/
public function addPackChildren(CreditNoteLine $line): self
{
if (!$this->packChildrens->contains($line)) {
$this->packChildrens[] = $line;
$line->setPackParent($this);
if ($line->getCreditNote() !== $this->getCreditNote()) {
$line->setCreditNote($this->getCreditNote());
}
}
return $this;
}
/**
* @return CreditNote|null
*/
public function getDocument(): ?CreditNote
{
return $this->getCreditNote();
}
/**
* @param CreditNote $creditNote
* @return CreditNoteLine
*/
public function duplicate(CreditNote $creditNote): CreditNoteLine
{
if ($this->id) {
$clone = clone $this;
$clone->setId();
$clone->setCreditNote($creditNote);
$clone->setCreatedAt(new DateTime());
$clone->setCreatedBy(null);
$clone->setUpdatedAt(new DateTime());
$clone->setUpdatedBy(null);
$clone->childrens = new ArrayCollection();
foreach ($this->getChildrens() as $children) {
$clone_children = $children->duplicate($creditNote);
$clone->addChildren($clone_children);
$children->packChildrens = new ArrayCollection();
foreach ($children->getPackChildrens() as $packChildren) {
$clone_pack_children = $packChildren->duplicate($creditNote);
$children->addPackChildren($clone_pack_children);
}
}
$clone->packChildrens = new ArrayCollection();
foreach ($this->getPackChildrens() as $packChildren) {
$clone_pack_children = $packChildren->duplicate($creditNote);
$clone->addPackChildren($clone_pack_children);
}
return $clone;
}
return $this;
}
/**
* @return bool
*/
public function isProduct(): bool
{
$options = $this->getOptions();
return !empty($options['product']) && !empty($options['product']['id']);
}
/**
* @return bool
*/
public function isDeclination(): bool
{
return $this->isProduct() && !empty($this->getOptions()['product']['declination_id']);
}
/**
* @return Product|null
* @throws NonUniqueResultException
*/
public function getProduct(): ?Product
{
if ($this->em && $this->product) {
SoftdeleteFilter::disable($this->em, [Product::class]);
$product = $this->em->getRepository(Product::class)
->createQueryBuilder('p')
->where('p.id = :productId')
->setParameter('productId', $this->product->getId()->toBinary())
->getQuery()
->getOneOrNullResult();
SoftdeleteFilter::enable($this->em, [Product::class]);
return $product;
}
return $this->product;
}
/**
* @param Product|null $Product
* @return $this
*/
public function setProduct(?Product $Product): self
{
$this->product = $Product;
return $this;
}
/**
* @return Declination|null
* @throws NonUniqueResultException
*/
public function getDeclination(): ?Declination
{
if ($this->em && $this->declination) {
SoftdeleteFilter::disable($this->em, [Declination::class]);
$declination = $this->em->getRepository(Declination::class)
->createQueryBuilder('d')
->where('d.id = :declinationId')
->setParameter('declinationId', $this->declination->getId()->toBinary())
->getQuery()
->getOneOrNullResult();
SoftdeleteFilter::enable($this->em, [Declination::class]);
return $declination;
}
return $this->declination;
}
/**
* @param Declination|null $declination
* @return $this
*/
public function setDeclination(?Declination $declination): self
{
$this->declination = $declination;
return $this;
}
}