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

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