src/Entity/Common/Company.php line 210

  1. <?php
  2. namespace App\Entity\Common;
  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\Delete;
  8. use ApiPlatform\Metadata\Get;
  9. use ApiPlatform\Metadata\GetCollection;
  10. use ApiPlatform\Metadata\Link;
  11. use ApiPlatform\Metadata\Patch;
  12. use ApiPlatform\Metadata\Post;
  13. use ApiPlatform\Metadata\Put;
  14. use ApiPlatform\OpenApi\Model;
  15. use App\Controller\Upload\CreateAttachmentAction;
  16. use App\Doctrine\Type\Common\CompanyStatus;
  17. use App\Doctrine\Type\Common\CompanyType;
  18. use App\Doctrine\Type\SelectableType;
  19. use App\Dto\Common\AddressInput;
  20. use App\Dto\Common\CompanyExtendedInput;
  21. use App\Dto\Common\CompanyInput;
  22. use App\Dto\Common\LogoInput;
  23. use App\Dto\Common\CompanyStatusInput;
  24. use App\Dto\Sales\CallOffOrderInput;
  25. use App\Dto\User\ContactInput;
  26. use App\Entity\File\Upload;
  27. use App\Entity\Identity\User;
  28. use App\Entity\Places\Address;
  29. use App\Processor\Common\CompanyAddressInputProcessor;
  30. use App\Processor\Common\CompanyContactInputProcessor;
  31. use App\Processor\Common\CompanyInputProcessor;
  32. use App\Processor\Common\LogoInputProcessor;
  33. use App\Processor\Common\CompanyStatusInputProcessor;
  34. use App\Processor\Sales\CallOffOrderInputProcessor;
  35. use App\Provider\Common\TransporterCompanyProvider;
  36. use App\Repository\Common\CompanyRepository;
  37. use App\Validator\IsValidEnumArray\IsValidEnumArray;
  38. use ArrayObject;
  39. use Doctrine\Common\Collections\ArrayCollection;
  40. use Doctrine\Common\Collections\Collection;
  41. use Doctrine\Common\Collections\Criteria;
  42. use Doctrine\DBAL\Types\Types;
  43. use Doctrine\ORM\Mapping as ORM;
  44. use Gedmo\Mapping\Annotation as Gedmo;
  45. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  46. use Symfony\Component\Validator\Constraints as Assert;
  47. #[ORM\Table(name'company')]
  48. #[ORM\Index(columns: ['logo_id'], name'company_logo_id_idx')]
  49. #[ORM\Index(columns: ['parent_id'], name'company_parent_id_idx')]
  50. #[ORM\Index(columns: ['created_by'], name'company_created_by_idx')]
  51. #[ORM\Index(columns: ['updated_by'], name'company_updated_by_idx')]
  52. #[ORM\UniqueConstraint(name'company_slug_key'columns: ['slug'])]
  53. #[ORM\UniqueConstraint(name'company_name_key'columns: ['name'])]
  54. #[ORM\UniqueConstraint(name'company_code_key'columns: ['code'])]
  55. #[ORM\Entity(repositoryClassCompanyRepository::class)]
  56. #[UniqueEntity('slug')]
  57. #[UniqueEntity('name')]
  58. #[UniqueEntity('code')]
  59. #[ApiResource(
  60.     operations: [
  61.         new GetCollection(),
  62.         new Get(providerTransporterCompanyProvider::class),
  63.         new Post(uriTemplate'/companies/{slug}/status'inputFormats: ['json' => ['application/json']], inputCompanyStatusInput::class, processorCompanyStatusInputProcessor::class),
  64.         new Post(uriTemplate'/companies/{slug}/logo'inputFormats: ['multipart' => ['multipart/form-data']], inputLogoInput::class, providerTransporterCompanyProvider::class, processorLogoInputProcessor::class),
  65.         new Patch(inputFormats: ['json' => ['application/merge-patch+json'], 'multipart' => ['multipart/form-data']], providerTransporterCompanyProvider::class),
  66.         new Put(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], providerTransporterCompanyProvider::class),
  67.         new Delete(),
  68.     ],
  69.     inputCompanyInput::class,
  70.     processorCompanyInputProcessor::class,
  71. )]
  72. #[ApiResource(
  73.     operations: [
  74.         new GetCollection(uriTemplate'/providers'),
  75.         new GetCollection(uriTemplate'/consumers'),
  76.         new GetCollection(uriTemplate'/transporters'),
  77.     ],
  78. )]
  79. #[GetCollection(
  80.     uriTemplate'/companies/{parent}/subsidiaries',
  81.     uriVariables: [
  82.         'parent' => new Link(fromProperty'subsidiaries'fromClassCompany::class),
  83.     ],
  84. )]
  85. #[Post(
  86.     uriTemplate'/companies/{slug}/users',
  87.     shortName'User',
  88.     inputContactInput::class,
  89.     processorCompanyContactInputProcessor::class,
  90. )]
  91. #[Post(
  92.     uriTemplate'/companies/{slug}/addresses',
  93.     shortName'Address',
  94.     inputAddressInput::class,
  95.     processorCompanyAddressInputProcessor::class,
  96. )]
  97. #[ApiResource(
  98.     // FIXME : This does not work well with docker
  99.     uriTemplate'/companies/{slug}/attachments',
  100.     operations: [
  101.         new Post(
  102.             controllerCreateAttachmentAction::class,
  103.             openapi: new Model\Operation(
  104.                 requestBody: new Model\RequestBody(
  105.                     content: new ArrayObject([
  106.                         'multipart/form-data' => [
  107.                             'schema' => [
  108.                                 'type' => 'object',
  109.                                 'properties' => [
  110.                                     'file' => [
  111.                                         'type' => 'string',
  112.                                         'format' => 'binary'
  113.                                     ]
  114.                                 ]
  115.                             ]
  116.                         ]
  117.                     ])
  118.                 )
  119.             ),
  120.             shortName'Upload',
  121.             validationContext: ['groups' => ['Default''upload:create']],
  122.             deserializefalse,
  123.         ),
  124.     ],
  125. )]
  126. #[Post(
  127.     uriTemplate'/sales/clients/{slug}/call_off_orders',
  128.     inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']],
  129.     shortName'CallOffOrder',
  130.     inputCallOffOrderInput::class,
  131.     processorCallOffOrderInputProcessor::class,
  132. )]
  133. #[ApiResource(
  134.     uriTemplate'/sales/tenants',
  135.     operations: [
  136.         new GetCollection(),
  137.         new Post(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_tenant'),
  138.         new Post(uriTemplate'/sales/tenants/{slug}'inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_tenant_subsidiary'),
  139.     ],
  140.     inputCompanyExtendedInput::class,
  141.     processorCompanyInputProcessor::class,
  142. )]
  143. #[ApiResource(
  144.     uriTemplate'/sales/clients',
  145.     operations: [
  146.         new GetCollection(),
  147.         new Post(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_client'),
  148.         new Post(uriTemplate'/sales/clients/{slug}'inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_client_subsidiary'),
  149.     ],
  150.     inputCompanyExtendedInput::class,
  151.     processorCompanyInputProcessor::class,
  152. )]
  153. #[ApiResource(
  154.     uriTemplate'/sales/customers',
  155.     operations: [
  156.         new GetCollection(),
  157.         new Post(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_customer'),
  158.         new Post(uriTemplate'/sales/customers/{slug}'inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_customer_subsidiary'),
  159.     ],
  160.     inputCompanyExtendedInput::class,
  161.     processorCompanyInputProcessor::class,
  162. )]
  163. #[ApiResource(
  164.     uriTemplate'/procurement/suppliers',
  165.     operations: [
  166.         new GetCollection(),
  167.         new Post(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_supplier'),
  168.         new Post(uriTemplate'/procurement/suppliers/{slug}'inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_supplier_subsidiary'),
  169.     ],
  170.     inputCompanyExtendedInput::class,
  171.     processorCompanyInputProcessor::class,
  172. )]
  173. #[ApiResource(
  174.     uriTemplate'/purchasing/manufacturers',
  175.     operations: [
  176.         new GetCollection(),
  177.         new Post(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_manufacturer'),
  178.         new Post(uriTemplate'/purchasing/manufacturers/{slug}'inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_manufacturer_subsidiary'),
  179.     ],
  180.     inputCompanyExtendedInput::class,
  181.     processorCompanyInputProcessor::class,
  182. )]
  183. #[ApiResource(
  184.     uriTemplate'/procurement/transporters',
  185.     operations: [
  186.         new GetCollection(),
  187.         new Post(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_transporter'),
  188.         new Post(uriTemplate'/procurement/transporters/{slug}'inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_transporter_subsidiary'),
  189.     ],
  190.     inputCompanyExtendedInput::class,
  191.     processorCompanyInputProcessor::class,
  192. )]
  193. #[ApiResource(
  194.     uriTemplate'/procurement/carriers',
  195.     operations: [
  196.         new GetCollection(),
  197.         new Post(inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_carrier'),
  198.         new Post(uriTemplate'/procurement/carriers/{slug}'inputFormats: ['json' => ['application/json'], 'multipart' => ['multipart/form-data']], name'create_carrier_subsidiary'),
  199.     ],
  200.     inputCompanyExtendedInput::class,
  201.     processorCompanyInputProcessor::class,
  202. )]
  203. #[ApiFilter(SearchFilter::class, properties: [
  204.     'name' => 'ipartial',
  205.     'code' => 'ipartial',
  206. ])]
  207. class Company
  208. {
  209.     use Blameable;
  210.     use Trackable;
  211.     #[ORM\Id]
  212.     #[ORM\GeneratedValue(strategy'IDENTITY')]
  213.     #[ORM\SequenceGenerator(sequenceName'company_id_seq')]
  214.     #[ORM\Column(typeTypes::INTEGER)]
  215.     #[ApiProperty(identifierfalse)]
  216.     private ?int $id null;
  217.     #[Gedmo\Slug(fields: ['name'])]
  218.     #[ORM\Column(typeTypes::STRING)]
  219.     #[ApiProperty(identifiertrue)]
  220.     private ?string $slug null;
  221.     #[Assert\NotBlank]
  222.     #[Assert\Type(typeTypes::STRING)]
  223.     #[ORM\Column(typeTypes::STRING)]
  224.     private ?string $name null;
  225.     #[Assert\Type(typeTypes::STRING)]
  226.     #[ORM\Column(typeTypes::STRING)]
  227.     private ?string $code null;
  228.     #[Assert\Type(typeTypes::STRING)]
  229.     #[ORM\Column(typeTypes::STRINGnullabletrue)]
  230.     private ?string $tradeRegister null;
  231.     #[Assert\Type(typeTypes::STRING)]
  232.     #[ORM\Column(typeTypes::STRINGnullabletrue)]
  233.     private ?string $taxIdentificationNumber null;
  234.     /** @var CompanyType[] $types */
  235.     #[Assert\Count(min1)]
  236.     #[IsValidEnumArray(enumCompanyType::class)]
  237.     #[ORM\Column(typeSelectableType::NAMEnullabletrueenumTypeCompanyType::class)]
  238.     private array $types = [];
  239.     #[ORM\Column(typeTypes::JSONnullabletrue)]
  240.     private ?array $servedContinents = [];
  241.     #[ORM\Column(typeTypes::JSONnullabletrue)]
  242.     private ?array $servedCountries = [];
  243.     public ?array $serviceArea = [];
  244.     #[Assert\NotNull]
  245.     #[IsValidEnumArray(enumCompanyStatus::class)]
  246.     #[ORM\Column(typeTypes::STRINGenumTypeCompanyStatus::class, options: ['default' => 'ACTIVE'])]
  247.     private ?CompanyStatus $status CompanyStatus::ACTIVE;
  248.     #[ORM\ManyToOne(targetEntityUpload::class, cascade: ['persist''remove'])]
  249.     #[ORM\JoinColumn(name'logo_id'referencedColumnName'id')]
  250.     #[ApiProperty(readableLinktrue)]
  251.     private ?Upload $logo null;
  252.     /** @var Collection<int, Address> */
  253.     #[ORM\OneToMany(mappedBy'owner'targetEntityAddress::class, cascade: ['persist''remove'])]
  254.     private Collection $addresses;
  255.     /** @var Collection<int, Upload> */
  256.     #[ORM\ManyToMany(targetEntityUpload::class, cascade: ['persist''remove'])]
  257.     #[ORM\JoinTable(name'company_file_map')]
  258.     #[ORM\JoinColumn(name'company_id')]
  259.     #[ORM\InverseJoinColumn(name'file_id')]
  260.     private Collection $attachments;
  261.     #[ORM\ManyToOne(targetEntityCompany::class, inversedBy'subsidiaries')]
  262.     #[ORM\JoinColumn(name'parent_id'referencedColumnName'id')]
  263.     private ?Company $parent null;
  264.     #[ORM\OneToMany(mappedBy'parent'targetEntityCompany::class)]
  265.     private Collection $subsidiaries;
  266.     /** @var Collection<int, User> */
  267.     #[ORM\OneToMany(mappedBy'company'targetEntityUser::class, cascade: ['persist''remove'])]
  268.     private Collection $users;
  269.     public function __construct()
  270.     {
  271.         $this->addresses = new ArrayCollection();
  272.         $this->attachments = new ArrayCollection();
  273.         $this->subsidiaries = new ArrayCollection();
  274.         $this->users = new ArrayCollection();
  275.     }
  276.     public function getId(): ?int
  277.     {
  278.         return $this->id;
  279.     }
  280.     public function getSlug(): ?string
  281.     {
  282.         return $this->slug;
  283.     }
  284.     public function setSlug(string $slug): self
  285.     {
  286.         $this->slug $slug;
  287.         return $this;
  288.     }
  289.     public function getName(): ?string
  290.     {
  291.         return $this->name;
  292.     }
  293.     public function setName(string $name): self
  294.     {
  295.         $this->name $name;
  296.         return $this;
  297.     }
  298.     public function getCode(): ?string
  299.     {
  300.         return $this->code;
  301.     }
  302.     public function setCode(string $code): self
  303.     {
  304.         $this->code $code;
  305.         return $this;
  306.     }
  307.     public function getTradeRegister(): ?string
  308.     {
  309.         return $this->tradeRegister;
  310.     }
  311.     public function setTradeRegister(?string $tradeRegister): self
  312.     {
  313.         $this->tradeRegister $tradeRegister;
  314.         return $this;
  315.     }
  316.     public function getTaxIdentificationNumber(): ?string
  317.     {
  318.         return $this->taxIdentificationNumber;
  319.     }
  320.     public function setTaxIdentificationNumber(?string $taxIdentificationNumber): self
  321.     {
  322.         $this->taxIdentificationNumber $taxIdentificationNumber;
  323.         return $this;
  324.     }
  325.     public function getTypes(): array
  326.     {
  327.         return $this->types;
  328.     }
  329.     public function addType(CompanyType $type): static
  330.     {
  331.         if (!in_array($type$this->types)) {
  332.             $this->types []= $type;
  333.         }
  334.         return $this;
  335.     }
  336.     public function setTypes($types): self
  337.     {
  338.         $this->types $types;
  339.         return $this;
  340.     }
  341.     public function removeType(CompanyType $type): static
  342.     {
  343.         $key array_search($type$this->typestrue);
  344.         if ($key !== false) {
  345.             unset($this->types[$key]);
  346.         }
  347.         return $this;
  348.     }
  349.     public function getServedContinents(): ?array
  350.     {
  351.         return $this->servedContinents;
  352.     }
  353.     public function setServedContinents(?array $servedContinents): self
  354.     {
  355.         $this->servedContinents $servedContinents;
  356.         return $this;
  357.     }
  358.     public function getServedCountries(): ?array
  359.     {
  360.         return $this->servedCountries;
  361.     }
  362.     public function setServedCountries(?array $servedCountries): self
  363.     {
  364.         $this->servedCountries $servedCountries;
  365.         return $this;
  366.     }
  367.     public function getStatus(): ?CompanyStatus
  368.     {
  369.         return $this->status;
  370.     }
  371.     public function setStatus(CompanyStatus $status): self
  372.     {
  373.         $this->status $status;
  374.         return $this;
  375.     }
  376.     #[ApiProperty(readableLinktrue)]
  377.     public function getMainAddress(): ?Address
  378.     {
  379.         $criteria Criteria::create();
  380.         $criteria->andWhere(Criteria::expr()->eq('main'true));
  381.         $entities $this->addresses->matching($criteria);
  382.         return (count($entities) && $entities[0] instanceof Address)
  383.             ? $entities[0]
  384.             : null;
  385.     }
  386.     /** @return Collection<int, Address> */
  387.     public function getAddresses(): Collection
  388.     {
  389.         return $this->addresses;
  390.     }
  391.     public function addAddress(Address $address): static
  392.     {
  393.         if (!$this->addresses->contains($address)) {
  394.             $this->addresses[] = $address;
  395.             $address->setOwner($this);
  396.         }
  397.         return $this;
  398.     }
  399.     public function removeAddress(Address $address): static
  400.     {
  401.         if ($this->addresses->removeElement($address)) {
  402.             // set the owning side to null (unless already changed)
  403.             if ($address->getOwner() === $this) {
  404.                 $address->setOwner(null);
  405.             }
  406.         }
  407.         return $this;
  408.     }
  409.     /**
  410.      * @return Collection<int, Upload>
  411.      */
  412.     public function getAttachments(): Collection
  413.     {
  414.         return $this->attachments;
  415.     }
  416.     public function addAttachment(Upload $attachment): self
  417.     {
  418.         if (!$this->attachments->contains($attachment)) {
  419.             $this->attachments->add($attachment);
  420.         }
  421.         return $this;
  422.     }
  423.     public function removeAttachment(Upload $attachment): self
  424.     {
  425.         $this->attachments->removeElement($attachment);
  426.         return $this;
  427.     }
  428.     public function getParent(): ?self
  429.     {
  430.         return $this->parent;
  431.     }
  432.     public function setParent(?self $parent): self
  433.     {
  434.         $this->parent $parent;
  435.         return $this;
  436.     }
  437.     /**
  438.      * @return Collection<int, Company>
  439.      */
  440.     public function getSubsidiaries(): Collection
  441.     {
  442.         return $this->subsidiaries;
  443.     }
  444.     public function addSubsidiary(Company $subsidiary): self
  445.     {
  446.         if (!$this->subsidiaries->contains($subsidiary)) {
  447.             $this->subsidiaries->add($subsidiary);
  448.             $subsidiary->setParent($this);
  449.         }
  450.         return $this;
  451.     }
  452.     public function removeSubsidiary(Company $subsidiary): self
  453.     {
  454.         if ($this->subsidiaries->removeElement($subsidiary)) {
  455.             // set the owning side to null (unless already changed)
  456.             if ($subsidiary->getParent() === $this) {
  457.                 $subsidiary->setParent(null);
  458.             }
  459.         }
  460.         return $this;
  461.     }
  462.     /**
  463.      * @return Collection<int, User>
  464.      */
  465.     public function getUsers(): Collection
  466.     {
  467.         return $this->users;
  468.     }
  469.     public function addUser(User $user): self
  470.     {
  471.         if (!$this->users->contains($user)) {
  472.             $this->users->add($user);
  473.             $user->setCompany($this);
  474.         }
  475.         return $this;
  476.     }
  477.     public function removeUser(User $user): self
  478.     {
  479.         if ($this->subsidiaries->removeElement($user)) {
  480.             // set the owning side to null (unless already changed)
  481.             if ($user->getCompany() === $this) {
  482.                 $user->setCompany(null);
  483.             }
  484.         }
  485.         return $this;
  486.     }
  487.     public function getLogo(): ?Upload
  488.     {
  489.         return $this->logo;
  490.     }
  491.     public function setLogo(?Upload $logo): self
  492.     {
  493.         $this->logo $logo;
  494.         return $this;
  495.     }
  496. }