<?php
namespace App\Entity;
use App\Exception\CurrencyException;
use App\Exception\InvalidArgumentException;
use App\Model\LicenseFileArchive;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* @ORM\Entity(
* repositoryClass="App\Repository\OrderConfirmationRepository"
* )
* @ORM\Table(
* name="order_confirmation",
* options={"collate"="utf8_swedish_ci"}
* )
* @ORM\HasLifecycleCallbacks
*/
class OrderConfirmation implements EntityInterface, LoggableInterface, SalesDocumentInterface, SalesDocumentDiscountInterface
{
use DocumentTrait;
use LoggableTrait;
use SalesItemListTrait;
use VatJustificationTrait;
const NUMBER_PREFIX = 'OC';
const ORDER_NUMBER_PREFIX = 0;
const STATUS_DRAFT = 'draft';
const STATUS_NOT_CONFIRMED = 'not_confirmed';
const STATUS_PRELIMINARY_CONFIRMED = 'preliminary_confirmed';
const STATUS_CONFIRMED = 'confirmed';
const STATUS_PARTIALLY_DELIVERED = 'partially_delivered';
const STATUS_EQUIPMENT_DELIVERED = 'equipment_delivered';
const STATUS_DELIVERED = 'delivered';
const STATUS_COMPLETED = 'completed';
const STATUS_RISK_ORDER = 'risk_order';
const STATUS_REJECTED = 'rejected';
/**
* @ORM\Id
* @ORM\Column(
* type="integer"
* )
* @ORM\GeneratedValue(
* strategy="AUTO"
* )
*
* @var int|null
*/
protected ?int $id = null;
/**
* @ORM\Column(
* name="append_general_terms_and_conditions",
* type="boolean"
* )
*
* @var bool
*/
protected bool $appendGeneralTermsAndConditions = true;
/**
* @ORM\OneToOne(
* targetEntity="CompanyDocumentAddress",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\JoinColumn(
* name="buyer_id"
* )
* @Assert\Valid
*
* @var CompanyDocumentAddress|null
*/
protected ?CompanyDocumentAddress $buyer = null;
/**
* @ORM\OneToOne(
* targetEntity="CompanyDocumentAddress",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\JoinColumn(
* name="consignee_id"
* )
* @Assert\Valid
*
* @var CompanyDocumentAddress|null
*/
protected ?CompanyDocumentAddress $consignee = null;
/**
* @ORM\OneToOne(
* targetEntity="CompanyDocumentAddress",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\JoinColumn(
* name="delivery_address_id"
* )
* @Assert\Valid
*
* @var CompanyDocumentAddress|null
*/
protected ?CompanyDocumentAddress $deliveryAddress = null;
/**
* @ORM\Column(
* name="delivery_date",
* type="date",
* nullable=true
* )
*
* @var DateTime|null
*/
protected ?DateTime $deliveryDate = null;
/**
* @ORM\OneToMany(
* targetEntity="DocumentVersionOrderConfirmation",
* mappedBy="orderConfirmation",
* cascade={"persist","remove"}
* )
* @ORM\OrderBy({"created" = "DESC"})
*
* @var Collection<DocumentVersionOrderConfirmation>
*/
protected $documentVersions;
/**
* @ORM\OneToOne(
* targetEntity="DocumentEndCustomer",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\JoinColumn(
* name="end_customer_id"
* )
* @Assert\Valid
*
* @var DocumentEndCustomer|null
*/
protected ?DocumentEndCustomer $endCustomer = null;
/**
* @ORM\OneToOne(
* targetEntity="CompanyDocumentAddress",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\JoinColumn(
* name="invoicing_address_id"
* )
* @Assert\Valid
*
* @var CompanyDocumentAddress|null
*/
protected ?CompanyDocumentAddress $invoicingAddress = null;
/**
* @ORM\ManyToMany(
* targetEntity="LogEntry",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\JoinTable(
* name="order_confirmation_log_entry",
* joinColumns={
* @ORM\JoinColumn(
* name="order_confirmation_id",
* referencedColumnName="id",
* onDelete="cascade"
* )
* },
* inverseJoinColumns={
* @ORM\JoinColumn(
* name="log_entry_id",
* referencedColumnName="id",
* unique=true,
* onDelete="cascade"
* )
* }
* )
* @ORM\OrderBy({"time" = "ASC"})
* @Assert\Valid
*
* @var Collection<LogEntry>
*/
protected $logEntries;
/**
* @ORM\Column(
* type="string",
* length=5000,
* nullable=true
* )
*
* @var string|null
*/
protected ?string $notes = null;
/**
* @ORM\Column(
* name="order_number",
* type="integer",
* nullable=true
* )
*
* @var int|null
*/
protected ?int $orderNumber = null;
/**
* @ORM\Column(
* name="other_instructions",
* type="string",
* length=1000,
* nullable=true
* )
*
* @var string|null
*/
protected ?string $otherInstructions = null;
/**
* @ORM\OneToMany(
* targetEntity="DeliveryDate",
* mappedBy="orderConfirmation",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\OrderBy({"date" = "ASC"})
*
* @var Collection<DeliveryDate>
*/
protected $plannedDeliveryDates;
/**
* @ORM\Column(
* name="preliminary_confirmation",
* type="boolean"
* )
*
* @var bool
*/
protected bool $preliminaryConfirmation = false;
/**
* @ORM\OneToOne(
* targetEntity="SalesCase",
* inversedBy="orderConfirmation"
* )
* @ORM\JoinColumn(
* name="sales_case_id",
* referencedColumnName="id",
* onDelete="cascade"
* )
* @Assert\NotNull
*
* @var SalesCase
*/
protected SalesCase $salesCase;
/**
* @ORM\ManyToMany(
* targetEntity="SalesItem",
* cascade={"persist","remove"},
* orphanRemoval=true,
* fetch="EXTRA_LAZY"
* )
* @ORM\JoinTable(
* name="order_confirmation_sales_item",
* joinColumns={
* @ORM\JoinColumn(
* name="order_confirmation_id",
* referencedColumnName="id",
* onDelete="cascade"
* )
* },
* inverseJoinColumns={
* @ORM\JoinColumn(
* name="sales_item_id",
* referencedColumnName="id",
* unique=true,
* onDelete="cascade"
* )
* }
* )
* @ORM\OrderBy({"position" = "ASC"})
* @Assert\Valid
*
* @var Collection<SalesItem>
*/
protected $salesItems;
/**
* @var bool
*/
protected bool $salesItemsPopulated = false;
/**
* @ORM\Column(
* name="shipping_marks",
* type="string",
* length=500,
* nullable=true
* )
*
* @var string|null
*/
protected ?string $shippingMarks = null;
/**
* @ORM\Column(
* name="terms_of_delivery",
* type="string",
* length=500,
* nullable=true
* )
*
* @var string|null
*/
protected ?string $termsOfDelivery = null;
/**
* @ORM\ManyToMany(
* targetEntity="TermsOfPaymentRow",
* cascade={"persist","remove"},
* orphanRemoval=true
* )
* @ORM\JoinTable(
* name="order_confirmation_terms_of_payment_row",
* joinColumns={
* @ORM\JoinColumn(
* name="order_confirmation_id",
* referencedColumnName="id",
* onDelete="cascade"
* )
* },
* inverseJoinColumns={
* @ORM\JoinColumn(
* name="terms_of_payment_row_id",
* referencedColumnName="id",
* unique=true,
* onDelete="cascade"
* )
* }
* )
* @Assert\Valid
*
* @var Collection<TermsOfPaymentRow>
*/
protected $termsOfPaymentRows;
/**
* @ORM\Column(
* type="string",
* length=2000,
* nullable=true
* )
*
* @var string|null
*/
protected ?string $text = null;
/**
* @ORM\Column(
* type="string",
* length=500,
* nullable=true
* )
*
* @var string|null
*/
protected ?string $transportation = null;
/**
* @param SalesCase $salesCase
*/
public function __construct(SalesCase $salesCase)
{
$this->salesCase = $salesCase;
$this->documentVersions = new ArrayCollection();
$this->logEntries = new ArrayCollection();
$this->plannedDeliveryDates = new ArrayCollection();
$this->salesItems = new ArrayCollection();
$this->termsOfPaymentRows = new ArrayCollection();
}
/**
* @return string
*/
public function __toString(): string
{
return $this->getNumber() . ($this->salesCase->getCompany() !== null ? ' (' . $this->salesCase->getCompany()->getName() . ')' : '');
}
/**
* @param DocumentVersionOrderConfirmation $documentVersion
*
* @throws InvalidArgumentException
*/
public function addDocumentVersion(DocumentVersionOrderConfirmation $documentVersion)
{
if ($documentVersion->getOrderConfirmation() !== $this) {
throw new InvalidArgumentException('Document version has mismatching order confirmation document.');
}
$this->documentVersions->add($documentVersion);
}
/**
* @param DeliveryDate $deliveryDate
*
* @throws InvalidArgumentException
*/
public function addPlannedDeliveryDate(DeliveryDate $deliveryDate)
{
if ($deliveryDate->getOrderConfirmation() !== $this) {
throw new InvalidArgumentException('Delivery date has mismatching order confirmation document.');
}
$this->plannedDeliveryDates->add($deliveryDate);
}
/**
* @param TermsOfPaymentRow $row
*/
public function addTermsOfPaymentRow(TermsOfPaymentRow $row)
{
if ($this->termsOfPaymentRows === null) {
$this->termsOfPaymentRows = new ArrayCollection();
}
$this->termsOfPaymentRows->add($row);
}
/**
* @return bool
*/
public function getAppendGeneralTermsAndConditions(): bool
{
return $this->appendGeneralTermsAndConditions;
}
/**
* @return CompanyDocumentAddress|null
*/
public function getBuyer(): ?CompanyDocumentAddress
{
return $this->buyer;
}
/**
* @return CompanyDocumentAddress|null
*/
public function getConsignee(): ?CompanyDocumentAddress
{
return $this->consignee;
}
/**
* @return CompanyDocumentAddress|null
*/
public function getDeliveryAddress(): ?CompanyDocumentAddress
{
return $this->deliveryAddress;
}
/**
* @return DateTime|null
*/
public function getDeliveryDate(): ?DateTime
{
return $this->deliveryDate;
}
/**
* @return Collection<DocumentVersionOrderConfirmation>
*/
public function getDocumentVersions(): Collection
{
return $this->documentVersions;
}
/**
* @return DateTime|null
*
* @throws Exception
*/
public function getDueDate(): ?DateTime
{
if (null !== $deliveryDate = $this->getDeliveryDate()) {
if (count($this->getTermsOfPaymentRows()) > 0) {
/* @var TermsOfPaymentRow $first */
$first = $this->termsOfPaymentRows->first();
if (null !== $days = $first->getDays()) {
$dueDate = clone $deliveryDate;
$dueDate->add(new \DateInterval('P' . $days . 'D'));
return $dueDate;
}
}
}
return null;
}
/**
* @return DocumentEndCustomer|null
*/
public function getEndCustomer(): ?DocumentEndCustomer
{
return $this->endCustomer;
}
/**
* @return float
*
* @throws CurrencyException
* @throws Exception
*/
public function getGrossMargin(): float
{
if (($totalSales = $this->getValueNet(true)) <= 0) {
throw new Exception('The OC has no total sales value.');
}
$totalCostOfSales = 0;
foreach ($this->salesCase->getPurchaseOrders() as $purchaseOrder) {
if ($purchaseOrder->isSent()) {
$totalCostOfSales += $purchaseOrder->getTotalPurchaseValue(true);
}
}
return ($totalSales - $totalCostOfSales) / $totalSales;
}
/**
* @return array
*/
public function getGrossMarginDisplay(): array
{
$value = null;
$error = null;
try {
$value = $this->getGrossMargin();
} catch (Exception $e) {
$error = $e->getMessage();
}
return [$value, $error];
}
/**
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return LicenseFileArchive|null
*/
public function getLicenseFileArchive(): ?LicenseFileArchive
{
if ($this->hasLicenseFiles()) {
return new LicenseFileArchive($this->salesCase);
}
return null;
}
/**
* @return CompanyDocumentAddress|null
*/
public function getInvoicingAddress(): ?CompanyDocumentAddress
{
return $this->invoicingAddress;
}
/**
* @return null|string
*/
public function getNotes(): ?string
{
return $this->notes;
}
/**
* @return string
*/
public function getNumber(): string
{
return self::NUMBER_PREFIX . str_pad($this->salesCase->getId(), 6, '0', STR_PAD_LEFT)
. '-'
. ($this->isDraft() ? 'DRAFT' : self::ORDER_NUMBER_PREFIX . str_pad($this->getOrderNumber(), 5, '0', STR_PAD_LEFT));
}
/**
* @return int|null
*/
public function getOrderNumber(): ?int
{
return $this->orderNumber;
}
/**
* @return null|string
*/
public function getOtherInstructions(): ?string
{
return $this->otherInstructions;
}
/**
* @return Collection<DeliveryDate>
*/
public function getPlannedDeliveryDates(): Collection
{
return $this->plannedDeliveryDates;
}
/**
* @return string
*/
public function getPreviewFileName(): string
{
return 'Order Confirmation - ' . $this->getNumber() . ' - Preview ' . date('Y-m-d') . '.pdf';
}
/**
* @return SalesCase
*/
public function getSalesCase(): SalesCase
{
return $this->salesCase;
}
/**
* @return array|null
*
* @throws CurrencyException
*/
public function getSalesCaseCosts(): ?array
{
$purchasePrices = [];
foreach ($this->salesCase->getPurchaseOrders() as $purchaseOrder) {
if ($purchaseOrder->isSent()) {
foreach ($purchaseOrder->getSalesItems() as $salesItem) {
if (null !== $purchasePrice = $salesItem->getPurchasePrice(true)) {
$purchasePrices[$salesItem->getCode()] = $purchasePrice;
}
}
}
}
if (0 === count($purchasePrices)) {
return null;
}
$salesQuantities = [];
foreach ($this->salesCase->getInvoices() as $invoice) {
if ($invoice instanceof Invoice || $invoice instanceof CreditInvoice) {
if ($invoice->isInvoiced()) {
foreach ($invoice->getSalesItems() as $salesItem) {
if (!array_key_exists($salesItem->getCode(), $salesQuantities)) {
$salesQuantities[$salesItem->getCode()] = 0;
}
$quantity = $salesItem->getQuantity();
if ($invoice instanceof CreditInvoice) {
$quantity = -$quantity;
}
$salesQuantities[$salesItem->getCode()] += $quantity;
}
}
}
}
$costs = [];
foreach ($this->salesItems as $salesItem) {
$code = $salesItem->getCode();
$quantity = array_key_exists($code, $salesQuantities) ? $salesQuantities[$code] : null;
$unitPrice = array_key_exists($code, $purchasePrices) ? $purchasePrices[$code] : null;
$cost = null;
if (null !== $quantity && null !== $unitPrice) {
$cost = $quantity * $unitPrice;
}
$costs[$salesItem->getCode()] = [
'position' => $salesItem->getPositionDisplay(),
'code' => $code,
'quantity' => $quantity,
'unitPrice' => $unitPrice,
'cost' => $cost,
];
}
return $costs;
}
/**
* @param bool $includeDrafts
*
* @return int
*/
public function getSalesItemInvoicedQuantity(bool $includeDrafts = true): int
{
$quantity = 0;
foreach ($this->getSalesCase()->getInvoicesOfTypeInvoice() as $invoice) {
if (!$includeDrafts && $invoice->isDraft()) {
continue;
}
foreach ($invoice->getSalesItems() as $item) {
$quantity += $item->getQuantity();
}
}
foreach ($this->getSalesCase()->getInvoicesOfTypeCreditInvoice() as $invoice) {
if (!$includeDrafts && $invoice->isDraft()) {
continue;
}
foreach ($invoice->getSalesItems() as $item) {
$quantity -= $item->getQuantity();
}
}
return $quantity;
}
/**
* @param bool $includeDrafts
*
* @return int
*/
public function getSalesItemPurchasedQuantity(bool $includeDrafts = true): int
{
$quantity = 0;
foreach ($this->getSalesCase()->getPurchaseOrders() as $purchaseOrder) {
if ($purchaseOrder->isRejected() || (!$includeDrafts && $purchaseOrder->isDraft())) {
continue;
}
foreach ($purchaseOrder->getSalesItems() as $item) {
$quantity += $item->getQuantity();
}
}
return $quantity;
}
/**
* @return Collection<SalesItem>
*/
public function getSalesItems(): Collection
{
if (!$this->salesItemsPopulated) {
$currency = $this->getCurrency();
foreach ($this->salesItems as $salesItem) {
$salesItem->setCurrency($currency);
$salesItem->setCurrencyExchangeRate($this->currencyExchangeRate);
}
$this->salesItemsPopulated = true;
}
return $this->salesItems;
}
/**
* @return null|string
*/
public function getShippingMarks(): ?string
{
return $this->shippingMarks;
}
/**
* @return array<string>
*/
public static function getStatusChoices(): array
{
return [
self::STATUS_DRAFT,
self::STATUS_NOT_CONFIRMED,
self::STATUS_PRELIMINARY_CONFIRMED,
self::STATUS_CONFIRMED,
self::STATUS_PARTIALLY_DELIVERED,
self::STATUS_EQUIPMENT_DELIVERED,
self::STATUS_DELIVERED,
self::STATUS_COMPLETED,
self::STATUS_RISK_ORDER,
self::STATUS_REJECTED,
];
}
/**
* @return array<Supplier>
*
* @throws Exception
*/
public function getSuppliers(): array
{
$list = new ArrayCollection();
foreach ($this->getSalesItems() as $item) {
if (null !== $supplier = $item->getSupplier()) {
if (!$list->contains($supplier)) {
$list->add($supplier);
}
}
}
$iterator = $list->getIterator();
$iterator->uasort(
function (Supplier $a, Supplier $b) {
if ($a->getName() == $b->getName()) {
return 0;
}
return ($a->getName() < $b->getName()) ? -1 : 1;
}
);
return $iterator->getArrayCopy();
}
/**
* @return Collection<SalesItem>
*/
public function getSupportItems(): Collection
{
return $this->getSalesItems()->filter(
function (SalesItem $salesItem) {
return $salesItem->isSupport();
}
);
}
/**
* @return null|string
*/
public function getTermsOfDelivery(): ?string
{
return $this->termsOfDelivery;
}
/**
* @return Collection<TermsOfPaymentRow>
*/
public function getTermsOfPaymentRows(): Collection
{
return $this->termsOfPaymentRows;
}
/**
* @return null|string
*/
public function getText(): ?string
{
return $this->text;
}
/**
* @return null|string
*/
public function getTransportation(): ?string
{
return $this->transportation;
}
/**
* @param bool $includeDrafts
*
* @return array<SalesItem>
*
* @throws Exception
*/
public function getUninvoicedSalesItems(bool $includeDrafts = true): array
{
/* @var SalesItem[] $list */
$list = [];
foreach ($this->getSalesItems() as $ocItem) {
$list[$ocItem->getPositionNormalized()] = clone $ocItem;
}
foreach ($this->salesCase->getInvoicesOfTypeInvoice() as $invoice) {
if (!$includeDrafts && $invoice->isDraft()) {
continue;
}
foreach ($invoice->getSalesItems() as $invItem) {
$position = $invItem->getPositionNormalized();
if (isset($list[$position])) {
$itemQuantity = $invItem->getQuantity();
$list[$position]->setQuantity(
$list[$position]->getQuantity() - $itemQuantity
);
if ($invItem->isPciItem() && !$invItem->isPciExpandItem()) {
// Subtract PCI sub-items from the list of uninvoiced because they are not listed in the invoice
foreach ($list as $itemTemp) {
if ($itemTemp->isPciSubItem() && $itemTemp->getPciPosition() === $position) {
$itemTemp->setQuantity(
$itemTemp->getQuantity() - $itemQuantity * $itemTemp->getQuantityPerPci()
);
}
}
}
}
}
}
foreach ($this->salesCase->getInvoicesOfTypeCreditInvoice() as $invoice) {
if (!$includeDrafts && $invoice->isDraft()) {
continue;
}
foreach ($invoice->getSalesItems() as $invItem) {
$position = $invItem->getPositionNormalized();
if (isset($list[$position])) {
$itemQuantity = $invItem->getQuantity();
$list[$position]->setQuantity(
$list[$position]->getQuantity() + $itemQuantity
);
}
}
}
// Adjust PCI item quantity based on uninvoiced sub-item quantities
$pciMaxQuantities = [];
foreach ($list as $item) {
if ($item->isPciSubItem()) {
if (empty($item->getQuantityPerPci())) {
throw new Exception('Missing quantity per PCI for OC position ' . $item->getPositionDisplay() . '.');
}
$pciPosition = $item->getPciPosition();
$pciMaxQuantity = floor($item->getQuantity() / $item->getQuantityPerPci());
if (array_key_exists($pciPosition, $pciMaxQuantities)) {
$pciMaxQuantities[$pciPosition] = min($pciMaxQuantities[$pciPosition], $pciMaxQuantity);
} else {
$pciMaxQuantities[$pciPosition] = $pciMaxQuantity;
}
}
}
foreach ($pciMaxQuantities as $position => $maxQuantity) {
if (array_key_exists($position, $list)) {
$list[$position]->setQuantity($maxQuantity);
}
}
// Remove items with no uninvoiced quantities
foreach ($list as $key => $item) {
if ($item->getQuantity() <= 0) {
unset($list[$key]);
}
}
return $list;
}
/**
* @return array<SalesItem>
*/
public function getUnpurchasedSalesItems(): array
{
/* @var SalesItem[] $list */
$list = [];
foreach ($this->getSalesItems() as $ocItem) {
$supplier = $ocItem->getSupplier();
$key = $ocItem->getCode() . ':' . ($supplier !== null ? $supplier->getId() : '');
$list[$key] = clone $ocItem;
}
foreach ($this->getSalesCase()->getPurchaseOrders() as $purchaseOrder) {
if (! $purchaseOrder->isRejected()) {
foreach ($purchaseOrder->getSalesItems() as $item) {
$supplier = $purchaseOrder->getSupplier();
$key = $item->getCode() . ':' . ($supplier !== null ? $supplier->getId() : '');
if (isset($list[$key])) {
$list[$key]->setQuantity(
$list[$key]->getQuantity() - $item->getQuantity()
);
}
}
}
}
foreach ($list as $key => $item) {
if ($item->getQuantity() == 0) {
unset($list[$key]);
}
}
return $list;
}
/**
* @return bool
*/
public function hasLicenseFiles(): bool
{
foreach ($this->getSalesItems() as $salesItem) {
if ($salesItem->isLicenseFile()) {
return true;
}
}
return false;
}
/**
* @return bool
*/
public function isCompleted(): bool
{
return $this->getStatus() == self::STATUS_COMPLETED;
}
/**
* @return bool
*/
public function isCurrencyExchangeRateLocked(): bool
{
return !in_array(
$this->status,
[
self::STATUS_DRAFT,
self::STATUS_NOT_CONFIRMED,
self::STATUS_RISK_ORDER,
self::STATUS_PARTIALLY_DELIVERED,
self::STATUS_EQUIPMENT_DELIVERED,
]
);
}
/**
* @return bool
*/
public function isDraft(): bool
{
return $this->getStatus() == self::STATUS_DRAFT;
}
/**
* @return bool
*/
public function isNotConfirmed(): bool
{
return $this->getStatus() == self::STATUS_NOT_CONFIRMED;
}
/**
* @return bool
*/
public function isPreliminaryConfirmation(): bool
{
return $this->preliminaryConfirmation;
}
/**
* @return bool
*/
public function isRejected(): bool
{
return $this->getStatus() == self::STATUS_REJECTED;
}
/**
* @return bool
*/
public function isRiskOrder(): bool
{
return $this->getStatus() == self::STATUS_RISK_ORDER;
}
/**
* @ORM\PreUpdate
*/
public function preUpdateOrderConfirmation(): void
{
if (count($this->getPlannedDeliveryDates()) == 0 && $this->getDeliveryDate() !== null) {
$deliveryDate = new DeliveryDate($this, $this->getDeliveryDate(), 100);
$this->addPlannedDeliveryDate($deliveryDate);
}
}
/**
* @param DeliveryDate $deliveryDate
*/
public function removePlannedDeliveryDate(DeliveryDate $deliveryDate): void
{
if ($this->plannedDeliveryDates !== null) {
$this->plannedDeliveryDates->removeElement($deliveryDate);
}
}
/**
* @param TermsOfPaymentRow $row
*/
public function removeTermsOfPaymentRow(TermsOfPaymentRow $row): void
{
if ($this->termsOfPaymentRows !== null) {
$this->termsOfPaymentRows->removeElement($row);
}
}
/**
* @param bool $appendGeneralTermsAndConditions
*/
public function setAppendGeneralTermsAndConditions(bool $appendGeneralTermsAndConditions): void
{
$this->appendGeneralTermsAndConditions = $appendGeneralTermsAndConditions;
}
/**
* @param CompanyDocumentAddress|null $buyer
*/
public function setBuyer(?CompanyDocumentAddress $buyer): void
{
$this->buyer = $buyer;
}
/**
* @param CompanyDocumentAddress|null $consignee
*/
public function setConsignee(?CompanyDocumentAddress $consignee): void
{
$this->consignee = $consignee;
}
/**
* @param CompanyDocumentAddress|null $deliveryAddress
*/
public function setDeliveryAddress(?CompanyDocumentAddress $deliveryAddress): void
{
$this->deliveryAddress = $deliveryAddress;
}
/**
* @param DateTime|null $deliveryDate
*/
public function setDeliveryDate(?DateTime $deliveryDate)
{
$this->deliveryDate = $deliveryDate;
}
/**
* @param DocumentEndCustomer|null $endCustomer
*/
public function setEndCustomer(?DocumentEndCustomer $endCustomer)
{
$this->endCustomer = $endCustomer;
}
/**
* @param CompanyDocumentAddress|null $invoicingAddress
*/
public function setInvoicingAddress(?CompanyDocumentAddress $invoicingAddress): void
{
$this->invoicingAddress = $invoicingAddress;
}
/**
* @param string|null $notes
*/
public function setNotes(?string $notes)
{
$this->notes = $notes;
}
/**
* @param int|null $orderNumber
*/
public function setOrderNumber(?int $orderNumber)
{
$this->orderNumber = $orderNumber;
}
/**
* @param string|null $otherInstructions
*/
public function setOtherInstructions(?string $otherInstructions)
{
$this->otherInstructions = $otherInstructions;
}
/**
* @param bool $preliminaryConfirmation
*/
public function setPreliminaryConfirmation(bool $preliminaryConfirmation)
{
$this->preliminaryConfirmation = $preliminaryConfirmation;
}
/**
* @param string|null $shippingMarks
*/
public function setShippingMarks(?string $shippingMarks)
{
$this->shippingMarks = $shippingMarks;
}
/**
* @param string|null $termsOfDelivery
*/
public function setTermsOfDelivery(?string $termsOfDelivery)
{
$this->termsOfDelivery = $termsOfDelivery;
}
/**
* @param string|null $text
*/
public function setText(?string $text)
{
$this->text = $text;
}
/**
* @param string|null $transportation
*/
public function setTransportation(?string $transportation)
{
$this->transportation = $transportation;
}
/**
* @Assert\Callback
*
* @param ExecutionContextInterface $context
*/
public function validate(ExecutionContextInterface $context)
{
$total = 0;
foreach ($this->getPlannedDeliveryDates() as $deliveryDate) {
$total += $deliveryDate->getPercentage();
}
if ($total > 100) {
$context->buildViolation('validation.plannedDeliveryDates.percentageOutOfBounds')
->setTranslationDomain('OrderConfirmation')
->atPath('plannedDeliveryDates')
->addViolation();
}
}
}