src/Entity/Expediting/Shipment.php line 178
<?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\Patch;
use ApiPlatform\Metadata\Post;
use ApiPlatform\OpenApi\Model;
use App\Controller\Expediting\ShipmentDocumentUploadAction;
use App\Doctrine\Type\Expediting\ExpeditingStatus;
use App\Doctrine\Type\Expediting\TransportMode;
use App\Dto\Expediting\ConsolidationInput;
use App\Dto\Expediting\ConsolidationOutput;
use App\Dto\Expediting\ContainerRemovalInput;
use App\Dto\Expediting\ContainersInput;
use App\Dto\Expediting\ContainersOutput;
use App\Dto\Expediting\DocumentationKitItemInput;
use App\Dto\Expediting\DocumentationKitDetailsInput;
use App\Dto\Expediting\ShipmentBookingInput;
use App\Dto\Expediting\ShipmentInput;
use App\Dto\Expediting\ShipmentMilestonesOutput;
use App\Dto\Expediting\ShipmentPackageInput;
use App\Dto\Expediting\ShipmentStatusInput;
use App\Dto\Expediting\ShippingPlanInput;
use App\Entity\Common as Common;
use App\Entity\File\File;
use App\Entity\Places\Facility;
use App\Entity\Sales\WorkOrder;
use App\Processor\Expediting\ConsolidationInputProcessor;
use App\Processor\Expediting\ConsolidationPackageAdditionProcessor;
use App\Processor\Expediting\ConsolidationPackageRemovalProcessor;
use App\Processor\Expediting\ConsolidationPlanCreationProcessor;
use App\Processor\Expediting\ContainerDeletionProcessor;
use App\Processor\Expediting\DocumentationKitDetailsProcessor;
use App\Processor\Expediting\DocumentationKitItemProcessor;
use App\Processor\Expediting\ShipmentBookingInputProcessor;
use App\Processor\Expediting\ShipmentContainersInputProcessor;
use App\Processor\Expediting\ShipmentInputProcessor;
use App\Processor\Expediting\ShipmentStatusInputProcessor;
use App\Provider\Expediting\ConsolidationOutputProvider;
use App\Provider\Expediting\ShipmentContainersProvider;
use App\Provider\Expediting\ShipmentDocumentationKitRequestProvider;
use App\Provider\Expediting\ShipmentMilestonesProvider;
use App\Validator\IsValidEnum\IsValidEnum;
use ArrayObject;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Annotation\Ignore;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Table(name: 'expediting_shipment')]
#[ORM\Index(columns: ['created_by'], name: 'expediting_shipment_created_by_idx')]
#[ORM\Index(columns: ['updated_by'], name: 'expediting_shipment_updated_by_idx')]
#[ORM\UniqueConstraint(name: 'expediting_shipment_reference_key', columns: ['reference'])]
#[ORM\UniqueConstraint(name: 'expediting_shipment_slug_key', columns: ['slug'])]
#[ORM\Entity]
#[UniqueEntity(fields: ['reference', 'slug'])]
#[ApiResource(
routePrefix: '/expediting',
input: ShipmentInput::class,
processor: ShipmentInputProcessor::class,
)]
#[ApiResource(
operations: [
new Get(
uriTemplate: '/expediting/shipments/{slug}/milestones',
output: ShipmentMilestonesOutput::class,
provider: ShipmentMilestonesProvider::class
),
new Get(
uriTemplate: '/expediting/shipments/{slug}/containers',
output: ContainersOutput::class,
provider: ShipmentContainersProvider::class
),
new Get(
uriTemplate: '/expediting/shipments/{slug}/shipment',
output: ConsolidationOutput::class,
provider: ConsolidationOutputProvider::class
),
new Get(
uriTemplate: '/expediting/shipments/{slug}/kit-request',
provider: ShipmentDocumentationKitRequestProvider::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/kit/details',
input: DocumentationKitDetailsInput::class,
processor: DocumentationKitDetailsProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/kit/item',
input: DocumentationKitItemInput::class,
processor: DocumentationKitItemProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/containers',
input: ContainersInput::class,
processor: ShipmentContainersInputProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/container-remove',
input: ContainerRemovalInput::class,
processor: ContainerDeletionProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/plan',
input: ShippingPlanInput::class,
processor: ConsolidationPlanCreationProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/booking',
input: ShipmentBookingInput::class,
processor: ShipmentBookingInputProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/add',
input: ShipmentPackageInput::class,
processor: ConsolidationPackageAdditionProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/remove',
input: ShipmentPackageInput::class,
processor: ConsolidationPackageRemovalProcessor::class
),
new Post(
uriTemplate: '/expediting/shipments/{slug}/shipment',
input: ConsolidationInput::class,
processor: ConsolidationInputProcessor::class
),
new Patch(
uriTemplate: '/expediting/shipments/{slug}/status',
inputFormats: ['json' => ['application/merge-patch+json']],
input: ShipmentStatusInput::class,
processor: ShipmentStatusInputProcessor::class
),
]
)]
#[ApiResource(
// FIXME : This does not work well with docker
uriTemplate: '/shipments/{slug}/attachments',
operations: [
new Post(
controller: ShipmentDocumentUploadAction::class,
openapi: new Model\Operation(
requestBody: new Model\RequestBody(
content: new ArrayObject([
'multipart/form-data' => [
'schema' => [
'type' => 'object',
'properties' => [
'file' => [
'type' => 'string',
'format' => 'binary'
]
]
]
]
])
)
),
shortName: 'Upload',
validationContext: ['groups' => ['Default', 'upload:create']],
deserialize: false,
),
],
routePrefix: '/expediting',
)]
#[ApiFilter(SearchFilter::class, properties: [
'reference' => 'ipartial',
])]
class Shipment
{
use Common\Blameable;
use Common\Trackable;
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'IDENTITY')]
#[ORM\SequenceGenerator(sequenceName: 'expediting_shipment_id_seq')]
#[ORM\Column(type: Types::INTEGER)]
#[ApiProperty(identifier: false)]
private ?int $id = null;
#[Gedmo\Slug(fields: ['reference'])]
#[ORM\Column(type: Types::STRING)]
#[ApiProperty(identifier: true)]
private ?string $slug = null;
#[Assert\NotBlank]
#[Assert\Type(type: Types::STRING)]
#[ORM\Column(type: Types::STRING)]
private ?string $reference = null;
#[Assert\NotNull]
#[IsValidEnum(enum: ExpeditingStatus::class)]
#[ORM\Column(type: Types::STRING, nullable: false, enumType: ExpeditingStatus::class, options: ['default' => 'PLANNED'])]
private ?ExpeditingStatus $status = ExpeditingStatus::PLANNED;
/** @var Collection<int, ShippingPlan> */
#[ORM\OneToMany(mappedBy: 'shipment', targetEntity: ShippingPlan::class)]
private Collection $shippingPlans;
/** @var Collection<int, Container> */
#[ORM\OneToMany(mappedBy: 'shipment', targetEntity: Container::class)]
private Collection $containers;
/** @var Collection<int, Package> */
#[ORM\ManyToMany(targetEntity: Package::class, inversedBy: 'shipments')]
#[ORM\JoinTable(name: 'expediting_shipment_package_map')]
#[ORM\JoinColumn(name: 'shipment_id')]
#[ORM\InverseJoinColumn(name: 'package_id')]
private Collection $packages;
/** @var Collection<int, DocumentationKit> */
#[ORM\OneToMany(mappedBy: 'shipment', targetEntity: DocumentationKit::class, cascade: ['persist', 'remove'])]
#[ORM\OrderBy(['id' => 'ASC'])]
#[Ignore]
private Collection $documentationKits;
/** @var Collection<int, File> */
#[ORM\ManyToMany(targetEntity: File::class, cascade: ['persist', 'remove'])]
#[ORM\JoinTable(name: 'expediting_shipment_file_map')]
#[ORM\JoinColumn(name: 'shipment_id')]
#[ORM\InverseJoinColumn(name: 'file_id')]
#[ORM\OrderBy(['id' => 'ASC'])]
private Collection $attachments;
public function __construct()
{
$this->shippingPlans = new ArrayCollection();
$this->containers = new ArrayCollection();
$this->packages = new ArrayCollection();
$this->documentationKits = new ArrayCollection();
$this->attachments = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getReference(): ?string
{
return $this->reference;
}
public function setReference(string $reference): self
{
$this->reference = $reference;
return $this;
}
#[ApiProperty(readableLink: true)]
public function getShippingSegments(): ?Collection
{
$shippingPlan = $this->shippingPlans->first();
if (!$shippingPlan instanceof ShippingPlan) {
return null;
}
return $shippingPlan->getShippingSegments();
}
#[ApiProperty(readableLink: true)]
public function getPlaceOfLoading(): ?Facility
{
$shippingPlan = $this->shippingPlans->first();
if (!$shippingPlan instanceof ShippingPlan) {
return null;
}
return $shippingPlan->getShippingSegments()?->first()?->getPlaceOfLoading();
}
#[ApiProperty(readableLink: true)]
public function getPlaceOfDischarge(): ?Facility
{
$shippingPlan = $this->shippingPlans->first();
if (!$shippingPlan instanceof ShippingPlan) {
return null;
}
return $shippingPlan->getShippingSegments()?->last()?->getPlaceOfDischarge();
}
public function getTransportMode(): ?TransportMode
{
$shippingPlan = $this->shippingPlans->first();
if (!$shippingPlan instanceof ShippingPlan) {
return null;
}
return $shippingPlan->getShippingSegments()?->first()?->getTransportMode();
}
public function getStatus(): ?ExpeditingStatus
{
return $this->status;
}
public function setStatus(?ExpeditingStatus $status): self
{
$this->status = $status;
return $this;
}
/** @return Collection<int, ShippingPlan> */
public function getShippingPlans(): Collection
{
return $this->shippingPlans;
}
public function addShippingPlan(ShippingPlan $shippingPlan): static
{
if (!$this->shippingPlans->contains($shippingPlan)) {
$this->shippingPlans[] = $shippingPlan;
$shippingPlan->setShipment($this);
}
return $this;
}
public function removeShippingPlan(ShippingPlan $shippingPlan): static
{
if ($this->shippingPlans->removeElement($shippingPlan)) {
// set the owning side to null (unless already changed)
if ($shippingPlan->getShipment() === $this) {
$shippingPlan->setShipment(null);
}
}
return $this;
}
/** @return Collection<int, Container> */
public function getContainers(): Collection
{
return $this->containers;
}
public function addContainer(Container $container): static
{
if (!$this->containers->contains($container)) {
$this->containers[] = $container;
$container->setShipment($this);
}
return $this;
}
public function removeContainer(Container $container): static
{
if ($this->containers->removeElement($container)) {
// set the owning side to null (unless already changed)
if ($container->getShipment() === $this) {
$container->setShipment(null);
}
}
return $this;
}
/**
* @return Collection<int, WorkOrder>
*/
public function getWorkOrders(): Collection
{
$workOrders = new ArrayCollection();
foreach ($this->packages as $package) {
foreach ($package->getItems() as $item) {
if ($item instanceof Part) {
$workOrder = $item->getItem()->getFreight()->getWorkOrder();
} elseif ($item instanceof Item) {
$workOrder = $item->getFreight()->getWorkOrder();
} else {
continue;
}
if (!$workOrders->contains($workOrder)) {
$workOrders->add($workOrder);
}
}
}
return $workOrders;
}
/**
* @return Collection<int, Package>
*/
public function getPackages(): Collection
{
return $this->packages;
}
public function addPackage(Package $package): self
{
if (!$this->packages->contains($package)) {
$this->packages->add($package);
}
return $this;
}
public function removePackage(Package $package): self
{
$this->packages->removeElement($package);
return $this;
}
public function hasDocumentationKit(): ?bool
{
return !$this->documentationKits->isEmpty();
}
public function getDocumentationKit(): ?DocumentationKit
{
return !$this->documentationKits->isEmpty()
? $this->documentationKits->last()
: null;
}
/**
* @return Collection<int, DocumentationKit>
*/
public function getDocumentationKits(): Collection
{
return $this->documentationKits;
}
public function addDocumentationKit(DocumentationKit $documentationKit): self
{
if (!$this->documentationKits->contains($documentationKit)) {
$this->documentationKits->add($documentationKit);
$documentationKit->setShipment($this);
}
return $this;
}
public function removeFreight(DocumentationKit $documentationKit): self
{
if ($this->documentationKits->removeElement($documentationKit)) {
// set the owning side to null (unless already changed)
if ($documentationKit->getShipment() === $this) {
$documentationKit->setShipment(null);
}
}
return $this;
}
/**
* @return Collection<int, File>
*/
public function getAttachments(): Collection
{
return $this->attachments;
}
public function addAttachment(File $attachment): self
{
if (!$this->attachments->contains($attachment)) {
$this->attachments->add($attachment);
}
return $this;
}
public function removeAttachment(File $attachment): self
{
$this->attachments->removeElement($attachment);
return $this;
}
}