src/Model/Product/Product.php line 210

Open in your IDE?
  1. <?php
  2. namespace App\Model\Product;
  3. use ApiPlatform\Core\Annotation\ApiFilter;
  4. use ApiPlatform\Core\Annotation\ApiProperty;
  5. use ApiPlatform\Core\Annotation\ApiResource;
  6. use App\Model\Category\Category;
  7. use App\Model\CustomerFile\CustomerFile;
  8. use App\Model\IriNormalizableInterface;
  9. use App\Model\NormalizeAsIRITrait;
  10. use App\Model\Params\Params;
  11. use App\Model\ProductSpecificField\ProductSpecificField;
  12. use App\Model\SpecificField\SpecificField;
  13. use App\Model\SpecificFieldsAwareInterface;
  14. use App\Model\Traits\ImportableObjectTrait;
  15. use App\Model\Traits\TimestampableTrait;
  16. use App\Model\Unit\Unit;
  17. use App\Model\Vat\Vat;
  18. use App\Model\Warranty\Warranty;
  19. use App\V4\Entity\ActionableEntityInterface;
  20. use App\V4\Model\ProductConfiguration\ProductConfiguration;
  21. use Doctrine\Common\Collections\ArrayCollection;
  22. use Doctrine\Common\Collections\Collection;
  23. use Symfony\Component\Serializer\Annotation\Groups;
  24. use Symfony\Component\Serializer\Annotation\MaxDepth;
  25. use Symfony\Component\Serializer\Annotation\SerializedName;
  26. use Symfony\Component\Validator\Constraints as Assert;
  27. //Ici le formulaire d'édition est en POST, car il nécessite du form-data qui ne fonctionne pas avec PATCH ou PUT
  28. /**
  29.  * @ApiResource(
  30.  *     attributes={
  31.  *         "api_allow_update": true
  32.  *     },
  33.  *     collectionOperations={
  34.  *         "get": {
  35.  *             "normalization_context": {
  36.  *                  "groups": {"product:list"}
  37.  *             },
  38.  *             "security": "is_granted(constant('App\\Voters\\ProductVoter::PRODUCT_SHOW_LIST'), 'App\Voters\ProductVoter')"
  39.  *         },
  40.  *         "post": {
  41.  *             "deserialize": false,
  42.  *             "write": false,
  43.  *             "controller": "App\Controller\Product\ProductDataPersisterAction",
  44.  *             "input_formats": {
  45.  *                 "multipart": {"multipart/form-data"}
  46.  *             },
  47.  *             "normalization_context": {
  48.  *                  "groups": {"product:read"}
  49.  *             },
  50.  *             "denormalization_context": {
  51.  *                  "groups": {}
  52.  *             }
  53.  *         },
  54.  *         "get_form": {
  55.  *             "method": "GET",
  56.  *             "path": "/products/form",
  57.  *             "controller": App\Controller\Product\GetProductFormAction::class
  58.  *         },
  59.  *         "get_search": {
  60.  *             "method": "GET",
  61.  *             "path": "/products/search/form",
  62.  *             "controller": App\Controller\Product\GetProductSearchFormAction::class,
  63.  *         },
  64.  *         "post_search": {
  65.  *             "method": "POST",
  66.  *             "deserialize": false,
  67.  *             "path": "/products/search/form",
  68.  *             "normalization_context": {
  69.  *                  "groups": {"product:list"}
  70.  *             },
  71.  *             "controller": App\Controller\Product\PostProductSearchFormAction::class,
  72.  *             "validate": false,
  73.  *         },
  74.  *         "post_export_request": {
  75.  *              "method": "POST",
  76.  *              "path": "/v4/export/product",
  77.  *              "controller": App\V4\Action\Export\EntityExportRequestAction::class,
  78.  *              "swagger_context": {
  79.  *                  "summary": "Demande de création d'export de produits",
  80.  *                  "description": "Demande de création d'export de produits où 'ids' sont les ids des produits et 'fields' les champs souhaités",
  81.  *                  "parameters": {
  82.  *                      {
  83.  *                          "in": "body",
  84.  *                          "name": "body",
  85.  *                          "schema": {
  86.  *                              "type": "object",
  87.  *                              "properties": {
  88.  *                                  "ids": {
  89.  *                                      "type": "array",
  90.  *                                      "items": {"type": "string"}
  91.  *                                  },
  92.  *                                  "fields": {
  93.  *                                       "type": "array",
  94.  *                                       "items": {"type": "string"}
  95.  *                                  }
  96.  *                              }
  97.  *                          }
  98.  *                      }
  99.  *                  },
  100.  *                  "responses": {
  101.  *                      "201": {
  102.  *                          "description": "Création de l'export avec succès",
  103.  *                          "schema": {
  104.  *                              "type": "object",
  105.  *                              "properties": {
  106.  *                                  "message": {"type": "string", "example": "export_request_created"},
  107.  *                              }
  108.  *                          }
  109.  *                      },
  110.  *                      "400": {
  111.  *                          "description": "Utilisateur non trouvé ou champs 'fields' ou 'ids' manquant dans le body request",
  112.  *                          "schema": {
  113.  *                              "type": "object",
  114.  *                              "properties": {
  115.  *                                  "message": {"type": "string", "example": "user_not_found or missing_fields_or_ids"},
  116.  *                              }
  117.  *                          }
  118.  *                      },
  119.  *                      "422": {
  120.  *                          "description": "Les champs 'fields' ou 'ids' du body request sont vides ou l'entité demandée est invalide",
  121.  *                          "schema": {
  122.  *                              "type": "object",
  123.  *                              "properties": {
  124.  *                                  "message": {"type": "string", "example": "empty_fields_or_ids or entity_not_valid"},
  125.  *                              }
  126.  *                          }
  127.  *                      },
  128.  *                  },
  129.  *              }
  130.  *          },
  131.  *          "post_export_download": {
  132.  *              "method": "POST",
  133.  *              "path": "/v4/export/download/product/{id}",
  134.  *              "controller": App\V4\Action\Export\EntityExportDownloadAction::class,
  135.  *              "swagger_context": {
  136.  *                  "summary": "Demande de téléchargement d'un export produits",
  137.  *                  "description": "Demande de téléchargement d'un export produits ou 'id' est le nom du fichier d'export",
  138.  *                  "requestBody": {},
  139.  *                  "parameters": {
  140.  *                      {
  141.  *                          "in": "path",
  142.  *                          "name": "id",
  143.  *                          "type": "string",
  144.  *                          "required": "true"
  145.  *                      }
  146.  *                  },
  147.  *                  "responses": {
  148.  *                      "200": {
  149.  *                          "description": "Téléchargement de l'export réalisé avec succès"
  150.  *                      },
  151.  *                      "401": {
  152.  *                          "description": "Utilisateur non trouvé ou non connecté",
  153.  *                          "schema": {
  154.  *                              "type": "object",
  155.  *                              "properties": {
  156.  *                                  "message": {"type": "string", "example": "need_authenticated"},
  157.  *                              }
  158.  *                          }
  159.  *                      },
  160.  *                      "404": {
  161.  *                          "description": "Fichier introuvable",
  162.  *                          "schema": {
  163.  *                              "type": "object",
  164.  *                              "properties": {
  165.  *                                  "message": {"type": "string", "example": "export_not_found"},
  166.  *                              }
  167.  *                          }
  168.  *                      },
  169.  *                  },
  170.  *              }
  171.  *          }
  172.  *     },
  173.  *     itemOperations={
  174.  *         "get": {
  175.  *             "normalization_context": {
  176.  *                  "groups": {"product:read"}
  177.  *             },
  178.  *             "security": "is_granted(constant('App\\Voters\\ProductVoter::PRODUCT_ADD_EDIT'), 'App\Voters\ProductVoter')"
  179.  *         },
  180.  *         "get_form": {
  181.  *             "method": "GET",
  182.  *             "path": "/products/{id}/form",
  183.  *             "controller": App\Controller\Product\GetProductFormAction::class
  184.  *         },
  185.  *         "put": {
  186.  *             "deserialize": false,
  187.  *             "write": false,
  188.  *             "method": "POST",
  189.  *             "controller": "App\Controller\Product\ProductDataPersisterAction",
  190.  *             "input_formats": {
  191.  *                 "multipart": {"multipart/form-data"}
  192.  *             },
  193.  *             "normalization_context": {
  194.  *                  "groups": {"product:read"}
  195.  *             },
  196.  *             "denormalization_context": {
  197.  *                  "groups": {}
  198.  *             }
  199.  *         },
  200.  *         "delete"
  201.  *     }
  202.  * )
  203.  *
  204.  * @ApiFilter(App\Filters\PagingFilter::class)
  205.  */
  206. class Product implements IriNormalizableInterfaceSpecificFieldsAwareInterfaceActionableEntityInterface
  207. {
  208.     public const SPECIFIC_FIELD_CLASS_NAME ProductSpecificField::class;
  209.     public const SUBSCRIPTION_UNIT_HOUR 'hours';
  210.     public const SUBSCRIPTION_UNIT_DAY 'days';
  211.     public const SUBSCRIPTION_UNIT_MONTH 'months';
  212.     public const SUBSCRIPTION_UNIT_YEAR 'years';
  213.     public const SUBSCRIPTION_UNITS = [
  214.         self::SUBSCRIPTION_UNIT_HOUR,
  215.         self::SUBSCRIPTION_UNIT_DAY,
  216.         self::SUBSCRIPTION_UNIT_MONTH,
  217.         self::SUBSCRIPTION_UNIT_YEAR,
  218.     ];
  219.     use TimestampableTrait;
  220.     use ImportableObjectTrait;
  221.     use NormalizeAsIRITrait;
  222.     /**
  223.      * @var string|null
  224.      *
  225.      * @ApiProperty(identifier=true)
  226.      * @Groups({"list", "product:list", "product:read"})
  227.      */
  228.     private $id;
  229.     /**
  230.      * @var string|null
  231.      *
  232.      * @Groups({"product:list", "product:read"})
  233.      */
  234.     private $externalId;
  235.     /**
  236.      * @var string|null
  237.      */
  238.     private $customerId;
  239.     /**
  240.      * @var Vat|null
  241.      *
  242.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  243.      */
  244.     private $vat;
  245.     /**
  246.      * @var Unit|null
  247.      *
  248.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  249.      */
  250.     private $unit;
  251.     /**
  252.      * @var Category[]|null
  253.      *
  254.      * @Groups({"list", "product:list", "product:read", "product:write", "product:update"})
  255.      * @MaxDepth(1)
  256.      */
  257.     private $categories;
  258.     /**
  259.      * @var Warranty|null
  260.      *
  261.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  262.      */
  263.     private $warranty;
  264.     /**
  265.      * @var SpecificField[]|Collection
  266.      *
  267.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  268.      */
  269.     private $specificFields;
  270.     /**
  271.      * @var string|null
  272.      *
  273.      * @Assert\Length(max="255")
  274.      * @Assert\NotBlank()
  275.      *
  276.      * @Groups({"list", "product:list", "product:read", "product:write", "product:update"})
  277.      */
  278.     private $name;
  279.     /**
  280.      * @var string|null
  281.      *
  282.      * @Assert\Length(max="255")
  283.      *
  284.      * @Groups({"list", "product:list", "product:read", "product:write", "product:update"})
  285.      */
  286.     private $shortDescription;
  287.     /**
  288.      * @var string|null
  289.      *
  290.      * @Assert\Length(max="255")
  291.      *
  292.      * @Groups({"list", "product:list", "product:read", "product:write", "product:update"})
  293.      */
  294.     private $reference;
  295.     /**
  296.      * @var string|null
  297.      *
  298.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  299.      */
  300.     private $priceExcludingVat;
  301.     /**
  302.      * @var string|null
  303.      *
  304.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  305.      */
  306.     private $sellingPriceExcludingVat;
  307.     /**
  308.      * @var string|null
  309.      *
  310.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  311.      */
  312.     private $imageId;
  313.     /**
  314.      * @var CustomerFile|null
  315.      *
  316.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  317.      */
  318.     private $imageFile;
  319.     /**
  320.      * @var string|null
  321.      *
  322.      * @Assert\Length(max="255")
  323.      *
  324.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  325.      */
  326.     private $serialNumber;
  327.     /**
  328.      * @var bool
  329.      *
  330.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  331.      */
  332.     private $isComponent false;
  333.     /**
  334.      * @var int|null
  335.      *
  336.      * @Assert\GreaterThan(0)
  337.      *
  338.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  339.      */
  340.     private $stockQty 1;
  341.     /**
  342.      * @var CustomerFile[]
  343.      *
  344.      * @Groups({"product:list", "product:read", "product:write", "product:update"})
  345.      */
  346.     private $customerFiles;
  347.     /**
  348.      * @var ProductConfiguration|null
  349.      *
  350.      * @Groups({"list", "product:list", "product:read", "product:write", "product:update"})
  351.      */
  352.     private $productConfiguration;
  353.     /**
  354.      * @var int|null
  355.      *
  356.      * @Groups({
  357.      *     "list",
  358.      *     "product:list", "product:read",
  359.      *     "product:write", "product:update",
  360.      * })
  361.      */
  362.     private $subscriptionValue;
  363.     /**
  364.      * @var string|null
  365.      *
  366.      * @Groups({
  367.      *     "list",
  368.      *     "product:list", "product:read",
  369.      *     "product:write", "product:update",
  370.      * })
  371.      */
  372.     private $subscriptionUnit;
  373.     /**
  374.      * @var string|null
  375.      *
  376.      * @Groups({
  377.      *     "list",
  378.      *     "product:list", "product:read",
  379.      *     "product:write", "product:update",
  380.      * })
  381.      */
  382.     private $quoteSection;
  383.     /**
  384.      * @var string|null
  385.      *
  386.      * @Groups({
  387.      *      "list",
  388.      *      "product:list", "product:read",
  389.      *      "product:write", "product:update",
  390.      *  })
  391.      */
  392.     private $description;
  393.     public function __construct()
  394.     {
  395.         $this->specificFields = new ArrayCollection();
  396.         $this->categories = new ArrayCollection();
  397.     }
  398.     /**
  399.      * @Assert\IsTrue(message="subscription_unit_empty_and_not_value");
  400.      **/
  401.     public function isCorrectSubscriptionValueAndUnit(): bool
  402.     {
  403.         if (!$this->isSubscriptionProduct()) {
  404.             return true;
  405.         }
  406.         return null !== $this->subscriptionValue && null !== $this->subscriptionUnit;
  407.     }
  408.     /**
  409.      * @return bool
  410.      */
  411.     public function isSubscriptionProduct(): bool
  412.     {
  413.         return null !== $this->subscriptionValue || null !== $this->subscriptionUnit;
  414.     }
  415.     /**
  416.      * @return string
  417.      */
  418.     public function getId(): ?string
  419.     {
  420.         return $this->id;
  421.     }
  422.     /**
  423.      * @param string|null $id
  424.      *
  425.      * @return self
  426.      */
  427.     public function setId(?string $id): self
  428.     {
  429.         $this->id $id;
  430.         return $this;
  431.     }
  432.     /**
  433.      * @return string|null
  434.      */
  435.     public function getExternalId(): ?string
  436.     {
  437.         return $this->externalId;
  438.     }
  439.     /**
  440.      * @param string|null $externalId
  441.      *
  442.      * @return self
  443.      */
  444.     public function setExternalId(?string $externalId): self
  445.     {
  446.         $this->externalId $externalId;
  447.         return $this;
  448.     }
  449.     /**
  450.      * @return string|null
  451.      */
  452.     public function getCustomerId(): ?string
  453.     {
  454.         return $this->customerId;
  455.     }
  456.     /**
  457.      * @param string $customerId
  458.      *
  459.      * @return self
  460.      */
  461.     public function setCustomerId(string $customerId): self
  462.     {
  463.         $this->customerId $customerId;
  464.         return $this;
  465.     }
  466.     /**
  467.      * @return Params|null
  468.      */
  469.     public function getVat(): ?Params
  470.     {
  471.         return $this->vat;
  472.     }
  473.     /**
  474.      * @param Params|null $vat
  475.      *
  476.      * @return self
  477.      */
  478.     public function setVat(?Params $vat): self
  479.     {
  480.         $this->vat $vat;
  481.         return $this;
  482.     }
  483.     /**
  484.      * @return Params|null
  485.      */
  486.     public function getUnit(): ?Params
  487.     {
  488.         return $this->unit;
  489.     }
  490.     /**
  491.      * @param Params|null $unit
  492.      *
  493.      * @return self
  494.      */
  495.     public function setUnit(?Params $unit): self
  496.     {
  497.         $this->unit $unit;
  498.         return $this;
  499.     }
  500.     /**
  501.      * @return Collection|Category[]
  502.      */
  503.     public function getCategories(): Collection
  504.     {
  505.         return $this->categories;
  506.     }
  507.     /**
  508.      * @param Collection|Category[] $categories
  509.      *
  510.      * @return $this
  511.      */
  512.     public function setCategories(Collection $categories): self
  513.     {
  514.         $this->categories $categories;
  515.         return $this;
  516.     }
  517.     /**
  518.      * @param Category $category
  519.      *
  520.      * @return $this
  521.      */
  522.     public function addCategory(Category $category): self
  523.     {
  524.         if (!$this->categories->contains($category)) {
  525.             $this->categories[] = $category;
  526.             $category->addProduct($this);
  527.         }
  528.         return $this;
  529.     }
  530.     /**
  531.      * @param Category $category
  532.      *
  533.      * @return $this
  534.      */
  535.     public function removeCategory(Category $category): self
  536.     {
  537.         if ($this->categories->contains($category)) {
  538.             $this->categories->removeElement($category);
  539.             $category->removeProduct($this);
  540.         }
  541.         return $this;
  542.     }
  543.     /**
  544.      * @return Params|null
  545.      */
  546.     public function getWarranty(): ?Params
  547.     {
  548.         return $this->warranty;
  549.     }
  550.     /**
  551.      * @param Params|null $warranty
  552.      *
  553.      * @return self
  554.      */
  555.     public function setWarranty(?Params $warranty): self
  556.     {
  557.         $this->warranty $warranty;
  558.         return $this;
  559.     }
  560.     /**
  561.      * {@inheritdoc}
  562.      */
  563.     public function getSpecificFields(): Collection
  564.     {
  565.         return $this->specificFields;
  566.     }
  567.     /**
  568.      * {@inheritdoc}
  569.      */
  570.     public function getSpecificFieldByFieldId(string $id): ?SpecificField
  571.     {
  572.         foreach ($this->specificFields as $specificField) {
  573.             if ($specificField->getFieldId() === $id) {
  574.                 return $specificField;
  575.             }
  576.         }
  577.         return null;
  578.     }
  579.     /**
  580.      * @param ProductSpecificField $specificField
  581.      *
  582.      * @return $this
  583.      *
  584.      * @see ImportableObjectTrait::class
  585.      */
  586.     public function addProductSpecificField(ProductSpecificField $specificField): self
  587.     {
  588.         return $this->addSpecificField($specificField);
  589.     }
  590.     /**
  591.      * {@inheritdoc}
  592.      */
  593.     public function addSpecificField($specificField): SpecificFieldsAwareInterface
  594.     {
  595.         $this->specificFields[] = $specificField;
  596.         return $this;
  597.     }
  598.     /**
  599.      * {@inheritdoc}
  600.      */
  601.     public function setSpecificFields(Collection $specificFields): self
  602.     {
  603.         $this->specificFields $specificFields;
  604.         return $this;
  605.     }
  606.     /**
  607.      * @return string|null
  608.      */
  609.     public function getName(): ?string
  610.     {
  611.         return $this->name;
  612.     }
  613.     /**
  614.      * @param string|null $name
  615.      *
  616.      * @return self
  617.      */
  618.     public function setName(?string $name): self
  619.     {
  620.         $this->name $name;
  621.         return $this;
  622.     }
  623.     /**
  624.      * @return string|null
  625.      */
  626.     public function getShortDescription(): ?string
  627.     {
  628.         return $this->shortDescription;
  629.     }
  630.     /**
  631.      * @param string|null $shortDescription
  632.      *
  633.      * @return Product
  634.      */
  635.     public function setShortDescription(?string $shortDescription): Product
  636.     {
  637.         $this->shortDescription $shortDescription;
  638.         return $this;
  639.     }
  640.     /**
  641.      * @return string|null
  642.      */
  643.     public function getReference(): ?string
  644.     {
  645.         return $this->reference;
  646.     }
  647.     /**
  648.      * @param string|null $reference
  649.      *
  650.      * @return self
  651.      */
  652.     public function setReference(?string $reference): self
  653.     {
  654.         $this->reference $reference;
  655.         return $this;
  656.     }
  657.     /**
  658.      * @return string|null
  659.      */
  660.     public function getPriceExcludingVat(): ?string
  661.     {
  662.         return $this->priceExcludingVat;
  663.     }
  664.     /**
  665.      * @param string|null $priceExcludingVat
  666.      *
  667.      * @return self
  668.      */
  669.     public function setPriceExcludingVat(?string $priceExcludingVat): self
  670.     {
  671.         $this->priceExcludingVat $priceExcludingVat;
  672.         return $this;
  673.     }
  674.     /**
  675.      * @return string|null
  676.      */
  677.     public function getSellingPriceExcludingVat(): ?string
  678.     {
  679.         return $this->sellingPriceExcludingVat;
  680.     }
  681.     /**
  682.      * @param string|null $sellingPriceExcludingVat
  683.      *
  684.      * @return self
  685.      */
  686.     public function setSellingPriceExcludingVat(?string $sellingPriceExcludingVat): self
  687.     {
  688.         $this->sellingPriceExcludingVat $sellingPriceExcludingVat;
  689.         return $this;
  690.     }
  691.     /**
  692.      * @return string|null
  693.      */
  694.     public function getImageId(): ?string
  695.     {
  696.         return $this->imageId;
  697.     }
  698.     /**
  699.      * @param string|null $imageId
  700.      *
  701.      * @return self
  702.      */
  703.     public function setImageId(?string $imageId): self
  704.     {
  705.         $this->imageId $imageId;
  706.         return $this;
  707.     }
  708.     /**
  709.      * @return CustomerFile|null
  710.      */
  711.     public function getImageFile(): ?CustomerFile
  712.     {
  713.         return $this->imageFile;
  714.     }
  715.     /**
  716.      * @param CustomerFile|null $imageFile
  717.      *
  718.      * @return Product
  719.      */
  720.     public function setImageFile(?CustomerFile $imageFile): self
  721.     {
  722.         $this->imageFile $imageFile;
  723.         return $this;
  724.     }
  725.     /**
  726.      * @TODO: PV-746: Find a better way
  727.      *
  728.      * @SerializedName("imageUrl")
  729.      * @Groups({"list", "product:list", "product:read"})
  730.      *
  731.      * @return string
  732.      */
  733.     public function getImageUrl(): ?string
  734.     {
  735.         if ($this->imageId) {
  736.             return '/api/logo/'.$this->imageId;
  737.         }
  738.         return null;
  739.     }
  740.     /**
  741.      * @return string|null
  742.      */
  743.     public function getSerialNumber(): ?string
  744.     {
  745.         return $this->serialNumber;
  746.     }
  747.     /**
  748.      * @param string|null $serialNumber
  749.      *
  750.      * @return self
  751.      */
  752.     public function setSerialNumber(?string $serialNumber): self
  753.     {
  754.         $this->serialNumber $serialNumber;
  755.         return $this;
  756.     }
  757.     /**
  758.      * @return bool
  759.      */
  760.     public function isComponent(): bool
  761.     {
  762.         return $this->isComponent;
  763.     }
  764.     /**
  765.      * @param bool $isComponent
  766.      *
  767.      * @return self
  768.      */
  769.     public function setIsComponent(bool $isComponent): self
  770.     {
  771.         $this->isComponent $isComponent;
  772.         return $this;
  773.     }
  774.     /**
  775.      * @return int|null
  776.      */
  777.     public function getStockQty(): ?int
  778.     {
  779.         return $this->stockQty;
  780.     }
  781.     /**
  782.      * @param int|null $stockQty
  783.      *
  784.      * @return self
  785.      */
  786.     public function setStockQty(?int $stockQty): self
  787.     {
  788.         $this->stockQty $stockQty;
  789.         return $this;
  790.     }
  791.     /**
  792.      * @return CustomerFile[]
  793.      */
  794.     public function getCustomerFiles()
  795.     {
  796.         return $this->customerFiles;
  797.     }
  798.     /**
  799.      * @param CustomerFile $customerFile
  800.      *
  801.      * @return $this
  802.      */
  803.     public function addCustomerFile(CustomerFile $customerFile): self
  804.     {
  805.         $this->customerFiles[] = $customerFile;
  806.         return $this;
  807.     }
  808.     /**
  809.      * @param CustomerFile $customerFile
  810.      *
  811.      * @return self
  812.      */
  813.     public function removeCustomerFile(CustomerFile $customerFile): self
  814.     {
  815.         $index array_search($customerFile$this->customerFilestrue);
  816.         if (false !== $index) {
  817.             unset($this->customerFiles[$index]);
  818.         }
  819.         return $this;
  820.     }
  821.     /**
  822.      * @param CustomerFile[] $customerFiles
  823.      *
  824.      * @return Product
  825.      */
  826.     public function setCustomerFiles(array $customerFiles): self
  827.     {
  828.         $this->customerFiles $customerFiles;
  829.         return $this;
  830.     }
  831.     /**
  832.      * @return ProductConfiguration|null
  833.      */
  834.     public function getProductConfiguration(): ?ProductConfiguration
  835.     {
  836.         return $this->productConfiguration;
  837.     }
  838.     /**
  839.      * @param ProductConfiguration|null $productConfiguration
  840.      *
  841.      * @return Product
  842.      */
  843.     public function setProductConfiguration(?ProductConfiguration $productConfiguration): self
  844.     {
  845.         $this->productConfiguration $productConfiguration;
  846.         return $this;
  847.     }
  848.     /**
  849.      * @return int|null
  850.      */
  851.     public function getSubscriptionValue(): ?int
  852.     {
  853.         return $this->subscriptionValue;
  854.     }
  855.     /**
  856.      * @param int|null $subscriptionValue
  857.      *
  858.      * @return self
  859.      */
  860.     public function setSubscriptionValue(?int $subscriptionValue): self
  861.     {
  862.         $this->subscriptionValue $subscriptionValue;
  863.         return $this;
  864.     }
  865.     /**
  866.      * @return string|null
  867.      */
  868.     public function getSubscriptionUnit(): ?string
  869.     {
  870.         return $this->subscriptionUnit;
  871.     }
  872.     /**
  873.      * @param string|null $subscriptionUnit
  874.      *
  875.      * @return self
  876.      */
  877.     public function setSubscriptionUnit(?string $subscriptionUnit): self
  878.     {
  879.         $this->subscriptionUnit $subscriptionUnit;
  880.         return $this;
  881.     }
  882.     /**
  883.      * @return string|null
  884.      */
  885.     public function getQuoteSection(): ?string
  886.     {
  887.         return $this->quoteSection;
  888.     }
  889.     /**
  890.      * @param string|null $quoteSection
  891.      *
  892.      * @return Product
  893.      */
  894.     public function setQuoteSection(?string $quoteSection): self
  895.     {
  896.         $this->quoteSection $quoteSection;
  897.         return $this;
  898.     }
  899.     /**
  900.      * @Groups({
  901.      *     "quote:read"
  902.      * })
  903.      *
  904.      * @return bool
  905.      */
  906.     public function isConfigurable(): bool
  907.     {
  908.         return $this->getProductConfiguration() instanceof ProductConfiguration;
  909.     }
  910.     /**
  911.      * @return string|null
  912.      */
  913.     public function getDescription(): ?string
  914.     {
  915.         return $this->description;
  916.     }
  917.     /**
  918.      * @param string|null $description
  919.      *
  920.      * @return $this
  921.      */
  922.     public function setDescription(?string $description): self
  923.     {
  924.         $this->description $description;
  925.         return $this;
  926.     }
  927. }