src/Entity/Expediting/ShippingPlan.php line 68
<?php
namespace App\Entity\Expediting;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Link;
use App\Doctrine\Type\Expediting\ShippingPlanStatus;
use App\Doctrine\Type\Expediting\ShippingSegmentStatus;
use App\Entity\Common as Common;
use App\Entity\Finance\Bill;
use App\Entity\Finance\Invoice;
use App\Entity\Finance\Proforma;
use App\Entity\Finance\BaseQuotation;
use App\Entity\Sales\WorkOrder;
use App\Entity\Scheduler\Task;
use App\Provider\Expediting\ShippingPlansProvider;
use App\Provider\Finance\ShippingPlanQuotationsProvider;
use App\Validator\IsValidEnum\IsValidEnum;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Uid\Ulid;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Table(name: 'expediting_shipping_plan')]
#[ORM\Index(columns: ['original_plan_id'], name: 'expediting_shipping_plan_original_plan_id_idx')]
#[ORM\Index(columns: ['work_order_id'], name: 'expediting_shipping_plan_work_order_idx')]
#[ORM\Index(columns: ['shipment_id'], name: 'expediting_shipping_plan_shipment_idx')]
#[ORM\Index(columns: ['created_by'], name: 'expediting_shipping_plan_created_by_idx')]
#[ORM\Index(columns: ['updated_by'], name: 'expediting_shipping_plan_updated_by_idx')]
#[ORM\UniqueConstraint(name: 'expediting_shipping_plan_original_plan_id_key', columns: ['original_plan_id'])]
#[ORM\UniqueConstraint(name: 'expediting_shipping_plan_identifier_key', columns: ['identifier'])]
#[ORM\Entity]
#[UniqueEntity(fields: ['identifier'])]
#[ApiResource(
uriTemplate: '/work_orders/{slug}/shipping_plans',
operations: [
new GetCollection(provider: ShippingPlansProvider::class),
],
uriVariables: [
'slug' => new Link(fromProperty: 'shippingPlans', fromClass: WorkOrder::class),
],
)]
#[ApiResource(
operations: [
new Get(),
new GetCollection(order: ['id' => 'DESC'], provider: ShippingPlanQuotationsProvider::class),
],
routePrefix: '/expediting',
)]
#[ApiFilter(SearchFilter::class, properties: [
'workOrder.reference' => 'ipartial',
'quotations.payableTo' => 'exact',
'quotations.status' => 'exact',
'quotations.type' => 'exact',
'tasks.status' => 'exact',
'tasks.type' => 'exact',
'status' => 'exact',
])]
class ShippingPlan
{
use Common\Blameable;
use Common\Trackable;
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'IDENTITY')]
#[ORM\SequenceGenerator(sequenceName: 'expediting_shipping_plan_id_seq')]
#[ORM\Column(type: Types::INTEGER)]
#[ApiProperty(identifier: false)]
private ?int $id = null;
#[Assert\Ulid]
#[Assert\NotNull]
#[ORM\Column(type: 'ulid', unique: true)]
#[ApiProperty(identifier: true)]
private ?Ulid $identifier = null;
#[Assert\NotNull]
#[IsValidEnum(enum: ShippingPlanStatus::class)]
#[ORM\Column(type: Types::STRING, enumType: ShippingPlanStatus::class, options: ['default' => 'DRAFTED'])]
private ?ShippingPlanStatus $status = ShippingPlanStatus::DRAFTED;
#[ORM\ManyToOne(targetEntity: WorkOrder::class, inversedBy: 'shippingPlans')]
#[ORM\JoinColumn(name: 'work_order_id')]
private ?WorkOrder $workOrder = null;
#[ORM\ManyToOne(targetEntity: Shipment::class, inversedBy: 'shippingPlans')]
#[ORM\JoinColumn(name: 'shipment_id')]
private ?Shipment $shipment = null;
/** @var Collection<int, BaseQuotation> */
#[ORM\OneToMany(mappedBy: 'shippingPlan', targetEntity: BaseQuotation::class)]
private Collection $quotations;
/** @var Collection<int, Proforma> */
#[ORM\OneToMany(mappedBy: 'shippingPlan', targetEntity: Proforma::class)]
private Collection $proformas;
#[Assert\Type(type: ShippingPlan::class)]
#[ORM\OneToOne(targetEntity: ShippingPlan::class)]
#[ORM\JoinColumn(name: 'original_plan_id')]
private ?ShippingPlan $originalPlan = null;
/** @var Collection<int, ShippingSegment> */
#[ORM\OneToMany(mappedBy: 'shippingPlan', targetEntity: ShippingSegment::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[ORM\OrderBy(['id' => 'ASC'])]
#[ApiProperty(readableLink: true)]
private Collection $shippingSegments;
/** @var Collection<int, Task> */
#[ORM\ManyToMany(targetEntity: Task::class, mappedBy: 'shippingPlans')]
private Collection $tasks;
#[Assert\Callback]
public function validate(ExecutionContextInterface $context, $payload): void
{
if (empty($this->workOrder) && empty($this->shipment)) {
$context->buildViolation('Shipping plan must be associated only with either, a work order, or a shipment')
->atPath('workOrder')
->addViolation();
$context->buildViolation('Shipping plan must be associated only with either, a work order, or a shipment')
->atPath('shipment')
->addViolation();
}
}
public function __construct()
{
$this->identifier = new Ulid();
$this->proformas = new ArrayCollection();
$this->quotations = new ArrayCollection();
$this->shippingSegments = new ArrayCollection();
$this->tasks = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getIdentifier(): ?Ulid
{
return $this->identifier;
}
public function setIdentifier(Ulid $identifier): self
{
$this->identifier = $identifier;
return $this;
}
public function getStatus(): ?ShippingPlanStatus
{
return $this->status;
}
public function setStatus(?ShippingPlanStatus $status): self
{
$this->status = $status;
return $this;
}
public function getWorkOrder(): ?WorkOrder
{
return $this->workOrder;
}
public function setWorkOrder(?WorkOrder $workOrder): static
{
$this->workOrder = $workOrder;
return $this;
}
public function getShipment(): ?Shipment
{
return $this->shipment;
}
public function setShipment(?Shipment $shipment): static
{
$this->shipment = $shipment;
return $this;
}
/**
* @return Collection<int, Package>
*/
public function getPackages(): Collection
{
return (null !== $this->workOrder)
? $this->workOrder->getPackages()
: $this->shipment->getPackages();
}
public function getOriginalPlan(): ?self
{
return $this->originalPlan;
}
public function setOriginalPlan(?self $originalPlan): self
{
$this->originalPlan = $originalPlan;
return $this;
}
/**
* @return Collection<int, ShippingSegment>
*/
public function getShippingSegments(): Collection
{
return $this->shippingSegments;
}
public function getCurrentSegment(): ?ShippingSegment
{
if (!in_array($this->status, [ShippingPlanStatus::DRAFTED, ShippingPlanStatus::QUOTED, ShippingPlanStatus::APPROVED])) {
return null;
}
foreach ($this->shippingSegments as $segment) {
if (in_array($segment->getStatus(), [ShippingSegmentStatus::COMPLETED, ShippingPlanStatus::CANCELED])) {
continue;
}
return $segment;
}
return null;
}
public function addShippingSegment(ShippingSegment $shippingSegment): self
{
if (!$this->shippingSegments->contains($shippingSegment)) {
$this->shippingSegments->add($shippingSegment);
$shippingSegment->setShippingPlan($this);
}
return $this;
}
public function removeShippingSegment(ShippingSegment $shippingSegment): self
{
if ($this->shippingSegments->removeElement($shippingSegment)) {
// set the owning side to null (unless already changed)
if ($shippingSegment->getShippingPlan() === $this) {
$shippingSegment->setShippingPlan(null);
}
}
return $this;
}
/**
* @return Collection<int, BaseQuotation>
*/
public function getQuotations(): Collection
{
$quotations = new ArrayCollection();
foreach ($this->quotations as $entity) {
if (!$entity instanceof Bill) {
$quotations->add($entity);
}
}
return $quotations;
}
public function addQuotation(BaseQuotation $quotation): self
{
if (!$this->quotations->contains($quotation)) {
$this->quotations->add($quotation);
$quotation->setShippingPlan($this);
}
return $this;
}
public function removeQuotation(BaseQuotation $quotation): self
{
if ($this->quotations->removeElement($quotation)) {
// set the owning side to null (unless already changed)
if ($quotation->getShippingPlan() === $this) {
$quotation->setShippingPlan(null);
}
}
return $this;
}
/**
* @return Collection<int, Bill>
*/
public function getBills(): Collection
{
$bills = new ArrayCollection();
foreach ($this->quotations as $entity) {
if ($entity instanceof Bill) {
$bills->add($entity);
}
}
return $bills;
}
public function addBill(Bill $bill): self
{
if (!$this->quotations->contains($bill)) {
$this->quotations->add($bill);
$bill->setShippingPlan($this);
}
return $this;
}
public function removeBill(Bill $bill): self
{
if ($this->quotations->removeElement($bill)) {
// set the owning side to null (unless already changed)
if ($bill->getShippingPlan() === $this) {
$bill->setShippingPlan(null);
}
}
return $this;
}
/**
* @return Collection<int, Proforma>
*/
public function getProformas(): Collection
{
$proformas = new ArrayCollection();
foreach ($this->proformas as $entity) {
if (!$entity instanceof Invoice) {
$proformas->add($entity);
}
}
return $proformas;
}
public function addProforma(Proforma $proforma): self
{
if (!$this->proformas->contains($proforma)) {
$this->proformas->add($proforma);
$proforma->setShippingPlan($this);
}
return $this;
}
public function removeProforma(Proforma $proforma): self
{
if ($this->proformas->removeElement($proforma)) {
// set the owning side to null (unless already changed)
if ($proforma->getShippingPlan() === $this) {
$proforma->setShippingPlan(null);
}
}
return $this;
}
/**
* @return Collection<int, Bill>
*/
public function getInvoices(): Collection
{
$invoices = new ArrayCollection();
foreach ($this->proformas as $entity) {
if ($entity instanceof Bill) {
$invoices->add($entity);
}
}
return $invoices;
}
public function addInvoice(Invoice $invoice): self
{
if (!$this->proformas->contains($invoice)) {
$this->proformas->add($invoice);
$invoice->setShippingPlan($this);
}
return $this;
}
public function removeInvoice(Invoice $invoice): self
{
if ($this->proformas->removeElement($invoice)) {
// set the owning side to null (unless already changed)
if ($invoice->getShippingPlan() === $this) {
$invoice->setShippingPlan(null);
}
}
return $this;
}
/**
* @return Collection<int, Task>
*/
public function getTasks(): Collection
{
return $this->tasks;
}
public function addTask(Task $task): self
{
if (!$this->tasks->contains($task)) {
$this->tasks[] = $task;
$task->addShippingPlan($this);
}
return $this;
}
public function removeTask(Task $task): self
{
if ($this->tasks->removeElement($task)) {
$task->removeShippingPlan($this);
}
return $this;
}
}