src/V4/Model/Quote/Quote.php line 355

Open in your IDE?
  1. <?php
  2. namespace App\V4\Model\Quote;
  3. use ApiPlatform\Core\Annotation\ApiFilter;
  4. use ApiPlatform\Core\Annotation\ApiProperty;
  5. use ApiPlatform\Core\Annotation\ApiResource;
  6. use App\Model\CustomerFile\CustomerFile;
  7. use App\Model\IriNormalizableInterface;
  8. use App\Model\NormalizeAsIRITrait;
  9. use App\Model\ProspectRefreshNeededTrait;
  10. use App\Model\SpecificFieldsAwareInterface;
  11. use App\Model\Traits\BlamableTrait;
  12. use App\Model\Traits\ImportableObjectTrait;
  13. use App\Model\Traits\TimestampableTrait;
  14. use App\V4\Entity\ActionableEntityInterface;
  15. use App\V4\Model\ChildrenAwareInterface;
  16. use App\V4\Model\Prospect\Prospect;
  17. use App\V4\Model\QuoteLine\QuoteLine;
  18. use App\V4\Model\QuoteReason\QuoteReason;
  19. use App\V4\Model\QuoteSpecificField\QuoteSpecificField;
  20. use App\V4\Model\QuoteState\QuoteState;
  21. use App\V4\Model\QuoteTaskExternalRef\QuoteTaskExternalRef;
  22. use App\V4\Model\SpecificField\SpecificField;
  23. use DateTime;
  24. use Doctrine\Common\Collections\ArrayCollection;
  25. use Doctrine\Common\Collections\Collection;
  26. use Symfony\Component\Serializer\Annotation\Groups;
  27. use Symfony\Component\Serializer\Annotation\MaxDepth;
  28. use Symfony\Component\Validator\Constraints as Assert;
  29. /**
  30.  * @ApiResource(
  31.  *     shortName="V4/Quote",
  32.  *     attributes={
  33.  *         "api_allow_update": true
  34.  *     },
  35.  *     collectionOperations={
  36.  *         "get": {
  37.  *             "normalization_context": {
  38.  *                  "groups": {"quote:list"}
  39.  *             },
  40.  *             "security": "is_granted(constant('App\\V4\\Voters\\QuoteVoter::QUOTE_SHOW_LIST'), 'App\V4\Voters\QuoteVoter')"
  41.  *         },
  42.  *         "post_quote": {
  43.  *             "method": "POST",
  44.  *             "deserialize": false,
  45.  *             "write": false,
  46.  *             "controller": "App\V4\Controller\Quote\QuoteDataPersisterAction",
  47.  *             "path": "/V4/quotes",
  48.  *             "input_formats": {
  49.  *                 "multipart": {"multipart/form-data"}
  50.  *             },
  51.  *             "normalization_context": {
  52.  *                  "groups": {"quote:read", "isProspectRefreshNeeded"}
  53.  *             },
  54.  *             "denormalization_context": {
  55.  *                  "groups": {}
  56.  *             }
  57.  *         },
  58.  *         "get_form": {
  59.  *             "method": "GET",
  60.  *             "path": "/V4/quotes/form",
  61.  *             "controller": App\V4\Controller\Quote\GetQuoteFormAction::class
  62.  *         },
  63.  *         "get_search": {
  64.  *             "method": "GET",
  65.  *             "path": "/V4/quotes/search/form",
  66.  *             "controller": App\V4\Controller\Quote\GetQuoteSearchFormAction::class,
  67.  *         },
  68.  *         "post_search": {
  69.  *             "method": "POST",
  70.  *             "deserialize": false,
  71.  *             "path": "/V4/quotes/search/form",
  72.  *             "normalization_context": {
  73.  *                  "groups": {"quote:list"}
  74.  *             },
  75.  *             "controller": App\V4\Controller\Quote\PostQuoteSearchFormAction::class,
  76.  *         },
  77.  *         "post_export_request": {
  78.  *             "method": "POST",
  79.  *             "path": "/v4/export/quote",
  80.  *             "controller": App\V4\Action\Export\EntityExportRequestAction::class,
  81.  *             "swagger_context": {
  82.  *                 "summary": "Demande de création d'export de devis",
  83.  *                 "description": "Demande de création d'export de devis où 'ids' sont les ids des devis et 'fields' les champs souhaités",
  84.  *                 "parameters": {
  85.  *                     {
  86.  *                         "in": "body",
  87.  *                         "name": "body",
  88.  *                         "schema": {
  89.  *                             "type": "object",
  90.  *                             "properties": {
  91.  *                                 "ids": {
  92.  *                                     "type": "array",
  93.  *                                     "items": {"type": "string"}
  94.  *                                 },
  95.  *                                 "fields": {
  96.  *                                      "type": "array",
  97.  *                                      "items": {"type": "string"}
  98.  *                                 }
  99.  *                             }
  100.  *                         }
  101.  *                     }
  102.  *                 },
  103.  *                 "responses": {
  104.  *                     "201": {
  105.  *                         "description": "Création de l'export avec succès",
  106.  *                         "schema": {
  107.  *                             "type": "object",
  108.  *                             "properties": {
  109.  *                                 "message": {"type": "string", "example": "export_request_created"},
  110.  *                             }
  111.  *                         }
  112.  *                     },
  113.  *                     "400": {
  114.  *                         "description": "Utilisateur non trouvé ou champs 'fields' ou 'ids' manquant dans le body request",
  115.  *                         "schema": {
  116.  *                             "type": "object",
  117.  *                             "properties": {
  118.  *                                 "message": {"type": "string", "example": "user_not_found or missing_fields_or_ids"},
  119.  *                             }
  120.  *                         }
  121.  *                     },
  122.  *                     "422": {
  123.  *                         "description": "Les champs 'fields' ou 'ids' du body request sont vides ou l'entité demandée est invalide",
  124.  *                         "schema": {
  125.  *                             "type": "object",
  126.  *                             "properties": {
  127.  *                                 "message": {"type": "string", "example": "empty_fields_or_ids or entity_not_valid"},
  128.  *                             }
  129.  *                         }
  130.  *                     },
  131.  *                 },
  132.  *             }
  133.  *         },
  134.  *         "post_export_download": {
  135.  *             "method": "POST",
  136.  *             "path": "/v4/export/download/quote/{id}",
  137.  *             "controller": App\V4\Action\Export\EntityExportDownloadAction::class,
  138.  *             "swagger_context": {
  139.  *                 "summary": "Demande de téléchargement d'un export devis",
  140.  *                 "description": "Demande de téléchargement d'un export devis ou 'id' est le nom du fichier d'export",
  141.  *                 "requestBody": {},
  142.  *                 "parameters": {
  143.  *                     {
  144.  *                         "in": "path",
  145.  *                         "name": "id",
  146.  *                         "type": "string",
  147.  *                         "required": "true"
  148.  *                     }
  149.  *                 },
  150.  *                 "responses": {
  151.  *                     "200": {
  152.  *                         "description": "Téléchargement de l'export réalisé avec succès"
  153.  *                     },
  154.  *                     "401": {
  155.  *                         "description": "Utilisateur non trouvé ou non connecté",
  156.  *                         "schema": {
  157.  *                             "type": "object",
  158.  *                             "properties": {
  159.  *                                 "message": {"type": "string", "example": "need_authenticated"},
  160.  *                             }
  161.  *                         }
  162.  *                     },
  163.  *                     "404": {
  164.  *                         "description": "Fichier introuvable",
  165.  *                         "schema": {
  166.  *                             "type": "object",
  167.  *                             "properties": {
  168.  *                                 "message": {"type": "string", "example": "export_not_found"},
  169.  *                             }
  170.  *                         }
  171.  *                     },
  172.  *                 },
  173.  *             }
  174.  *         },
  175.  *         "get_expected_signed_at_form": {
  176.  *             "method": "GET",
  177.  *             "path": "/V4/quotes/expected-signed-at/form",
  178.  *             "controller": App\V4\Controller\Quote\GetQuoteExpectedSignedAtFormAction::class,
  179.  *             "swagger_context": {
  180.  *                 "summary": "Retourne le formulaire de date de signature",
  181.  *                 "description": "Retourne le formulaire de date de signature dans le cadre d'une action rapide visant à basculer un devis en statut gagné",
  182.  *                 "parameters": {},
  183.  *             },
  184.  *         },
  185.  *     },
  186.  *     itemOperations={
  187.  *        "get": {
  188.  *             "path": "/V4/quotes/{id}",
  189.  *         },
  190.  *         "get_form": {
  191.  *             "method": "GET",
  192.  *             "path": "/V4/quotes/{id}/form",
  193.  *             "controller": App\V4\Controller\Quote\GetQuoteFormAction::class
  194.  *         },
  195.  *         "get_reason_form": {
  196.  *             "method": "GET",
  197.  *             "path": "/V4/quotes/{id}/reason/form",
  198.  *             "controller": App\V4\Controller\Quote\GetQuoteReasonFormAction::class
  199.  *         },
  200.  *         "post_reason": {
  201.  *             "method": "POST",
  202.  *             "path": "/V4/quotes/{id}/reason",
  203.  *             "controller": App\V4\Controller\Quote\PostQuoteReasonAction::class
  204.  *         },
  205.  *         "put_quote": {
  206.  *             "method": "POST",
  207.  *             "deserialize": false,
  208.  *             "write": false,
  209.  *             "controller": "App\V4\Controller\Quote\QuoteDataPersisterAction",
  210.  *             "path": "/V4/quotes/{id}",
  211.  *             "input_formats": {
  212.  *                 "multipart": {"multipart/form-data"}
  213.  *             },
  214.  *             "normalization_context": {
  215.  *                  "groups": {"quote:read", "isProspectRefreshNeeded"}
  216.  *             },
  217.  *             "denormalization_context": {
  218.  *                  "groups": {}
  219.  *             }
  220.  *         },
  221.  *         "regenerate_quote": {
  222.  *             "method": "POST",
  223.  *             "path": "/V4/quotes/{id}/regenerate",
  224.  *             "controller": "App\V4\Action\Quote\RegenerateQuoteAction",
  225.  *             "swagger_context": {
  226.  *                  "summary": "Demande de réactualisation de l'offre",
  227.  *                  "description": "Demande de réactualisation de l'offre du devis 'id'",
  228.  *                  "parameters": {
  229.  *                      {
  230.  *                          "in": "path",
  231.  *                          "name": "id",
  232.  *                          "type": "string",
  233.  *                          "required": "true"
  234.  *                      },
  235.  *                      {
  236.  *                          "in": "body",
  237.  *                          "name": "body",
  238.  *                          "schema": {
  239.  *                              "type": "object",
  240.  *                              "properties": {
  241.  *                                  "updatePrice": {"type": "boolean"},
  242.  *                                  "template": {"type": "string", "example": "id_du_template"},
  243.  *                              },
  244.  *                          },
  245.  *                      },
  246.  *                  },
  247.  *              },
  248.  *         },
  249.  *          "regenerate_quote_get": {
  250.  *               "method": "GET",
  251.  *               "path": "/V4/quotes/{id}/regenerate",
  252.  *               "controller": "App\V4\Action\Quote\GetRegenerateQuoteFormAction",
  253.  *               "swagger_context": {
  254.  *                   "summary": "Demande de récupération du formulaire de réactualisation de l'offre",
  255.  *                   "description": "Demande de récupération du formulaire de réactualisation de l'offre du devis 'id'",
  256.  *                   "responses": {
  257.  *                       "200": {
  258.  *                           "description": "Envoi du formulaire de réactualisation de l'offre",
  259.  *                       },
  260.  *                       "404": {
  261.  *                           "description": "Devis introuvable",
  262.  *                       },
  263.  *                   },
  264.  *               },
  265.  *          },
  266.  *         "split_chidren": {
  267.  *             "method": "POST",
  268.  *             "deserialize": false,
  269.  *             "path": "/quotes/{id}/split-children",
  270.  *             "controller": App\V4\Controller\Quote\SplitChildrenAction::class,
  271.  *         },
  272.  *         "get_tasks": {
  273.  *             "method": "GET",
  274.  *             "path": "/v4/quotes/{id}/related-tasks",
  275.  *             "normalization_context": {
  276.  *                  "groups": {"task:list"}
  277.  *             },
  278.  *             "controller": App\V4\Action\Quote\GetRelatedTasksByQuoteAction::class,
  279.  *             "read": false,
  280.  *             "swagger_context": {
  281.  *                 "summary": "Récupert les actions liées au devis",
  282.  *             },
  283.  *         },
  284.  *         "delete_quote": {
  285.  *             "method": "DELETE",
  286.  *             "deserialize": false,
  287.  *             "write": false,
  288.  *             "controller": "App\V4\Controller\Quote\QuoteDataPersisterAction",
  289.  *             "path": "/V4/quotes/{id}"
  290.  *         },
  291.  *         "duplicate_quote": {
  292.  *             "method": "GET",
  293.  *             "path": "/V4/quotes/{quoteId}/form/duplicate",
  294.  *             "controller": "App\V4\Action\Quote\DuplicateQuoteAction::class",
  295.  *             "swagger_context": {
  296.  *                 "summary": "Demande de duplication d'un devis",
  297.  *                 "description": "Demande de création d'un nouveau formulaire devis ayant pour valeur une copie du devis 'quoteId'",
  298.  *                 "parameters": {
  299.  *                     {
  300.  *                         "in": "path",
  301.  *                         "name": "quoteId",
  302.  *                         "type": "string",
  303.  *                         "required": "true"
  304.  *                     }
  305.  *                 },
  306.  *                 "responses": {
  307.  *                     "200": {
  308.  *                         "description": "Création d'un formulaire basé sur le devis à duppliquer réalisé avec succès"
  309.  *                     },
  310.  *                     "500": {
  311.  *                         "description": "Le devis ne peut pas être divisé car il est enfant ou parent d'un autre devis"
  312.  *                     },
  313.  *                     "404": {
  314.  *                         "description": "Devis introuvable"
  315.  *                     },
  316.  *                 },
  317.  *             },
  318.  *         },
  319.  *         "post_expected_signed_at_form": {
  320.  *             "method": "POST",
  321.  *             "path": "/V4/quotes/{id}/expected-signed-at",
  322.  *             "controller": App\V4\Controller\Quote\PostQuoteExpectedSignedAtFormAction::class,
  323.  *             "swagger_context": {
  324.  *                 "summary": "Envoie date de signature pour passage d'un devis en statut Gagné",
  325.  *                 "description": "Demande de soumission du formulaire de date de signature dans le cadre d'une action rapide visant à basculer un devis en statut gagné",
  326.  *                 "parameters": {
  327.  *                     {
  328.  *                         "in": "path",
  329.  *                         "name": "id",
  330.  *                         "type": "string",
  331.  *                         "required": "true"
  332.  *                     },
  333.  *                     {
  334.  *                         "in": "body",
  335.  *                         "name": "body",
  336.  *                         "schema": {
  337.  *                             "type": "object",
  338.  *                             "properties": {
  339.  *                                 "status": {"type": "string", "example": "id_statut_gagne"},
  340.  *                                 "expectedSignedAt": {"type": "string", "example": "2024-03-22T17:50"},
  341.  *                             },
  342.  *                         },
  343.  *                     },
  344.  *                 },
  345.  *             },
  346.  *         },
  347.  *     }
  348.  * )
  349.  *
  350.  * @ApiFilter(App\Filters\PagingFilter::class)
  351.  */
  352. class Quote implements IriNormalizableInterfaceSpecificFieldsAwareInterfaceChildrenAwareInterfaceActionableEntityInterface
  353. {
  354.     public const SPECIFIC_FIELD_CLASS_NAME QuoteSpecificField::class;
  355.     public const DEFAULT_POTENTIAL_VALUE 50;
  356.     use TimestampableTrait;
  357.     use BlamableTrait;
  358.     use ImportableObjectTrait;
  359.     use NormalizeAsIRITrait;
  360.     use ProspectRefreshNeededTrait;
  361.     /**
  362.      * @var string|null
  363.      *
  364.      * @ApiProperty(identifier=true)
  365.      *
  366.      * @Groups({"quote:list", "quote:read"})
  367.      */
  368.     private $id;
  369.     /**
  370.      * @var string|null
  371.      *
  372.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  373.      */
  374.     private $externalId;
  375.     /**
  376.      * @var string|null
  377.      */
  378.     private $customerId;
  379.     /**
  380.      * @var ArrayCollection|QuoteLine[]
  381.      *
  382.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  383.      */
  384.     private $quoteLines;
  385.     /**
  386.      * @var string|null
  387.      *
  388.      * @Assert\NotBlank()
  389.      * @Assert\Length(max=255)
  390.      *
  391.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  392.      */
  393.     private $name;
  394.     /**
  395.      * @var Prospect|null
  396.      *
  397.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  398.      * @MaxDepth(1)
  399.      */
  400.     private $prospect;
  401.     /**
  402.      * @var string|null
  403.      *
  404.      * @Assert\NotBlank()
  405.      *
  406.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  407.      */
  408.     private $prospectId;
  409.     /**
  410.      * @var string|null
  411.      *
  412.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  413.      */
  414.     private $managedBy;
  415.     /**
  416.      * @var string|null
  417.      *
  418.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  419.      */
  420.     private $contactId;
  421.     /**
  422.      * @var string|null
  423.      *
  424.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  425.      */
  426.     private $terms;
  427.     /**
  428.      * @var DateTime|null
  429.      *
  430.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  431.      */
  432.     private $warrantlyAt;
  433.     /**
  434.      * @var string|null
  435.      *
  436.      * @Assert\Length(max=100)
  437.      *
  438.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  439.      */
  440.     private $contractNumber;
  441.     /**
  442.      * @var bool|null
  443.      *
  444.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  445.      */
  446.     private $isMaintenance;
  447.     /**
  448.      * @var string|null
  449.      *
  450.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  451.      */
  452.     private $comment;
  453.     /**
  454.      * @var DateTime|null
  455.      *
  456.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  457.      */
  458.     private $issuedAt;
  459.     /**
  460.      * @var float|null
  461.      *
  462.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  463.      */
  464.     private $potential;
  465.     /**
  466.      * @var string|null
  467.      *
  468.      * @Assert\Length(max=255)
  469.      *
  470.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  471.      */
  472.     private $quoteNumber;
  473.     /**
  474.      * @var QuoteState|null
  475.      *
  476.      * @Assert\NotBlank()
  477.      *
  478.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  479.      */
  480.     private $status;
  481.     /**
  482.      * @var string|null
  483.      *
  484.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  485.      */
  486.     private $description;
  487.     /**
  488.      * @var DateTime|null
  489.      *
  490.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  491.      */
  492.     private $expectedSignedAt;
  493.     /**
  494.      * @var DateTime|null
  495.      *
  496.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  497.      */
  498.     private $expiredAt;
  499.     /**
  500.      * @var string|null
  501.      *
  502.      * @Assert\LessThan(99999999)
  503.      *
  504.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  505.      */
  506.     private $totalExcludingVat;
  507.     /**
  508.      * @var string|null
  509.      *
  510.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  511.      */
  512.     private $weightedTotal;
  513.     /**
  514.      * @var bool|null
  515.      *
  516.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  517.      */
  518.     private $isSalesForecast true;
  519.     /**
  520.      * @var CustomerFile[]|Collection
  521.      *
  522.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  523.      */
  524.     private $customerFiles = [];
  525.     /**
  526.      * @var string|null
  527.      *
  528.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  529.      */
  530.     private $sectionName;
  531.     /**
  532.      * @var SpecificField[]|Collection
  533.      *
  534.      * @Groups({"quote:list", "quote:read", "quote:write", "quote:update"})
  535.      */
  536.     private $specificFields;
  537.     /**
  538.      * @var Quote|null
  539.      *
  540.      * @Groups({"quote:list", "quote:read", "quote:write"})
  541.      */
  542.     private $parent;
  543.     /**
  544.      * @var Quote[]|Collection
  545.      *
  546.      * @Groups({"quote:list", "quote:read"})
  547.      */
  548.     private $children;
  549.     /**
  550.      * @var QuoteTaskExternalRef[]|Collection
  551.      *
  552.      * @Groups({"quote:read", "quote:write", "quote:update"})
  553.      */
  554.     private $tasks;
  555.     /**
  556.      * @var string|null
  557.      *
  558.      * @Groups({"quote:list"})
  559.      */
  560.     private $prospectFullName;
  561.     /**
  562.      * @var string|null
  563.      *
  564.      * @Groups({"quote:list"})
  565.      */
  566.     private $contactIdRealName;
  567.     /**
  568.      * @var string|null
  569.      */
  570.     private $managedByRealName;
  571.     /**
  572.      * @var QuoteReason|null
  573.      * @MaxDepth(1)
  574.      * @Groups({"list", "write_post_quote", "quote:read", "quote:write", "quote:update"})
  575.      */
  576.     private $reason;
  577.     /**
  578.      * @var string|null
  579.      * @Groups({"list", "write_post_quote", "quote:read", "quote:write", "quote:update"})
  580.      */
  581.     private $reasonComment;
  582.     public function __construct()
  583.     {
  584.         $this->specificFields = new ArrayCollection();
  585.         $this->quoteLines = new ArrayCollection();
  586.         $this->children = new ArrayCollection();
  587.         $this->tasks = new ArrayCollection();
  588.     }
  589.     /**
  590.      * @return float
  591.      */
  592.     public function getTotalIncludingVat(): float
  593.     {
  594.         $total 0;
  595.         foreach ($this->quoteLines as $quoteLine) {
  596.             $total += (float) $quoteLine->getTotal();
  597.         }
  598.         return $total;
  599.     }
  600.     /**
  601.      * @return array The total vat amount by percentage
  602.      */
  603.     public function getTotalVatByPercentage(): array
  604.     {
  605.         $totalVatByPercentage = [];
  606.         foreach ($this->quoteLines as $quoteLine) {
  607.             $vatPercentage $quoteLine->getVatRate();
  608.             if (!isset($totalVatByPercentage[$vatPercentage])) {
  609.                 $totalVatByPercentage[$vatPercentage] = 0;
  610.             }
  611.             $totalVatByPercentage[$vatPercentage] += $quoteLine->getVatAmount();
  612.         }
  613.         return $totalVatByPercentage;
  614.     }
  615.     /**
  616.      * @return float
  617.      */
  618.     public function getTotalDiscount(): float
  619.     {
  620.         $total 0;
  621.         foreach ($this->quoteLines as $quoteLine) {
  622.             $total += (float) $quoteLine->getDiscountAmount();
  623.         }
  624.         return $total;
  625.     }
  626.     /**
  627.      * @return float
  628.      */
  629.     public function getTotalExcludingVatBeforeDiscount(): float
  630.     {
  631.         $total 0;
  632.         foreach ($this->quoteLines as $quoteLine) {
  633.             $total += (float) $quoteLine->getTotalExclDiscountAndVat();
  634.         }
  635.         return $total;
  636.     }
  637.     /**
  638.      * @return bool
  639.      *
  640.      * @Assert\Callback()
  641.      */
  642.     public function validateReason(): bool
  643.     {
  644.         if (!$this->reason || !$this->status) {
  645.             return true;
  646.         }
  647.         if ($this->reason->getQuoteState() !== $this->status) {
  648.             return false;
  649.         }
  650.         return true;
  651.     }
  652.     /**
  653.      * @param string $name
  654.      *
  655.      * @return string
  656.      */
  657.     public function getSectionTotal(string $name): string
  658.     {
  659.         $sum 0;
  660.         foreach ($this->getQuoteLines() as $quoteLine) {
  661.             if ($name !== $quoteLine->getSectionName()) {
  662.                 continue;
  663.             }
  664.             $sum += floatval($quoteLine->getTotal());
  665.         }
  666.         return $sum;
  667.     }
  668.     /**
  669.      * @param string $sectionName
  670.      *
  671.      * @return QuoteLine[]
  672.      */
  673.     public function getQuoteLinesForSection(string $sectionName): array
  674.     {
  675.         $quoteLines = [];
  676.         foreach ($this->getQuoteLines() as $quoteLine) {
  677.             if ($sectionName === $quoteLine->getSectionName()) {
  678.                 $quoteLines[] = $quoteLine;
  679.             }
  680.         }
  681.         return $quoteLines;
  682.     }
  683.     /**
  684.      * {@inheritdoc}
  685.      */
  686.     public function isSplit(): bool
  687.     {
  688.         return $this->isParent() || $this->isChild();
  689.     }
  690.     /**
  691.      * @return void
  692.      */
  693.     public function getSplitType(): ?string
  694.     {
  695.         if ($this->isParent()) {
  696.             return 'parent';
  697.         }
  698.         if ($this->isChild()) {
  699.             return 'child';
  700.         }
  701.         return null;
  702.     }
  703.     /**
  704.      * {@inheritdoc}
  705.      */
  706.     public function isParent(): bool
  707.     {
  708.         return !$this->getChildren()->isEmpty();
  709.     }
  710.     /**
  711.      * {@inheritdoc}
  712.      */
  713.     public function isChild(): bool
  714.     {
  715.         return $this->getParent() instanceof Quote;
  716.     }
  717.     /**
  718.      * @return Quote[]|Collection
  719.      */
  720.     public function getSiblings(): Collection
  721.     {
  722.         if (!$this->isChild()) {
  723.             return new ArrayCollection();
  724.         }
  725.         $siblings = [];
  726.         foreach ($this->getParent()->getChildren() as $child) {
  727.             if ($child->getId() !== $this->getId()) {
  728.                 $siblings[] = $child;
  729.             }
  730.         }
  731.         return new ArrayCollection($siblings);
  732.     }
  733.     /**
  734.      * @return bool
  735.      */
  736.     public function isLate(): bool
  737.     {
  738.         return $this->getStatus() && $this->getStatus()->getInProgress() && $this->getExpectedSignedAt() < new DateTime();
  739.     }
  740.     /**
  741.      * @return bool
  742.      */
  743.     public function isWon(): bool
  744.     {
  745.         return $this->getStatus() instanceof QuoteState && $this->getStatus()->getIsWon();
  746.     }
  747.     /**
  748.      * @return string[]
  749.      */
  750.     public function getAllSectionNames(): array
  751.     {
  752.         $sectionsNames = [];
  753.         foreach ($this->getQuoteLines() as $quoteLine) {
  754.             if (!empty($quoteLine->getSectionName()) && !in_array($quoteLine->getSectionName(), $sectionsNamestrue)) {
  755.                 $sectionsNames[] = $quoteLine->getSectionName();
  756.             }
  757.         }
  758.         return $sectionsNames;
  759.     }
  760.     public function getCurrentPdfVersion(): int
  761.     {
  762.         if (empty($this->getCustomerFiles())) {
  763.             return 1;
  764.         }
  765.         $version 0;
  766.         foreach ($this->getCustomerFiles() as $customerFile) {
  767.             if ($version $customerFile->getVersionNumber()) {
  768.                 $version $customerFile->getVersionNumber();
  769.             }
  770.         }
  771.         return $version 1;
  772.     }
  773.     public function getTemplateId(): ?string
  774.     {
  775.         $customerFiles array_filter($this->getCustomerFiles(), static function ($cf) {
  776.             return $cf->isQuotePdf();
  777.         });
  778.         usort($customerFiles, static function (CustomerFile $aCustomerFile $b) {
  779.             return $a->getUpdatedAt() < $b->getUpdatedAt();
  780.         });
  781.         if (empty($customerFiles)) {
  782.             return null;
  783.         }
  784.         return $customerFiles[0]->getTemplateId();
  785.     }
  786.     /**
  787.      * @return string
  788.      */
  789.     public function getId(): ?string
  790.     {
  791.         return $this->id;
  792.     }
  793.     /**
  794.      * @param string|null $id
  795.      *
  796.      * @return Quote
  797.      */
  798.     public function setId(?string $id): Quote
  799.     {
  800.         $this->id $id;
  801.         return $this;
  802.     }
  803.     /**
  804.      * @return string|null
  805.      */
  806.     public function getExternalId(): ?string
  807.     {
  808.         return $this->externalId;
  809.     }
  810.     /**
  811.      * @param string|null $externalId
  812.      *
  813.      * @return Quote
  814.      */
  815.     public function setExternalId(?string $externalId): self
  816.     {
  817.         $this->externalId $externalId;
  818.         return $this;
  819.     }
  820.     /**
  821.      * @return Collection|QuoteLine[]
  822.      */
  823.     public function getQuoteLines(): Collection
  824.     {
  825.         return $this->quoteLines;
  826.     }
  827.     /**
  828.      * @param QuoteLine $quoteLine
  829.      *
  830.      * @return self
  831.      */
  832.     public function addQuoteLine(QuoteLine $quoteLine): self
  833.     {
  834.         if (!$this->quoteLines->contains($quoteLine)) {
  835.             $quoteLine->setQuote($this);
  836.             $this->quoteLines->add($quoteLine);
  837.         }
  838.         return $this;
  839.     }
  840.     /**
  841.      * @param Collection|QuoteLine[] $quoteLines
  842.      *
  843.      * @return self
  844.      */
  845.     public function setQuoteLines(Collection $quoteLines): self
  846.     {
  847.         $this->quoteLines $quoteLines;
  848.         return $this;
  849.     }
  850.     /**
  851.      * @param QuoteLine $quoteLine
  852.      *
  853.      * @return self
  854.      */
  855.     public function removeQuoteLine(QuoteLine $quoteLine): self
  856.     {
  857.         if ($this->quoteLines->contains($quoteLine)) {
  858.             $this->quoteLines->removeElement($quoteLine);
  859.         }
  860.         return $this;
  861.     }
  862.     /**
  863.      * @return string|null
  864.      */
  865.     public function getName(): ?string
  866.     {
  867.         return $this->name;
  868.     }
  869.     /**
  870.      * @param string|null $name
  871.      *
  872.      * @return Quote
  873.      */
  874.     public function setName(?string $name): Quote
  875.     {
  876.         $this->name $name;
  877.         return $this;
  878.     }
  879.     /**
  880.      * @return string|null
  881.      */
  882.     public function getCustomerId(): ?string
  883.     {
  884.         return $this->customerId;
  885.     }
  886.     /**
  887.      * @param string|null $customerId
  888.      *
  889.      * @return Quote
  890.      */
  891.     public function setCustomerId(?string $customerId): Quote
  892.     {
  893.         $this->customerId $customerId;
  894.         return $this;
  895.     }
  896.     /**
  897.      * @return string|null
  898.      */
  899.     public function getManagedBy(): ?string
  900.     {
  901.         return $this->managedBy;
  902.     }
  903.     /**
  904.      * @param string|null $managedBy
  905.      *
  906.      * @return Quote
  907.      */
  908.     public function setManagedBy(?string $managedBy): Quote
  909.     {
  910.         $this->managedBy $managedBy;
  911.         return $this;
  912.     }
  913.     /**
  914.      * @return DateTime|null
  915.      */
  916.     public function getIssuedAt(): ?DateTime
  917.     {
  918.         return $this->issuedAt;
  919.     }
  920.     /**
  921.      * @param DateTime|null $issuedAt
  922.      *
  923.      * @return Quote
  924.      */
  925.     public function setIssuedAt(?DateTime $issuedAt): Quote
  926.     {
  927.         $this->issuedAt $issuedAt;
  928.         return $this;
  929.     }
  930.     /**
  931.      * @return float|null
  932.      */
  933.     public function getPotential(): ?float
  934.     {
  935.         return $this->potential;
  936.     }
  937.     /**
  938.      * @param float|null $potential
  939.      *
  940.      * @return Quote
  941.      */
  942.     public function setPotential(?float $potential): Quote
  943.     {
  944.         $this->potential $potential;
  945.         return $this;
  946.     }
  947.     /**
  948.      * @return QuoteState|null
  949.      */
  950.     public function getStatus(): ?QuoteState
  951.     {
  952.         return $this->status;
  953.     }
  954.     /**
  955.      * @param QuoteState|null $status
  956.      *
  957.      * @return Quote
  958.      */
  959.     public function setStatus(?QuoteState $status): Quote
  960.     {
  961.         $this->status $status;
  962.         return $this;
  963.     }
  964.     /**
  965.      * @return DateTime|null
  966.      */
  967.     public function getExpectedSignedAt(): ?DateTime
  968.     {
  969.         return $this->expectedSignedAt;
  970.     }
  971.     /**
  972.      * @param DateTime|null $expectedSignedAt
  973.      *
  974.      * @return Quote
  975.      */
  976.     public function setExpectedSignedAt(?DateTime $expectedSignedAt): Quote
  977.     {
  978.         $this->expectedSignedAt $expectedSignedAt;
  979.         return $this;
  980.     }
  981.     /**
  982.      * @return string|null
  983.      */
  984.     public function getTotalExcludingVat(): ?string
  985.     {
  986.         return $this->totalExcludingVat;
  987.     }
  988.     /**
  989.      * @param string|null $totalExcludingVat
  990.      *
  991.      * @return Quote
  992.      */
  993.     public function setTotalExcludingVat(?string $totalExcludingVat): Quote
  994.     {
  995.         $this->totalExcludingVat $totalExcludingVat;
  996.         return $this;
  997.     }
  998.     /**
  999.      * @return bool|null
  1000.      */
  1001.     public function getIsSalesForecast(): ?bool
  1002.     {
  1003.         return $this->isSalesForecast;
  1004.     }
  1005.     /**
  1006.      * @param bool|null $isSalesForecast
  1007.      *
  1008.      * @return Quote
  1009.      */
  1010.     public function setIsSalesForecast(?bool $isSalesForecast): Quote
  1011.     {
  1012.         $this->isSalesForecast $isSalesForecast;
  1013.         return $this;
  1014.     }
  1015.     /**
  1016.      * @return Prospect|null
  1017.      */
  1018.     public function getProspect(): ?Prospect
  1019.     {
  1020.         return $this->prospect;
  1021.     }
  1022.     /**
  1023.      * @param Prospect|null $prospect
  1024.      *
  1025.      * @return Quote
  1026.      */
  1027.     public function setProspect(?Prospect $prospect): Quote
  1028.     {
  1029.         $this->prospect $prospect;
  1030.         return $this;
  1031.     }
  1032.     /**
  1033.      * @return string|null
  1034.      */
  1035.     public function getProspectId(): ?string
  1036.     {
  1037.         return $this->prospectId;
  1038.     }
  1039.     /**
  1040.      * @param string|null $prospectId
  1041.      *
  1042.      * @return Quote
  1043.      */
  1044.     public function setProspectId(?string $prospectId): self
  1045.     {
  1046.         $this->prospectId $prospectId;
  1047.         return $this;
  1048.     }
  1049.     /**
  1050.      * @return string|null
  1051.      */
  1052.     public function getQuoteNumber(): ?string
  1053.     {
  1054.         return $this->quoteNumber;
  1055.     }
  1056.     /**
  1057.      * @param string|null $quoteNumber
  1058.      *
  1059.      * @return Quote
  1060.      */
  1061.     public function setQuoteNumber(?string $quoteNumber): Quote
  1062.     {
  1063.         $this->quoteNumber $quoteNumber;
  1064.         return $this;
  1065.     }
  1066.     /**
  1067.      * @return DateTime|null
  1068.      */
  1069.     public function getExpiredAt(): ?DateTime
  1070.     {
  1071.         return $this->expiredAt;
  1072.     }
  1073.     /**
  1074.      * @param DateTime|null $expiredAt
  1075.      *
  1076.      * @return Quote
  1077.      */
  1078.     public function setExpiredAt(?DateTime $expiredAt): Quote
  1079.     {
  1080.         $this->expiredAt $expiredAt;
  1081.         return $this;
  1082.     }
  1083.     /**
  1084.      * @return string|null
  1085.      */
  1086.     public function getDescription(): ?string
  1087.     {
  1088.         return $this->description;
  1089.     }
  1090.     /**
  1091.      * @param string|null $description
  1092.      *
  1093.      * @return Quote
  1094.      */
  1095.     public function setDescription(?string $description): Quote
  1096.     {
  1097.         $this->description $description;
  1098.         return $this;
  1099.     }
  1100.     /**
  1101.      * @return string|null
  1102.      */
  1103.     public function getContactId(): ?string
  1104.     {
  1105.         return $this->contactId;
  1106.     }
  1107.     /**
  1108.      * @param string|null $contactId
  1109.      *
  1110.      * @return Quote
  1111.      */
  1112.     public function setContactId(?string $contactId): Quote
  1113.     {
  1114.         $this->contactId $contactId;
  1115.         return $this;
  1116.     }
  1117.     /**
  1118.      * @return string|null
  1119.      */
  1120.     public function getTerms(): ?string
  1121.     {
  1122.         return $this->terms;
  1123.     }
  1124.     /**
  1125.      * @param string|null $terms
  1126.      *
  1127.      * @return Quote
  1128.      */
  1129.     public function setTerms(?string $terms): Quote
  1130.     {
  1131.         $this->terms $terms;
  1132.         return $this;
  1133.     }
  1134.     /**
  1135.      * @return DateTime|null
  1136.      */
  1137.     public function getWarrantlyAt(): ?DateTime
  1138.     {
  1139.         return $this->warrantlyAt;
  1140.     }
  1141.     /**
  1142.      * @param DateTime|null $warrantlyAt
  1143.      *
  1144.      * @return Quote
  1145.      */
  1146.     public function setWarrantlyAt(?DateTime $warrantlyAt): Quote
  1147.     {
  1148.         $this->warrantlyAt $warrantlyAt;
  1149.         return $this;
  1150.     }
  1151.     /**
  1152.      * @return string|null
  1153.      */
  1154.     public function getContractNumber(): ?string
  1155.     {
  1156.         return $this->contractNumber;
  1157.     }
  1158.     /**
  1159.      * @param string|null $contractNumber
  1160.      *
  1161.      * @return Quote
  1162.      */
  1163.     public function setContractNumber(?string $contractNumber): Quote
  1164.     {
  1165.         $this->contractNumber $contractNumber;
  1166.         return $this;
  1167.     }
  1168.     /**
  1169.      * @return bool|null
  1170.      */
  1171.     public function getIsMaintenance(): ?bool
  1172.     {
  1173.         return $this->isMaintenance;
  1174.     }
  1175.     /**
  1176.      * @param bool|null $isMaintenance
  1177.      *
  1178.      * @return Quote
  1179.      */
  1180.     public function setIsMaintenance(?bool $isMaintenance): Quote
  1181.     {
  1182.         $this->isMaintenance $isMaintenance;
  1183.         return $this;
  1184.     }
  1185.     /**
  1186.      * @return string|null
  1187.      */
  1188.     public function getComment(): ?string
  1189.     {
  1190.         return $this->comment;
  1191.     }
  1192.     /**
  1193.      * @param string|null $comment
  1194.      *
  1195.      * @return Quote
  1196.      */
  1197.     public function setComment(?string $comment): Quote
  1198.     {
  1199.         $this->comment $comment;
  1200.         return $this;
  1201.     }
  1202.     /**
  1203.      * @Groups({"list", "write_post_quote"})
  1204.      *
  1205.      * @return string|null
  1206.      */
  1207.     public function getCreatedBy(): ?string
  1208.     {
  1209.         return $this->createdBy;
  1210.     }
  1211.     /**
  1212.      * @param string|null $createdBy
  1213.      *
  1214.      * @return Quote
  1215.      */
  1216.     public function setCreatedBy(?string $createdBy): Quote
  1217.     {
  1218.         $this->createdBy $createdBy;
  1219.         return $this;
  1220.     }
  1221.     /**
  1222.      * @Groups({"list", "write_post_quote"})
  1223.      *
  1224.      * @return string|null
  1225.      */
  1226.     public function getUpdatedBy(): ?string
  1227.     {
  1228.         return $this->updatedBy;
  1229.     }
  1230.     /**
  1231.      * @param string|null $updatedBy
  1232.      *
  1233.      * @return Quote
  1234.      */
  1235.     public function setUpdatedBy(?string $updatedBy): Quote
  1236.     {
  1237.         $this->updatedBy $updatedBy;
  1238.         return $this;
  1239.     }
  1240.     /**
  1241.      * @Groups({"list", "write_post_quote"})
  1242.      *
  1243.      * @return DateTime|null
  1244.      */
  1245.     public function getCreatedAt(): ?DateTime
  1246.     {
  1247.         return $this->createdAt;
  1248.     }
  1249.     /**
  1250.      * @param DateTime|null $createdAt
  1251.      *
  1252.      * @return Quote
  1253.      */
  1254.     public function setCreatedAt(?DateTime $createdAt): Quote
  1255.     {
  1256.         $this->createdAt $createdAt;
  1257.         return $this;
  1258.     }
  1259.     /**
  1260.      * @Groups({"list", "write_post_quote"})
  1261.      *
  1262.      * @return DateTime|null
  1263.      */
  1264.     public function getUpdatedAt(): ?DateTime
  1265.     {
  1266.         return $this->updatedAt;
  1267.     }
  1268.     /**
  1269.      * @param DateTime|null $updatedAt
  1270.      *
  1271.      * @return Quote
  1272.      */
  1273.     public function setUpdatedAt(?DateTime $updatedAt): Quote
  1274.     {
  1275.         $this->updatedAt $updatedAt;
  1276.         return $this;
  1277.     }
  1278.     /**
  1279.      * @return CustomerFile[]
  1280.      */
  1281.     public function getCustomerFiles()
  1282.     {
  1283.         return $this->customerFiles ?: [];
  1284.     }
  1285.     /**
  1286.      * @param CustomerFile $customerFile
  1287.      *
  1288.      * @return Quote
  1289.      */
  1290.     public function addCustomerFile(CustomerFile $customerFile): self
  1291.     {
  1292.         $this->customerFiles[] = $customerFile;
  1293.         return $this;
  1294.     }
  1295.     /**
  1296.      * @param CustomerFile $customerFile
  1297.      *
  1298.      * @return Quote
  1299.      */
  1300.     public function removeCustomerFile(CustomerFile $customerFile): self
  1301.     {
  1302.         $index array_search($customerFile$this->customerFilestrue);
  1303.         if (false !== $index) {
  1304.             unset($this->customerFiles[$index]);
  1305.         }
  1306.         return $this;
  1307.     }
  1308.     /**
  1309.      * @param CustomerFile[] $customerFiles
  1310.      *
  1311.      * @return Quote
  1312.      */
  1313.     public function setCustomerFiles(array $customerFiles): self
  1314.     {
  1315.         $this->customerFiles $customerFiles;
  1316.         return $this;
  1317.     }
  1318.     /**
  1319.      * {@inheritdoc}
  1320.      */
  1321.     public function getSpecificFields(): Collection
  1322.     {
  1323.         return $this->specificFields;
  1324.     }
  1325.     /**
  1326.      * {@inheritdoc}
  1327.      */
  1328.     public function getSpecificFieldByFieldId(string $id): ?SpecificField
  1329.     {
  1330.         foreach ($this->specificFields as $specificField) {
  1331.             if ($specificField->getFieldId() === $id) {
  1332.                 return $specificField;
  1333.             }
  1334.         }
  1335.         return null;
  1336.     }
  1337.     /**
  1338.      * @see ImportableObjectTrait::class
  1339.      *
  1340.      * @param QuoteSpecificField $specificField
  1341.      *
  1342.      * @return $this
  1343.      */
  1344.     public function addQuoteSpecificField(QuoteSpecificField $specificField): self
  1345.     {
  1346.         return $this->addSpecificField($specificField);
  1347.     }
  1348.     /**
  1349.      * {@inheritdoc}
  1350.      */
  1351.     public function addSpecificField($specificField): SpecificFieldsAwareInterface
  1352.     {
  1353.         $this->specificFields[] = $specificField;
  1354.         return $this;
  1355.     }
  1356.     /**
  1357.      * {@inheritdoc}
  1358.      */
  1359.     public function setSpecificFields(Collection $specificFields): self
  1360.     {
  1361.         $this->specificFields $specificFields;
  1362.         return $this;
  1363.     }
  1364.     /**
  1365.      * @return string|null
  1366.      */
  1367.     public function getWeightedTotal(): ?string
  1368.     {
  1369.         return $this->weightedTotal;
  1370.     }
  1371.     /**
  1372.      * @param string|null $weightedTotal
  1373.      *
  1374.      * @return Quote
  1375.      */
  1376.     public function setWeightedTotal(?string $weightedTotal): Quote
  1377.     {
  1378.         $this->weightedTotal $weightedTotal;
  1379.         return $this;
  1380.     }
  1381.     /**
  1382.      * @return string|null
  1383.      */
  1384.     public function getSectionName(): ?string
  1385.     {
  1386.         return $this->sectionName;
  1387.     }
  1388.     /**
  1389.      * @param string|null $sectionName
  1390.      *
  1391.      * @return Quote
  1392.      */
  1393.     public function setSectionName(?string $sectionName): Quote
  1394.     {
  1395.         $this->sectionName $sectionName;
  1396.         return $this;
  1397.     }
  1398.     /**
  1399.      * @return Quote|null
  1400.      */
  1401.     public function getParent(): ?self
  1402.     {
  1403.         return $this->parent;
  1404.     }
  1405.     /**
  1406.      * @param Quote|null $parent
  1407.      *
  1408.      * @return self
  1409.      */
  1410.     public function setParent(?self $parent): self
  1411.     {
  1412.         $this->parent $parent;
  1413.         return $this;
  1414.     }
  1415.     /**
  1416.      * {@inheritdoc}
  1417.      */
  1418.     public function getChildren(): Collection
  1419.     {
  1420.         return $this->children;
  1421.     }
  1422.     /**
  1423.      * @param Quote[]|Collection $children
  1424.      *
  1425.      * @return self
  1426.      */
  1427.     public function setChildren($children): self
  1428.     {
  1429.         //@todo : trouver le moyen de serializer le self pour récupérer devis1->parent->children qui contient devis1 (iri renvoyé actuellement donc ignoré)
  1430.         if ($children instanceof Collection) {
  1431.             $this->children $children;
  1432.         }
  1433.         return $this;
  1434.     }
  1435.     /**
  1436.      * @deprecated Use addChild() instead.
  1437.      *     This is stupid, but the ImportableObjectTrait checks for adders using add.ucfirst($type) where $type is the class name.
  1438.      *
  1439.      * @param Quote $child
  1440.      *
  1441.      * @return $this
  1442.      */
  1443.     public function addQuote(Quote $child): self
  1444.     {
  1445.         return $this->addChild($child);
  1446.     }
  1447.     /**
  1448.      * @param Quote $child
  1449.      *
  1450.      * @return $this
  1451.      */
  1452.     public function addChild(Quote $child): self
  1453.     {
  1454.         if (!$this->children->contains($child)) {
  1455.             $this->children[] = $child;
  1456.             $child->setParent($this);
  1457.         }
  1458.         return $this;
  1459.     }
  1460.     /**
  1461.      * @param Quote $child
  1462.      *
  1463.      * @return $this
  1464.      */
  1465.     public function removeChildren(Quote $child): self
  1466.     {
  1467.         if ($this->children->contains($child)) {
  1468.             $this->children->removeElement($child);
  1469.             $child->setParent(null);
  1470.         }
  1471.         return $this;
  1472.     }
  1473.     /**
  1474.      * @param string $taskId
  1475.      *
  1476.      * @return bool
  1477.      */
  1478.     public function hasTask(string $taskId): bool
  1479.     {
  1480.         foreach ($this->tasks as $task) {
  1481.             if ($taskId === $task->getExternalValue()) {
  1482.                 return true;
  1483.             }
  1484.         }
  1485.         return false;
  1486.     }
  1487.     /**
  1488.      * @return QuoteTaskExternalRef[]|Collection
  1489.      */
  1490.     public function getTasks(): Collection
  1491.     {
  1492.         return $this->tasks;
  1493.     }
  1494.     /**
  1495.      * @param QuoteTaskExternalRef[]|Collection $tasks
  1496.      *
  1497.      * @return self
  1498.      */
  1499.     public function setTasks(Collection $tasks): self
  1500.     {
  1501.         $this->tasks $tasks;
  1502.         return $this;
  1503.     }
  1504.     /**
  1505.      * @param QuoteTaskExternalRef $task
  1506.      *
  1507.      * @return self
  1508.      */
  1509.     public function addTask(QuoteTaskExternalRef $task): self
  1510.     {
  1511.         if (!$this->tasks->contains($task)) {
  1512.             $this->tasks->add($task);
  1513.         }
  1514.         return $this;
  1515.     }
  1516.     /**
  1517.      * Redondance avec addTask dû au ImportableObjectTrait.
  1518.      *
  1519.      * @param QuoteTaskExternalRef $task
  1520.      *
  1521.      * @return self
  1522.      */
  1523.     public function addQuoteTaskExternalRef(QuoteTaskExternalRef $task): self
  1524.     {
  1525.         return $this->addTask($task);
  1526.     }
  1527.     /**
  1528.      * @param QuoteTaskExternalRef $task
  1529.      *
  1530.      * @return self
  1531.      */
  1532.     public function removeTask(QuoteTaskExternalRef $task): self
  1533.     {
  1534.         if ($this->tasks->contains($task)) {
  1535.             $this->tasks->remove($task);
  1536.         }
  1537.         return $this;
  1538.     }
  1539.     /**
  1540.      * @return QuoteReason|null
  1541.      */
  1542.     public function getReason(): ?QuoteReason
  1543.     {
  1544.         return $this->reason;
  1545.     }
  1546.     /**
  1547.      * @param QuoteReason|null $reason
  1548.      *
  1549.      * @return Quote
  1550.      */
  1551.     public function setReason(?QuoteReason $reason): Quote
  1552.     {
  1553.         $this->reason $reason;
  1554.         return $this;
  1555.     }
  1556.     /**
  1557.      * @return string|null
  1558.      */
  1559.     public function getReasonComment(): ?string
  1560.     {
  1561.         return $this->reasonComment;
  1562.     }
  1563.     /**
  1564.      * @param string|null $reasonComment
  1565.      *
  1566.      * @return Quote
  1567.      */
  1568.     public function setReasonComment(?string $reasonComment): Quote
  1569.     {
  1570.         $this->reasonComment $reasonComment;
  1571.         return $this;
  1572.     }
  1573.     /**
  1574.      * @return string|null
  1575.      */
  1576.     public function getProspectFullName(): ?string
  1577.     {
  1578.         return $this->prospectFullName;
  1579.     }
  1580.     /**
  1581.      * @param string|null $prospectFullName
  1582.      *
  1583.      * @return Quote
  1584.      */
  1585.     public function setProspectFullName(?string $prospectFullName): self
  1586.     {
  1587.         $this->prospectFullName $prospectFullName;
  1588.         return $this;
  1589.     }
  1590.     /**
  1591.      * @return string|null
  1592.      */
  1593.     public function getContactIdRealName(): ?string
  1594.     {
  1595.         return $this->contactIdRealName;
  1596.     }
  1597.     /**
  1598.      * @param string|null $contactIdRealName
  1599.      *
  1600.      * @return Quote
  1601.      */
  1602.     public function setContactIdRealName(?string $contactIdRealName): self
  1603.     {
  1604.         $this->contactIdRealName $contactIdRealName;
  1605.         return $this;
  1606.     }
  1607.     /**
  1608.      * @return string
  1609.      */
  1610.     public function getManagedByRealName(): ?string
  1611.     {
  1612.         return $this->managedByRealName;
  1613.     }
  1614.     /**
  1615.      * @param string $managedByRealName
  1616.      *
  1617.      * @return Quote
  1618.      */
  1619.     public function setManagedByRealName(?string $managedByRealName): Quote
  1620.     {
  1621.         $this->managedByRealName $managedByRealName;
  1622.         return $this;
  1623.     }
  1624.     /**
  1625.      * @param string|null $taskId
  1626.      *
  1627.      * @return void
  1628.      */
  1629.     public function removeQuoteTaskExternalRefByExternalValue(?string $taskId)
  1630.     {
  1631.         foreach ($this->tasks as $task) {
  1632.             if ($taskId === $task->getExternalValue()) {
  1633.                 $this->removeTask($task);
  1634.             }
  1635.         }
  1636.     }
  1637. }