src/Entity/Sales/Contract.php line 101

  1. <?php
  2. namespace App\Entity\Sales;
  3. use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
  4. use ApiPlatform\Metadata\ApiFilter;
  5. use ApiPlatform\Metadata\ApiProperty;
  6. use ApiPlatform\Metadata\ApiResource;
  7. use ApiPlatform\Metadata\GetCollection;
  8. use ApiPlatform\Metadata\Link;
  9. use ApiPlatform\Metadata\Post;
  10. use ApiPlatform\OpenApi\Model;
  11. use App\Controller\Upload\CreateAttachmentAction;
  12. use App\Doctrine\Type\Sales\ContractStatus;
  13. use App\Doctrine\Type\Sales\ContractType;
  14. use App\Dto\Sales\ContractInput;
  15. use App\Dto\Sales\ContractStatusInput;
  16. use App\Entity\Common\Blameable;
  17. use App\Entity\Common\Company;
  18. use App\Entity\Common\Trackable;
  19. use App\Entity\File\Upload;
  20. use App\Processor\Sales\ContractInputProcessor;
  21. use App\Processor\Sales\ContractStatusInputProcessor;
  22. use ArrayObject;
  23. use DateTimeInterface;
  24. use Doctrine\Common\Collections\ArrayCollection;
  25. use Doctrine\Common\Collections\Collection;
  26. use Doctrine\DBAL\Types\Types;
  27. use Doctrine\ORM\Mapping as ORM;
  28. use Gedmo\Mapping\Annotation as Gedmo;
  29. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  30. use Symfony\Component\Validator\Constraints as Assert;
  31. #[ORM\Table(name'contract')]
  32. #[ORM\Index(columns: ['tenant_id'], name'contract_tenant_id_idx')]
  33. #[ORM\Index(columns: ['client_id'], name'contract_client_id_idx')]
  34. #[ORM\Index(columns: ['created_by'], name'contract_created_by_idx')]
  35. #[ORM\Index(columns: ['updated_by'], name'contract_updated_by_idx')]
  36. #[ORM\UniqueConstraint(name'contract_slug_key'columns: ['slug'])]
  37. #[ORM\UniqueConstraint(name'contract_number_key'columns: ['number'])]
  38. #[ORM\Entity]
  39. #[UniqueEntity('number')]
  40. #[ApiResource(
  41.     routePrefix'/sales',
  42.     inputContractInput::class,
  43.     processorContractInputProcessor::class,
  44. )]
  45. #[ApiResource(
  46.     operations: [
  47.         new Post(
  48.             uriTemplate'/sales/contracts/{slug}/status',
  49.             inputContractStatusInput::class,
  50.             processorContractStatusInputProcessor::class,
  51.         ),
  52.     ],
  53. )]
  54. #[ApiResource(
  55.     uriTemplate'/sales/assets/{asset}/contracts',
  56.     operations: [
  57.         new GetCollection(),
  58.     ],
  59.     uriVariables: [
  60.         'asset' => new Link(toProperty'assets'fromClassAsset::class),
  61.     ],
  62. )]
  63. #[ApiResource(
  64.     // FIXME : This does not work well with docker
  65.     uriTemplate'/sales/contracts/{slug}/attachments',
  66.     operations: [
  67.         new Post(
  68.             controllerCreateAttachmentAction::class,
  69.             openapi: new Model\Operation(
  70.                 requestBody: new Model\RequestBody(
  71.                     content: new ArrayObject([
  72.                         'multipart/form-data' => [
  73.                             'schema' => [
  74.                                 'type' => 'object',
  75.                                 'properties' => [
  76.                                     'file' => [
  77.                                         'type' => 'string',
  78.                                         'format' => 'binary'
  79.                                     ]
  80.                                 ]
  81.                             ]
  82.                         ]
  83.                     ])
  84.                 )
  85.             ),
  86.             shortName'Upload',
  87.             validationContext: ['groups' => ['Default''upload:create']],
  88.             deserializefalse
  89.         )
  90.     ],
  91. )]
  92. #[ApiFilter(SearchFilter::class, properties: [
  93.     'number' => 'ipartial',
  94.     'client.name' => 'exact',
  95.     'client.code' => 'exact',
  96.     'status' => 'exact',
  97. ])]
  98. class Contract
  99. {
  100.     use Blameable;
  101.     use Trackable;
  102.     #[ORM\Id]
  103.     #[ORM\GeneratedValue(strategy'IDENTITY')]
  104.     #[ORM\SequenceGenerator(sequenceName'contract_id_seq')]
  105.     #[ORM\Column(typeTypes::INTEGER)]
  106.     #[ApiProperty(identifierfalse)]
  107.     private ?int $id null;
  108.     #[Gedmo\Slug(fields: ['number'])]
  109.     #[ORM\Column(typeTypes::STRING)]
  110.     #[ApiProperty(identifiertrue)]
  111.     private string $slug;
  112.     #[Assert\Length(min5)]
  113.     #[ORM\Column(typeTypes::STRING)]
  114.     private ?string $number null;
  115.     #[Assert\NotNull]
  116.     #[Assert\NotEqualTo(propertyPath'client')]
  117.     #[ORM\ManyToOne(targetEntityCompany::class)]
  118.     #[ORM\JoinColumn(name'tenant_id'nullablefalse)]
  119.     private ?Company $tenant null;
  120.     #[Assert\NotNull]
  121.     #[ORM\ManyToOne(targetEntityCompany::class)]
  122.     #[ORM\JoinColumn(name'client_id'nullablefalse)]
  123.     #[ApiProperty(readableLinktrue)]
  124.     private ?Company $client null;
  125.     /** @var Collection<int, Asset> */
  126.     #[ORM\ManyToMany(targetEntityAsset::class, inversedBy'contracts')]
  127.     #[ORM\JoinTable(name'contract_asset_map')]
  128.     #[ORM\JoinColumn(name'contract_id')]
  129.     #[ORM\InverseJoinColumn(name'asset_id')]
  130.     private Collection $assets;
  131.     /** @var Collection<int, WorkOrder> */
  132.     #[ApiProperty(readablefalse)]
  133.     #[ORM\OneToMany(mappedBy'contract'targetEntityWorkOrder::class)]
  134.     private Collection $workOrders;
  135.     /** @var Collection<int, CallOffOrder> */
  136.     #[ORM\ManyToMany(targetEntityCallOffOrder::class, mappedBy'contracts')]
  137.     private Collection $callOffOrders;
  138.     /** @var Collection<int, Upload> */
  139.     #[ORM\ManyToMany(targetEntityUpload::class)]
  140.     #[ORM\JoinTable(name'contract_file_map')]
  141.     #[ORM\JoinColumn(name'contract_id')]
  142.     #[ORM\InverseJoinColumn(name'file_id')]
  143.     #[ApiProperty(readableLinktrue)]
  144.     private Collection $attachments;
  145.     #[Assert\NotNull]
  146.     #[ORM\Column(typeTypes::DATE_MUTABLEoptions: ['default' => 'CURRENT_DATE'])]
  147.     private ?DateTimeInterface $startingOn null;
  148.     #[Assert\GreaterThan(propertyPath'startingOn')]
  149.     #[ORM\Column(typeTypes::DATE_MUTABLEnullabletrue)]
  150.     private ?DateTimeInterface $endingOn null;
  151.     #[Assert\NotNull]
  152.     #[ORM\Column(typeTypes::STRINGenumTypeContractType::class)]
  153.     private ?ContractType $type null;
  154.     #[Assert\NotNull]
  155.     #[ORM\Column(typeTypes::STRINGenumTypeContractStatus::class, options: ['default' => 'ONGOING'])]
  156.     private ?ContractStatus $status ContractStatus::ONGOING;
  157.     public function __construct()
  158.     {
  159.         $this->assets = new ArrayCollection();
  160.         $this->attachments = new ArrayCollection();
  161.         $this->callOffOrders = new ArrayCollection();
  162.         $this->workOrders = new ArrayCollection();
  163.     }
  164.     public function getId(): ?int
  165.     {
  166.         return $this->id;
  167.     }
  168.     public function getSlug(): ?string
  169.     {
  170.         return $this->slug;
  171.     }
  172.     public function setSlug(string $slug): self
  173.     {
  174.         $this->slug $slug;
  175.         return $this;
  176.     }
  177.     public function getNumber(): ?string
  178.     {
  179.         return $this->number;
  180.     }
  181.     public function setNumber(?string $number): self
  182.     {
  183.         $this->number $number;
  184.         return $this;
  185.     }
  186.     public function getTenant(): ?Company
  187.     {
  188.         return $this->tenant;
  189.     }
  190.     public function setTenant(?Company $tenant): self
  191.     {
  192.         $this->tenant $tenant;
  193.         return $this;
  194.     }
  195.     public function getClient(): ?Company
  196.     {
  197.         return $this->client;
  198.     }
  199.     public function setClient(?Company $client): self
  200.     {
  201.         $this->client $client;
  202.         return $this;
  203.     }
  204.     /**
  205.      * @return Collection<int, Asset>
  206.      */
  207.     public function getAssets(): Collection
  208.     {
  209.         return $this->assets;
  210.     }
  211.     public function addAsset(Asset $asset): self
  212.     {
  213.         if (!$this->assets->contains($asset)) {
  214.             $this->assets->add($asset);
  215.         }
  216.         return $this;
  217.     }
  218.     public function removeAsset(Asset $asset): self
  219.     {
  220.         $this->assets->removeElement($asset);
  221.         return $this;
  222.     }
  223.     /** @return Collection<int, WorkOrder> */
  224.     public function getWorkOrders(): Collection
  225.     {
  226.         return $this->workOrders;
  227.     }
  228.     public function addWorkOrder(WorkOrder $workOrder): static
  229.     {
  230.         if (!$this->workOrders->contains($workOrder)) {
  231.             $this->workOrders[] = $workOrder;
  232.             $workOrder->setContract($this);
  233.         }
  234.         return $this;
  235.     }
  236.     public function removeWorkOrder(WorkOrder $workOrder): static
  237.     {
  238.         if ($this->workOrders->removeElement($workOrder)) {
  239.             // set the owning side to null (unless already changed)
  240.             if ($workOrder->getContract() === $this) {
  241.                 $workOrder->setContract(null);
  242.             }
  243.         }
  244.         return $this;
  245.     }
  246.     /**
  247.      * @return Collection<int, CallOffOrder>
  248.      */
  249.     public function getCallOffOrders(): Collection
  250.     {
  251.         return $this->callOffOrders;
  252.     }
  253.     public function addCallOffOrder(CallOffOrder $callOffOrder): self
  254.     {
  255.         if (!$this->callOffOrders->contains($callOffOrder)) {
  256.             $this->callOffOrders->add($callOffOrder);
  257.             $callOffOrder->addContract($this);
  258.         }
  259.         return $this;
  260.     }
  261.     public function removeCallOffOrder(CallOffOrder $callOffOrder): self
  262.     {
  263.         if ($this->callOffOrders->removeElement($callOffOrder)) {
  264.             $callOffOrder->removeContract($this);
  265.         }
  266.         return $this;
  267.     }
  268.     /**
  269.      * @return Collection<int, Upload>
  270.      */
  271.     public function getAttachments(): Collection
  272.     {
  273.         return $this->attachments;
  274.     }
  275.     public function addAttachment(Upload $attachment): self
  276.     {
  277.         if (!$this->attachments->contains($attachment)) {
  278.             $this->attachments->add($attachment);
  279.         }
  280.         return $this;
  281.     }
  282.     public function removeAttachment(Upload $attachment): self
  283.     {
  284.         $this->attachments->removeElement($attachment);
  285.         return $this;
  286.     }
  287.     public function getStartingOn(): DateTimeInterface
  288.     {
  289.         return $this->startingOn;
  290.     }
  291.     public function setStartingOn(DateTimeInterface $startingOn): self
  292.     {
  293.         $this->startingOn $startingOn;
  294.         return $this;
  295.     }
  296.     public function getEndingOn(): ?DateTimeInterface
  297.     {
  298.         return $this->endingOn;
  299.     }
  300.     public function setEndingOn(?DateTimeInterface $endingOn): self
  301.     {
  302.         $this->endingOn $endingOn;
  303.         return $this;
  304.     }
  305.     public function getType(): ?ContractType
  306.     {
  307.         return $this->type;
  308.     }
  309.     public function setType(ContractType $type): self
  310.     {
  311.         $this->type $type;
  312.         return $this;
  313.     }
  314.     public function getStatus(): ?ContractStatus
  315.     {
  316.         return $this->status;
  317.     }
  318.     public function setStatus(ContractStatus $status): self
  319.     {
  320.         $this->status $status;
  321.         return $this;
  322.     }
  323. }