src/Entity/Project.php line 17

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Repository\ProjectRepository;
  4. use App\Service\CurrencyService;
  5. use Doctrine\Common\Collections\ArrayCollection;
  6. use Doctrine\Common\Collections\Collection;
  7. use Doctrine\Common\Collections\Criteria;
  8. use Doctrine\DBAL\Types\Types;
  9. use Doctrine\ORM\Mapping as ORM;
  10. use Exception;
  11. use GuzzleHttp\Exception\GuzzleException;
  12. use Symfony\Component\Serializer\Annotation\Groups;
  13. #[ORM\Entity(repositoryClassProjectRepository::class)]
  14. class Project
  15. {
  16.     #[ORM\Id]
  17.     #[ORM\GeneratedValue]
  18.     #[ORM\Column(type'integer')]
  19.     #[Groups(['LogService'])]
  20.     private $id;
  21.     #[Groups(['LogService'])]
  22.     #[ORM\Column(type'string'length255)]
  23.     private $name;
  24.     #[ORM\Column(type'text'nullabletrue)]
  25.     #[Groups(['LogService'])]
  26.     private $description;
  27.     #[ORM\ManyToOne(targetEntityClient::class, inversedBy'projects')]
  28.     #[ORM\JoinColumn(nullabletrue)]
  29.     private $client;
  30.     #[ORM\OneToMany(targetEntityTask::class, mappedBy'project'fetch'EXTRA_LAZY')]
  31.     #[ORM\OrderBy(['week' => 'ASC'])]
  32.     private $tasks;
  33.     #[ORM\OneToMany(targetEntityVendorQuotationPlanning::class, mappedBy'project'fetch'EXTRA_LAZY')]
  34.     private $vendorQuotationPlannings;
  35.     #[ORM\OneToMany(targetEntitySalesOrder::class, mappedBy'project'fetch'EXTRA_LAZY')]
  36.     private $salesOrders;
  37.     #[ORM\Column(type'datetime'nullabletrue)]
  38.     #[Groups(['LogService'])]
  39.     private $createdAt;
  40.     #[ORM\Column(type'datetime'nullabletrue)]
  41.     #[Groups(['LogService'])]
  42.     private $updatedAt;
  43.     #[ORM\Column(type'date'nullabletrue)]
  44.     private $winDate;
  45.     #[ORM\Column(type'date'nullabletrue)]
  46.     private $startDate;
  47.     #[ORM\Column(type'date'nullabletrue)]
  48.     private $endDate;
  49.     #[ORM\ManyToOne(targetEntityUser::class, inversedBy'projects')]
  50.     private $createdBy;
  51.     #[Groups(['LogService'])]
  52.     #[ORM\ManyToOne(targetEntityUser::class, inversedBy'projectsUserIsPIC')]
  53.     private $personInCharge;
  54.     #[Groups(['LogService'])]
  55.     #[ORM\Column(type'string'length20nullabletrue)]
  56.     private $status;
  57.     #[Groups(['LogService'])]
  58.     #[ORM\Column(type'float'nullabletrue)]
  59.     private $plannedRevenue 0;
  60.     #[ORM\Column(type'float'nullabletrue)]
  61.     private $plannedRevenueUsd;
  62.     #[ORM\ManyToOne(targetEntityCurrency::class, inversedBy'projects')]
  63.     private $currency;
  64.     #[ORM\Column(type'string'length255nullabletrue)]
  65.     private $planFilename;
  66.     #[ORM\Column(type'string'length255nullabletrue)]
  67.     private $planFilepath;
  68.     #[ORM\Column(type'string'length192nullabletrue)]
  69.     private $planFiletype;
  70.     #[ORM\OneToMany(targetEntityProjectMember::class, mappedBy'project'orphanRemovaltruefetch'EXTRA_LAZY')]
  71.     private $projectMembers;
  72.     #[ORM\Column(type'datetime_immutable'nullabletrue)]
  73.     private $deletedAt;
  74.     #[ORM\ManyToMany(targetEntityDepartment::class)]
  75.     private $department;
  76.     #[ORM\Column(type'boolean'nullabletrue)]
  77.     private $retainer;
  78.     #[Groups(['LogService'])]
  79.     #[ORM\Column(name'`lead`'type'smallint'nullabletrue)]
  80.     private $lead;
  81.     #[ORM\Column(type'string'length20nullabletrue)]
  82.     private $type;
  83.     #[ORM\Column(type'date'nullabletrue)]
  84.     private $leadDate;
  85.     #[ORM\Column(type'date'nullabletrue)]
  86.     private $proposalDate;
  87.     #[ORM\Column(type'text'nullabletrue)]
  88.     private $planURL;
  89.     #[ORM\Column(type'float'nullabletrue)]
  90.     private $estimatedProfit 0;
  91.     #[ORM\Column(type'boolean'nullabletrueoptions: ['default' => false])]
  92.     private $noEstimatedVendorCost;
  93.     #[ORM\Column(type'float'nullabletrue)]
  94.     private $estimatedVendorCost 0;
  95.     #[ORM\Column(type'float'nullabletrue)]
  96.     private $estimatedVendorCostUsd;
  97.     #[ORM\OneToMany(targetEntityProjectSalesOrder::class, mappedBy'project'fetch'EXTRA_LAZY')]
  98.     private $projectSalesOrders;
  99.     #[ORM\OneToMany(targetEntityProjectAllocatedHours::class, mappedBy'project'fetch'EXTRA_LAZY')]
  100.     private $projectAllocatedHours;
  101.     #[ORM\Column(type'string'length50nullabletrue)]
  102.     private $leadSource;
  103.     #[ORM\Column(type'datetime_immutable'nullabletrue)]
  104.     private $lastReminder;
  105.     #[ORM\Column(type'string'length9nullabletrue)]
  106.     private $generatedId;
  107.     #[Groups(['LogService'])]
  108.     #[ORM\Column(type'datetime_immutable'nullabletrue)]
  109.     private $leadFailDate;
  110.     #[Groups(['LogService'])]
  111.     #[ORM\Column(type'text'nullabletrue)]
  112.     private $leadFailNote;
  113.     #[Groups(['LogService'])]
  114.     #[ORM\Column(type'datetime_immutable'nullabletrue)]
  115.     private $leadFailRemindDate;
  116.     #[Groups(['LogService'])]
  117.     #[ORM\ManyToOne(targetEntityClientContact::class, inversedBy'projects')]
  118.     private $clientPersonInCharge;
  119.     #[ORM\OneToMany(targetEntitySalesOrderPurchaseOrder::class, mappedBy'project'fetch'EXTRA_LAZY')]
  120.     private $salesOrderPurchaseOrders;
  121.     #[ORM\Column(type'smallint'nullabletrue)]
  122.     private $probability;
  123.     #[ORM\Column(type'boolean'nullabletrueoptions: ['default' => false])]
  124.     private $noPresentation;
  125.     #[ORM\Column(type'date'nullabletrue)]
  126.     private $presentationDate;
  127.     #[ORM\ManyToMany(targetEntityProjectClassification::class, inversedBy'projectsOfType')]
  128.     private $projectTypes;
  129.     #[ORM\ManyToMany(targetEntityIndustryClassification::class, inversedBy'projectsOfIndustry')]
  130.     private $projectIndustries;
  131.     #[ORM\Column(type'date'nullabletrue)]
  132.     private $proposalFollowUpDate;
  133.     #[ORM\ManyToOne(targetEntityProjectLeadStatus::class)]
  134.     private $leadStatus;
  135.     #[ORM\OneToMany(targetEntityRevenuePlanning::class, mappedBy'project'fetch'EXTRA_LAZY')]
  136.     private $revenuePlannings;
  137.     #[ORM\ManyToOne(inversedBy'projects')]
  138.     private ?ProjectLostReason $leadFail null;
  139.     #[ORM\OneToOne(targetEntityProjectDeliverable::class, mappedBy'project'cascade: ['persist''remove'])]
  140.     private $projectDeliverable;
  141.     #[ORM\OneToMany(mappedBy'project'targetEntityClientFeedback::class, cascade: ['persist''remove'])]
  142.     private Collection $clientFeedback;
  143.     #[ORM\ManyToOne(inversedBy'projects')]
  144.     private ?ClientFeedbackTemplate $clientFeedbackTemplate null;
  145.     #[ORM\Column(nullabletrue)]
  146.     private ?float $score null;
  147.     #[ORM\OneToMany(mappedBy'project'targetEntityExpenseRequest::class)]
  148.     private Collection $expenseRequests;
  149.     #[ORM\OneToMany(mappedBy'project'targetEntityChecklist::class)]
  150.     #[ORM\OneToOne(mappedBy'project'cascade: ['persist''remove'])]
  151.     private ?ProjectLostFilter $projectLostFilter null;
  152.     #[ORM\OneToMany(mappedBy'project'targetEntityChecklist::class, cascade: ['persist'])]
  153.     private Collection $checklists;
  154.     #[ORM\Column(typeTypes::TEXTnullabletrue)]
  155.     private ?string $brief null;
  156.     #[ORM\Column(length255nullabletrue)]
  157.     private ?string $mattermost null;
  158.     #[ORM\OneToMany(mappedBy'project'targetEntityProjectDynamicField::class, orphanRemovaltrue)]
  159.     private Collection $projectDynamicFields;
  160.     #[ORM\OneToOne(mappedBy'project'cascade: ['persist''remove'])]
  161.     private ?ProjectHosting $projectHosting null;
  162.     public function __clone()
  163.     {
  164.         $this->id null;
  165.     }
  166.     public function __construct()
  167.     {
  168.         $this->tasks = new ArrayCollection();
  169.         $this->vendorQuotationPlannings = new ArrayCollection();
  170.         $this->salesOrders = new ArrayCollection();
  171.         $this->projectMembers = new ArrayCollection();
  172.         $this->department = new ArrayCollection();
  173.         $this->projectSalesOrders = new ArrayCollection();
  174.         $this->projectAllocatedHours = new ArrayCollection();
  175.         $this->salesOrderPurchaseOrders = new ArrayCollection();
  176.         $this->projectTypes = new ArrayCollection();
  177.         $this->projectIndustries = new ArrayCollection();
  178.         $this->revenuePlannings = new ArrayCollection();
  179.         $this->clientFeedback = new ArrayCollection();
  180.         $this->expenseRequests = new ArrayCollection();
  181.         $this->checklists = new ArrayCollection();
  182.         $this->projectDynamicFields = new ArrayCollection();
  183.     }
  184.     public function getCreatedAt(): ?\DateTimeInterface
  185.     {
  186.         return $this->createdAt;
  187.     }
  188.     public function setCreatedAt(?\DateTimeInterface $createdAt): self
  189.     {
  190.         $this->createdAt $createdAt;
  191.         return $this;
  192.     }
  193.     public function getUpdatedAt(): ?\DateTimeInterface
  194.     {
  195.         return $this->updatedAt;
  196.     }
  197.     public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
  198.     {
  199.         $this->updatedAt $updatedAt;
  200.         return $this;
  201.     }
  202.     public function getId(): ?int
  203.     {
  204.         return $this->id;
  205.     }
  206.     public function getName(): ?string
  207.     {
  208.         return $this->name;
  209.     }
  210.     public function setName(string $name): self
  211.     {
  212.         $this->name $name;
  213.         return $this;
  214.     }
  215.     public function fullName()
  216.     {
  217.         return $this->generatedId $this->generatedId '-' $this->name $this->name;
  218.     }
  219.     public function getDescription(): ?string
  220.     {
  221.         return $this->description;
  222.     }
  223.     public function setDescription(?string $description): self
  224.     {
  225.         $this->description $description;
  226.         return $this;
  227.     }
  228.     public function getClient(): ?Client
  229.     {
  230.         return $this->client;
  231.     }
  232.     public function setClient(?Client $client): self
  233.     {
  234.         $this->client $client;
  235.         return $this;
  236.     }
  237.     /**
  238.      * @return Collection<int, Task>
  239.      */
  240.     public function getTasks(): Collection
  241.     {
  242.         return $this->tasks;
  243.     }
  244.     public function addTask(Task $task): self
  245.     {
  246.         if (!$this->tasks->contains($task)) {
  247.             $this->tasks[] = $task;
  248.             $task->setProject($this);
  249.         }
  250.         return $this;
  251.     }
  252.     public function removeTask(Task $task): self
  253.     {
  254.         if ($this->tasks->removeElement($task)) {
  255.             // set the owning side to null (unless already changed)
  256.             if ($task->getProject() === $this) {
  257.                 $task->setProject(null);
  258.             }
  259.         }
  260.         return $this;
  261.     }
  262.     /**
  263.      * @return Collection<int, VendorQuotationPlanning>
  264.      */
  265.     public function getVendorQuotationPlannings(): Collection
  266.     {
  267.         return $this->vendorQuotationPlannings;
  268.     }
  269.     public function addVendorQuotationPlanning(VendorQuotationPlanning $vendorQuotationPlanning): self
  270.     {
  271.         if (!$this->vendorQuotationPlannings->contains($vendorQuotationPlanning)) {
  272.             $this->vendorQuotationPlannings[] = $vendorQuotationPlanning;
  273.             $vendorQuotationPlanning->setProject($this);
  274.         }
  275.         return $this;
  276.     }
  277.     public function removeVendorQuotationPlanning(VendorQuotationPlanning $vendorQuotationPlanning): self
  278.     {
  279.         if ($this->vendorQuotationPlannings->removeElement($vendorQuotationPlanning)) {
  280.             // set the owning side to null (unless already changed)
  281.             if ($vendorQuotationPlanning->getProject() === $this) {
  282.                 $vendorQuotationPlanning->setProject(null);
  283.             }
  284.         }
  285.         return $this;
  286.     }
  287.     /**
  288.      *
  289.      * @return Collection<int, SalesOrder>
  290.      */
  291.     public function getSalesOrders(): Collection
  292.     {
  293.         return $this->salesOrders;
  294.     }
  295.     //    public function addSalesOrder(SalesOrder $salesOrder): self
  296.     //    {
  297.     //        if (!$this->salesOrders->contains($salesOrder)) {
  298.     //            $this->salesOrders[] = $salesOrder;
  299.     //            $salesOrder->setProject($this);
  300.     //        }
  301.     //
  302.     //        return $this;
  303.     //    }
  304.     public function removeSalesOrder(SalesOrder $salesOrder): self
  305.     {
  306.         if ($this->salesOrders->removeElement($salesOrder)) {
  307.             // set the owning side to null (unless already changed)
  308.             if ($salesOrder->getProject() === $this) {
  309.                 $salesOrder->setProject(null);
  310.             }
  311.         }
  312.         return $this;
  313.     }
  314.     public function getWinDate(): ?\DateTimeInterface
  315.     {
  316.         return $this->winDate;
  317.     }
  318.     public function setWinDate(?\DateTimeInterface $winDate): self
  319.     {
  320.         $this->winDate $winDate;
  321.         return $this;
  322.     }
  323.     public function getStartDate(): ?\DateTimeInterface
  324.     {
  325.         return $this->startDate;
  326.     }
  327.     public function setStartDate(?\DateTimeInterface $startDate): self
  328.     {
  329.         $this->startDate $startDate;
  330.         return $this;
  331.     }
  332.     public function getEndDate(): ?\DateTimeInterface
  333.     {
  334.         return $this->endDate;
  335.     }
  336.     public function setEndDate(?\DateTimeInterface $endDate): self
  337.     {
  338.         $this->endDate $endDate;
  339.         return $this;
  340.     }
  341.     public function getCreatedBy(): ?User
  342.     {
  343.         return $this->createdBy;
  344.     }
  345.     public function setCreatedBy(?User $createdBy): self
  346.     {
  347.         $this->createdBy $createdBy;
  348.         return $this;
  349.     }
  350.     public function getPersonInCharge(): ?User
  351.     {
  352.         return $this->personInCharge;
  353.     }
  354.     public function setPersonInCharge(?User $personInCharge): self
  355.     {
  356.         $this->personInCharge $personInCharge;
  357.         return $this;
  358.     }
  359.     public function getStatus(): ?string
  360.     {
  361.         return $this->status;
  362.     }
  363.     public function setStatus(?string $status): self
  364.     {
  365.         $this->status $status;
  366.         return $this;
  367.     }
  368.     public function getPlannedRevenue(): ?float
  369.     {
  370.         return $this->plannedRevenue;
  371.     }
  372.     public function setPlannedRevenue(?float $plannedRevenue): self
  373.     {
  374.         $this->plannedRevenue $plannedRevenue;
  375.         $this->plannedRevenueUsd $this->getPlannedRevenueToUsd($plannedRevenue);
  376.         return $this;
  377.     }
  378.     // public function getPlannedRevenueUsd(): ?float
  379.     // {
  380.     //     if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->plannedRevenue;
  381.     //     global $kernel;
  382.     //     $currencyService = $kernel->getContainer()->get('CurrencyService');
  383.     //     $dateStr = $this->createdAt->format('Y-m-d');
  384.     //     return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->plannedRevenue);
  385.     // }
  386.     public function getCurrency(): ?Currency
  387.     {
  388.         if (!$this->currency) {
  389.             global $kernel;
  390.             $currencyRepository $kernel->getContainer()->get('doctrine')->getRepository(Currency::class);
  391.             return $currencyRepository->findOneBy(['id' => 1]);
  392.         }
  393.         return $this->currency;
  394.     }
  395.     public function setCurrency(?Currency $currency): self
  396.     {
  397.         $this->currency $currency;
  398.         return $this;
  399.     }
  400.     public function getPlanFilename(): ?string
  401.     {
  402.         return $this->planFilename;
  403.     }
  404.     public function setPlanFilename(?string $planFilename): self
  405.     {
  406.         $this->planFilename $planFilename;
  407.         return $this;
  408.     }
  409.     public function getPlanFilepath(): ?string
  410.     {
  411.         return $this->planFilepath;
  412.     }
  413.     public function setPlanFilepath(?string $planFilepath): self
  414.     {
  415.         $this->planFilepath $planFilepath;
  416.         return $this;
  417.     }
  418.     public function getPlanFiletype(): ?string
  419.     {
  420.         return $this->planFiletype;
  421.     }
  422.     public function setPlanFiletype(?string $planFiletype): self
  423.     {
  424.         $this->planFiletype $planFiletype;
  425.         return $this;
  426.     }
  427.     public function getSoTotal()
  428.     {
  429.         $total 0;
  430.         $projectSalesOrders $this->getProjectSalesOrders();
  431.         foreach ($projectSalesOrders as $pso) {
  432.             $total += $pso->getAmount();
  433.         }
  434.         return $total;
  435.     }
  436.     public function getSoTotalUsd()
  437.     {
  438.         global $kernel;
  439.         $currencyService $kernel->getContainer()->get('CurrencyService');
  440.         $total 0;
  441.         $projectSalesOrders $this->getProjectSalesOrders();
  442.         foreach ($projectSalesOrders as $pso) {
  443.             // $total += $pso->getAmountUsd();
  444.             $total += $currencyService->convertAtDate($this->createdAt$pso->getSalesOrder()->getCurrency()->getIso(), 'USD'$pso->getAmount());
  445.         }
  446.         return round($total2PHP_ROUND_HALF_EVEN);
  447.     }
  448.     public function getInvoicesTotalPaid()
  449.     {
  450.         $total 0;
  451.         $projectSalesOrders $this->getProjectSalesOrders();
  452.         foreach ($projectSalesOrders as $pso) {
  453.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  454.             foreach ($soInvoices as $soInvoice) {
  455.                 if ($soInvoice->getProject()->getId() != $this->id) continue;
  456.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  457.                 if ($soInvoice->getInvoice()->getAmountDue() == 0) {
  458.                     $total += $soInvoice->getAmount();
  459.                 }
  460.             }
  461.         }
  462.         return $total;
  463.     }
  464.     public function getInvoicesTotalPaidUsd()
  465.     {
  466.         global $kernel;
  467.         $currencyService $kernel->getContainer()->get('CurrencyService');
  468.         $total 0;
  469.         $projectSalesOrders $this->getProjectSalesOrders();
  470.         foreach ($projectSalesOrders as $pso) {
  471.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  472.             foreach ($soInvoices as $soInvoice) {
  473.                 if ($soInvoice->getProject()->getId() != $this->id) continue;
  474.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  475.                 if ($soInvoice->getInvoice()->getAmountDue() == 0) {
  476.                     $invDateStr $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
  477.                     // $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
  478.                     $total += $currencyService->convertAtDate($this->createdAt$soInvoice->getInvoice()->getCurrency()->getIso(), 'USD'$soInvoice->getAmount());
  479.                 }
  480.             }
  481.         }
  482.         return round($total2PHP_ROUND_HALF_EVEN);
  483.     }
  484.     public function getInvoicesTotal()
  485.     {
  486.         $total 0;
  487.         $projectSalesOrders $this->getProjectSalesOrders();
  488.         foreach ($projectSalesOrders as $pso) {
  489.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  490.             foreach ($soInvoices as $soInvoice) {
  491.                 if ($soInvoice->getProject()->getId() != $this->id) continue;
  492.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  493.                 $total += $soInvoice->getAmount();
  494.             }
  495.         }
  496.         return $total;
  497.     }
  498.     /**
  499.      * @throws GuzzleException
  500.      */
  501.     public function getInvoicesTotalUsd($endDate null)
  502.     {
  503.         global $kernel;
  504.         $currencyService $kernel->getContainer()->get('CurrencyService');
  505.         $total 0;
  506.         $projectSalesOrders $this->getProjectSalesOrders();
  507.         foreach ($projectSalesOrders as $pso) {
  508.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  509.             foreach ($soInvoices as $soInvoice) {   
  510.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  511.                 if ($endDate != null  && $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d') > $endDate->format('Ymd')) continue;
  512.                 if ($soInvoice->getProject()->getId() != $this->id) continue;
  513.                 $invDateStr $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
  514.                 // $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
  515.                 $total += $currencyService->convertAtDate($this->createdAt$soInvoice->getInvoice()->getCurrency()->getIso(), 'USD',  $soInvoice->getAmount());
  516.             }
  517.         }
  518.         return round($total2PHP_ROUND_HALF_EVEN);
  519.     }
  520.     /**
  521.      * @throws GuzzleException
  522.      */
  523.     public function getInvoicesTotalUsdByMonth($startDate$endDate)
  524.     {
  525.         global $kernel;
  526.         $currencyService $kernel->getContainer()->get('CurrencyService');
  527.         $total 0;
  528.         $projectSalesOrders $this->getProjectSalesOrders();
  529.         foreach ($projectSalesOrders as $pso) {
  530.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  531.             foreach ($soInvoices as $soInvoice) {
  532.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  533.                 if ($soInvoice->getInvoice()->getInvoiceDate()->format('Ymd') < $startDate->format('Ymd')) continue;
  534.                 if ($soInvoice->getInvoice()->getInvoiceDate()->format('Ymd') > $endDate->format('Ymd')) continue;
  535.                 if ($soInvoice->getProject()->getId() != $this->id) continue;
  536.                 $invDateStr $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
  537.                 // $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
  538.                 $total += $currencyService->convertAtDate($this->createdAt$soInvoice->getInvoice()->getCurrency()->getIso(), 'USD'$soInvoice->getAmount());
  539.             }
  540.         }
  541.         return round($total2PHP_ROUND_HALF_EVEN);
  542.     }
  543.     /**
  544.      * @throws GuzzleException
  545.      */
  546.     public function getAllocatedInvoicesTotal($paid false)
  547.     {
  548.         global $kernel;
  549.         $total 0;
  550.         $projectSalesOrders $this->getProjectSalesOrders();
  551.         foreach ($projectSalesOrders as $pso) {
  552.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  553.             foreach ($soInvoices as $soInvoice) {
  554.                 if ($soInvoice->getInvoice()->getXeroStatus() == "VOIDED" || $soInvoice->getProject() !== $this) continue;
  555.                 if ($paid && $soInvoice->getInvoice()->getXeroStatus() == "PAID") continue;
  556.                 $total += $soInvoice->getAmount();
  557.                 if ($soInvoice->getInvoice()->getXeroCreditNoteAllocation()) {
  558.                     $total -= $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmount();
  559.                 }
  560.             }
  561.         }
  562.         return $total;
  563.     }
  564.     /**
  565.      * @throws GuzzleException
  566.      */
  567.     public function getAllocatedInvoicesTotalUsd($paid false)
  568.     {
  569.         global $kernel;
  570.         $currencyService $kernel->getContainer()->get('CurrencyService');
  571.         $total 0;
  572.         $projectSalesOrders $this->getProjectSalesOrders();
  573.         foreach ($projectSalesOrders as $pso) {
  574.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  575.             foreach ($soInvoices as $soInvoice) {
  576.                 if ($soInvoice->getInvoice()->getXeroStatus() == "VOIDED" || $soInvoice->getProject() !== $this) continue;
  577.                 if ($paid && $soInvoice->getInvoice()->getXeroStatus() == "PAID") continue;
  578.                 // $invDateStr = $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
  579.                 // $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
  580.                 // $total += $usValue;
  581.                 // $total += $soInvoice->getAmountUsd();
  582.                 $total += $currencyService->convertAtDate($this->createdAt$this->currency->getIso(), 'USD'$soInvoice->getAmount());
  583.                 if ($soInvoice->getInvoice()->getXeroCreditNoteAllocation()) {
  584.                     // $total -= $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmountUsd();
  585.                     $total -= $currencyService->convertAtDate($this->createdAt$soInvoice->getInvoice()->getCurrency()->getIso(), 'USD'$soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmount());
  586.                 }
  587.             }
  588.         }
  589.         return round($total2PHP_ROUND_HALF_EVEN);
  590.     }
  591.     /**
  592.      * @throws GuzzleException
  593.      */
  594.     public function getAllocatedInvoicesTotalSgd($paid false)
  595.     {
  596.         global $kernel;
  597.         $currencyService $kernel->getContainer()->get('CurrencyService');
  598.         $total 0;
  599.         $projectSalesOrders $this->getProjectSalesOrders();
  600.         foreach ($projectSalesOrders as $pso) {
  601.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  602.             foreach ($soInvoices as $soInvoice) {
  603.                 if ($soInvoice->getInvoice()->getXeroStatus() == "VOIDED" || $soInvoice->getProject() !== $this) continue;
  604.                 if ($paid && $soInvoice->getInvoice()->getXeroStatus() == "PAID") continue;
  605.                 // $invDateStr = $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
  606.                 // $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
  607.                 // $total += $usValue;
  608.                 // $total += $soInvoice->getAmountUsd();
  609.                 $total += $currencyService->convertAtDate($this->createdAt$this->currency->getIso(), 'SGD'$soInvoice->getAmount());
  610.                 if ($soInvoice->getInvoice()->getXeroCreditNoteAllocation()) {
  611.                     // $total -= $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmountUsd();
  612.                     $total -= $currencyService->convertAtDate($this->createdAt$soInvoice->getInvoice()->getCurrency()->getIso(), 'SGD'$soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmount());
  613.                 }
  614.             }
  615.         }
  616.         return round($total2PHP_ROUND_HALF_EVEN);
  617.     }
  618.     public function getTotalVQPPlannedAmt()
  619.     {
  620.         $total 0;
  621.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  622.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  623.             $total += $vendorQuotationPlanning->getAmountPlanned();
  624.         }
  625.         return $total;
  626.     }
  627.     public function getVendorQuotesTotalUSD()
  628.     {
  629.         global $kernel;
  630.         $currencyService $kernel->getContainer()->get('CurrencyService');
  631.         $total 0;
  632.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  633.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  634.             $vendorQuotations $vendorQuotationPlanning->getVendorQuotations();
  635.             foreach ($vendorQuotations as $vendorQuotation) {
  636.                 // $usValue = $currencyService->convertAtDate($vendorQuotation->getCreatedAt()->format('Y-m-d'), $vendorQuotation->getCurrency()->getIso(), 'USD', $vendorQuotation->getAmount());
  637.                 $total += $currencyService->convertAtDate($this->createdAt$vendorQuotation->getCurrency()->getIso(), 'USD'$vendorQuotation->getAmount());
  638.             }
  639.         }
  640.         return round($total2PHP_ROUND_HALF_EVEN);
  641.     }
  642.     public function getVendorQuotesTotal()
  643.     {
  644.         $total 0;
  645.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  646.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  647.             $vendorQuotations $vendorQuotationPlanning->getVendorQuotations();
  648.             foreach ($vendorQuotations as $vendorQuotation) {
  649.                 $total += $vendorQuotation->getAmount();
  650.             }
  651.         }
  652.         return $total;
  653.     }
  654.     public function getProjectManhour($endDate null)
  655.     {
  656.         $total 0;
  657.         $tasks $this->getTasks();
  658.         foreach ($tasks as $task) {
  659.             $timeSpents $task->getTimeSpents();
  660.             foreach ($timeSpents as $timeSpent) {
  661.                 $timeSpentDate $timeSpent->getDate()->format('Ymd');
  662.                 //if ($this->startDate != null && $timeSpentDate < $this->startDate->format('Ymd')) continue;
  663.                 if ($this->endDate != null && $timeSpentDate $this->endDate->format('Ymd')) continue;
  664.                 //if ($endDate != null && $timeSpentDate > $endDate->format('Ymd')) continue;
  665.                 $hours $timeSpent->getHours();
  666.                 $total += $hours;
  667.             };
  668.         }
  669.         return $total;
  670.     }
  671.     public function getProjectManhourByMonth($startDate$endDate)
  672.     {
  673.         $total 0;
  674.         $tasks $this->getTasks();
  675.         foreach ($tasks as $task) {
  676.             $timeSpents $task->getTimeSpents();
  677.             foreach ($timeSpents as $timeSpent) {
  678.                 $timeSpentDate $timeSpent->getDate()->format('Ymd');
  679.                 //if ($this->startDate != null && $timeSpentDate < $this->startDate->format('Ymd')) continue;
  680.                 if ($this->endDate != null && $timeSpentDate $this->endDate->format('Ymd')) continue;
  681.                 $hours $timeSpent->getHours();
  682.                 $total += $hours;
  683.             };
  684.         }
  685.         return $total;
  686.     }
  687.     public function getProjectManhourCost($endDate null// FIX: error on manhourcost
  688.     {
  689.         // error_reporting(E_ALL);
  690.         // ini_set('display_errors', 1);
  691.         $total 0;
  692.         $tasks $this->getTasks();
  693.         foreach ($tasks as $task) {
  694.             //     try {
  695.             //     print_r($task->getTimeSpents());
  696.             // } catch (Exception $e) {
  697.             //     echo 'Caught exception: ',  $e->getMessage(), "\n";
  698.             // }
  699.             //     return 0;
  700.             $timeSpents $task->getTimeSpents();
  701.             foreach ($timeSpents as $timeSpent) {
  702.                 $timeSpentDate $timeSpent->getDate()->format('Ymd');
  703.                 if ($this->startDate == null || $this->endDate == null) continue;
  704.                 if ($this->endDate != null && $timeSpentDate $this->endDate->format('Ymd')) continue;
  705.                 $hours $timeSpent->getHours() ?? 0;
  706.                 $rate $timeSpent->getUser()->getHourlyRateUsd($timeSpentDate) ?? 0;
  707.                 $total += $hours $rate;
  708.             }
  709.         }
  710.         return round($total2PHP_ROUND_HALF_EVEN);
  711.     }
  712.     public function getProjectManhourCostByMonth($startDate$endDate)
  713.     {
  714.         $total 0;
  715.         $tasks $this->getTasks();
  716.         foreach ($tasks as $task) {
  717.             $timeSpents $task->getTimeSpents();
  718.             foreach ($timeSpents as $timeSpent) {
  719.                 $timeSpentDate $timeSpent->getDate()->format('Ymd');
  720.                 //if ($this->startDate != null && $timeSpentDate < $this->startDate->format('Ymd')) continue;
  721.                 if ($this->endDate != null && $timeSpentDate $this->endDate->format('Ymd')) continue;
  722.                 $hours $timeSpent->getHours();
  723.                 $rate $timeSpent->getUser()->getHourlyRateUsd($timeSpentDate);
  724.                 $total += $hours $rate;
  725.             }
  726.         }
  727.         return round($total2PHP_ROUND_HALF_EVEN);
  728.     }
  729.     public function getProjectCost()
  730.     {
  731.         return $this->getVendorInvoicesTotalUSD() + $this->getProjectManhourCost();
  732.     }
  733.     public function getProjectEstimatedCost()
  734.     {
  735.         $totalEstimatedManHourCost 0;
  736.         foreach ($this->projectAllocatedHours as $allocation) {
  737.             $totalEstimatedManHourCost += intval($allocation->getHours() * $allocation->getUserRole()->getCost());
  738.         }
  739.         return $this->getEstimatedVendorCostUsd() + $totalEstimatedManHourCost;
  740.     }
  741.     public function getProjectEstimatedHourCost()
  742.     {
  743.         $totalEstimatedManHourCost 0;
  744.         foreach ($this->projectAllocatedHours as $allocation) {
  745.             $totalEstimatedManHourCost += intval($allocation->getHours() * $allocation->getUserRole()->getCost());
  746.         }
  747.         return $totalEstimatedManHourCost;
  748.     }
  749.     public function getProjectEstimatedHour()
  750.     {
  751.         $totalEstimatedManHour 0;
  752.         foreach ($this->projectAllocatedHours as $allocation) {
  753.             $totalEstimatedManHour += intval($allocation->getHours());
  754.         }
  755.         return $totalEstimatedManHour;
  756.     }
  757.     public function getProjectEstimatedCostUsd()
  758.     {
  759.         if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->getProjectEstimatedCost();
  760.         global $kernel;
  761.         $currencyService $kernel->getContainer()->get('CurrencyService');
  762.         $dateStr $this->createdAt->format('Y-m-d');
  763.         $amount $currencyService->convertAtDate($dateStr$this->currency->getIso(), 'USD'$this->getProjectEstimatedCost());
  764.         return round($amount2PHP_ROUND_HALF_EVEN);
  765.     }
  766.     /**
  767.      * [sum]Invoices sent to client - [sum] Vendors invoices - man hours = Total Profit
  768.      * @throws GuzzleException
  769.      */
  770.     public function getProjectProfit1()
  771.     {
  772.         return round($this->getInvoicesTotalUsd() - $this->getProjectCost(), 2PHP_ROUND_HALF_EVEN);
  773.     }
  774.     /**
  775.      * [sum]SalesOrders sent to client - [sum] Vendors invoices - man hours = Total Profit
  776.      */
  777.     public function getProjectProfit2()
  778.     {
  779.         return round($this->getSoTotalUsd() - $this->getVendorInvoicesTotalUSD() - $this->getProjectManhourCost(), 2PHP_ROUND_HALF_EVEN);
  780.     }
  781.     /**
  782.      * [sum]SalesOrders sent to client - [sum] Vendor Plan - man hours = Total Profit
  783.      */
  784.     public function getProjectProfit3()
  785.     {
  786.         // return $this->getSoTotalUsd() - $this->getVendorQuotesTotalUSD() - $this->getProjectManhourCost();
  787.         return round($this->getSoTotalUsd() - $this->getVendorPlannedTotalUsd() - $this->getProjectManhourCost(), 2PHP_ROUND_HALF_EVEN);
  788.     }
  789.     /**
  790.      * [sum]INV sent to client - [sum] Vendors plan - man hours = Total Profit
  791.      * @throws GuzzleException
  792.      */
  793.     public function getProjectProfit4()
  794.     {
  795.         // return $this->getInvoicesTotalUsd() - $this->getVendorQuotesTotalUSD() - $this->getProjectManhourCost();
  796.         return round($this->getInvoicesTotalUsd() - $this->getVendorPlannedTotalUsd() - $this->getProjectManhourCost(), 2PHP_ROUND_HALF_EVEN);
  797.     }
  798.     /**
  799.      * (Total Invoices - vendor invoice total- manhourCost) * 100 / total invoices
  800.      * @throws GuzzleException
  801.      */
  802.     public function getProjectGrossmargin1()
  803.     {
  804.         if ($this->getInvoicesTotalUsd() == || $this->getProjectProfit1() == 0) return 0;
  805.         return round($this->getProjectProfit1() / $this->getInvoicesTotalUsd() * 1002PHP_ROUND_HALF_EVEN);
  806.     }
  807.     /**
  808.      *
  809.      * (SO total - Vendor INV total - manhourCost) * 100 / SO total
  810.      * @throws GuzzleException
  811.      */
  812.     public function getProjectGrossmargin2()
  813.     {
  814.         if ($this->getSoTotalUsd() == || $this->getProjectProfit2() == 0) return 0;
  815.         return round($this->getProjectProfit2() / $this->getSoTotalUsd() * 1002PHP_ROUND_HALF_EVEN);
  816.     }
  817.     /**
  818.      * (SO total - Vendor plan total - manhourCost) * 100 / SO total
  819.      * @throws GuzzleException
  820.      */
  821.     public function getProjectGrossmargin3()
  822.     {
  823.         if ($this->getSoTotalUsd() == || $this->getProjectProfit3() == 0) return 0;
  824.         return round($this->getProjectProfit3() / $this->getSoTotalUsd() * 1002PHP_ROUND_HALF_EVEN);
  825.     }
  826.     /**
  827.      * (Total Invoices - vendor plan total - manhourCost) * 100 / total invoices
  828.      * @throws GuzzleException
  829.      */
  830.     public function getProjectGrossmargin4()
  831.     {
  832.         if ($this->getInvoicesTotalUsd() == || $this->getProjectProfit4() == 0) return 0;
  833.         return round($this->getProjectProfit4() / $this->getInvoicesTotalUsd() * 1002PHP_ROUND_HALF_EVEN);
  834.     }
  835.     /**
  836.      * @throws GuzzleException
  837.      */
  838.     public function getInvPercentagePaid()
  839.     {
  840.         if ($this->getInvoicesTotal() > 0) {
  841.             $percentagePaid round($this->getInvoicesTotalPaid() / $this->getInvoicesTotal() * 1002PHP_ROUND_HALF_EVEN);
  842.         } else {
  843.             $percentagePaid 0;
  844.         }
  845.         return $percentagePaid;
  846.     }
  847.     public function getVendorPlannedTotal()
  848.     {
  849.         $vendorPlannedTotal 0;
  850.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  851.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  852.             $vendorPlannedTotal += $vendorQuotationPlanning->getAmountPlanned();
  853.         }
  854.         return $vendorPlannedTotal;
  855.     }
  856.     public function getVendorPlannedTotalUsd()
  857.     {
  858.         global $kernel;
  859.         $currencyService $kernel->getContainer()->get('CurrencyService');
  860.         $vendorPlannedTotalUSD 0;
  861.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  862.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  863.             $dateStr $vendorQuotationPlanning->getCreatedAt()->format('Y-m-d');
  864.             // $usValue = $currencyService->convertAtDate($dateStr, $vendorQuotationPlanning->getCurrency()->getIso(), 'USD', $vendorQuotationPlanning->getAmountPlanned());
  865.             $usValue $currencyService->convertAtDate($dateStr$vendorQuotationPlanning->getCurrency()->getIso(), 'USD'$vendorQuotationPlanning->getAmountPlanned());
  866.             $vendorPlannedTotalUSD += $usValue;
  867.         }
  868.         return round($vendorPlannedTotalUSD2PHP_ROUND_HALF_EVEN);
  869.     }
  870.     public function getVendorPaymentStatus()
  871.     {
  872.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  873.         $vendorPaidCount 0;
  874.         $vendorNotPaidCount 0;
  875.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  876.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  877.             foreach ($vqpInvoices as $vqpInvoice) {
  878.                 $vendorInvoice $vqpInvoice->getVendorInvoice();
  879.                 if ($vendorInvoice->getXeroStatus() === "PAID") {
  880.                     $vendorPaidCount++;
  881.                 } else if ($vendorInvoice->getXeroStatus() === "UNPAID") {
  882.                     $vendorNotPaidCount++;
  883.                 }
  884.             }
  885.         }
  886.         $vendorPaymentStatus "";
  887.         if ($vendorNotPaidCount === && $vendorPaidCount 0) {
  888.             $vendorPaymentStatus "Fully Paid";
  889.         } else if ($vendorPaidCount && $vendorNotPaidCount 0) {
  890.             $vendorPaymentStatus "Partially Paid";
  891.         } else {
  892.             $vendorPaymentStatus "Not Paid";
  893.         }
  894.         return $vendorPaymentStatus;
  895.     }
  896.     public function getVendorPercentagePaid()
  897.     {
  898.         if ($this->getVendorInvoicesTotal() > 0) {
  899.             // $percentagePaid = round($this->getVendorInvoicesTotalPaid() / $this->getVendorInvoicesTotal() * 100, 2);
  900.             $percentagePaid round(($this->getVendorPlannedTotalUsd() - $this->getVendorInvoicesTotalUsd()) / $this->getVendorPlannedTotalUsd() * 1002PHP_ROUND_HALF_EVEN);
  901.         } else {
  902.             $percentagePaid 0;
  903.         }
  904.         return $percentagePaid;
  905.     }
  906.     public function getVendorInvoicesTotal()
  907.     {
  908.         $vendorInvoicesTotal 0;
  909.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  910.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  911.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  912.             foreach ($vqpInvoices as $vqpInvoice) {
  913.                 // here we get amount from allocation, not directly from Vendor Invoice
  914.                 if($vqpInvoice->getVendorInvoice()->getXeroStatus() == 'VOIDED') continue;
  915.                 $vendorInvoicesTotal += $vqpInvoice->getAmount();
  916.                 // $vendorInvoicesTotal += $vqpInvoice->getVendorInvoice()->getSubTotal();
  917.             }
  918.         }
  919.         return $vendorInvoicesTotal;
  920.     }
  921.     public function getVendorInvoicesTotalUsd($endDate null)
  922.     {
  923.         global $kernel;
  924.         $currencyService $kernel->getContainer()->get('CurrencyService');
  925.         $vendorInvoicesTotalUSD 0;
  926.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  927.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  928.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  929.             foreach ($vqpInvoices as $vqpInvoice) {
  930.                 // if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
  931.                 if($vqpInvoice->getVendorInvoice()->getXeroStatus() == 'VOIDED') continue;
  932.                 if ($endDate != null && $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Ymd') > $endDate->format('Ymd')) continue;
  933.                 // $vendorInvoicesTotalUSD += $vqpInvoice->getAmountUsd();
  934.                 $dateStr $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
  935.                 $vendorInvoicesTotalUSD += $currencyService->convertAtDate($dateStr$vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD'$vqpInvoice->getAmount());
  936.             }
  937.         }
  938.         return round($vendorInvoicesTotalUSD2PHP_ROUND_HALF_EVEN);
  939.     }
  940.     public function getVendorInvoicesTotalSgd($endDate null)
  941.     {
  942.         global $kernel;
  943.         $currencyService $kernel->getContainer()->get('CurrencyService');
  944.         $vendorInvoicesTotalUSD 0;
  945.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  946.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  947.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  948.             foreach ($vqpInvoices as $vqpInvoice) {
  949.                 // if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
  950.                 if($vqpInvoice->getVendorInvoice()->getXeroStatus() == 'VOIDED') continue;
  951.                 if ($endDate != null && $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Ymd') > $endDate->format('Ymd')) continue;
  952.                 // $vendorInvoicesTotalUSD += $vqpInvoice->getAmountUsd();
  953.                 $dateStr $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
  954.                 $vendorInvoicesTotalUSD += $currencyService->convertAtDate($dateStr$vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'SGD'$vqpInvoice->getAmount());
  955.             }
  956.         }
  957.         return round($vendorInvoicesTotalUSD2PHP_ROUND_HALF_EVEN);
  958.     }
  959.     public function getVendorInvoices()
  960.     {
  961.         $vendorInvoices = [];
  962.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  963.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  964.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  965.             foreach ($vqpInvoices as $vqpInvoice) {
  966.                 // here we get amount from allocation, not directly from Vendor Invoice
  967.                 array_push($vendorInvoices$vqpInvoice->getVendorInvoice());
  968.                 // $vendorInvoicesTotal += $vqpInvoice->getVendorInvoice()->getSubTotal();
  969.             }
  970.         }
  971.         return $vendorInvoices;
  972.     }
  973.     public function getProjectBudgetRemaining()
  974.     {
  975.         return round($this->getVendorPlannedTotal() - $this->getVendorInvoicesTotal(), 2PHP_ROUND_HALF_EVEN);
  976.     }
  977.     public function getProjectBudgetRemainingUsd()
  978.     {
  979.         return round($this->getVendorPlannedTotalUsd() - $this->getVendorInvoicesTotalUsd(), 2PHP_ROUND_HALF_EVEN);
  980.     }
  981.     public function getVendorInvoicesTotalUsdByMonth($startDate$endDate)
  982.     {
  983.         global $kernel;
  984.         $currencyService $kernel->getContainer()->get('CurrencyService');
  985.         $vendorInvoicesTotalUSD 0;
  986.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  987.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  988.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  989.             foreach ($vqpInvoices as $vqpInvoice) {
  990.                 $vqpInvoiceDate $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Ymd');
  991.                 if ($vqpInvoiceDate >= $startDate->format('Ymd') && $vqpInvoiceDate <= $endDate->format('Ymd')) {
  992.                     if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
  993.                     // $vendorInvoicesTotalUSD += $vqpInvoice->getVendorInvoice()->getSubTotalUsd();
  994.                     $dateStr $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
  995.                     $vendorInvoicesTotalUSD += $currencyService->convertAtDate($dateStr$vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD'$vqpInvoice->getVendorInvoice()->getSubTotal());
  996.                 }
  997.             }
  998.         }
  999.         return round($vendorInvoicesTotalUSD2PHP_ROUND_HALF_EVEN);
  1000.     }
  1001.     public function getVendorInvoicesTotalPaid()
  1002.     {
  1003.         global $kernel;
  1004.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1005.         $vendorInvoicesTotalPaid 0;
  1006.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  1007.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  1008.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  1009.             foreach ($vqpInvoices as $vqpInvoice) {
  1010.                 if ($vqpInvoice->getVendorInvoice()->getXeroStatus() === "PAID") {
  1011.                     $vendorInvoicesTotalPaid += $vqpInvoice->getAmount();
  1012.                     // $vendorInvoicesTotalPaid += $currencyService->convertAtDate($this->createdAt, $vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD', $vqpInvoice->getAmount());
  1013.                 }
  1014.             }
  1015.         }
  1016.         return round($vendorInvoicesTotalPaid2PHP_ROUND_HALF_EVEN);
  1017.     }
  1018.     public function getVendorInvoicesTotalPaidUsd()
  1019.     {
  1020.         global $kernel;
  1021.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1022.         $vendorInvoicesTotalPaid 0;
  1023.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  1024.         foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  1025.             $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  1026.             foreach ($vqpInvoices as $vqpInvoice) {
  1027.                 if ($vqpInvoice->getVendorInvoice()->getXeroStatus() === "PAID") {
  1028.                     // $vendorInvoicesTotalPaid += $vqpInvoice->getAmount();
  1029.                     $dateStr $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
  1030.                     $vendorInvoicesTotalPaid += $currencyService->convertAtDate($dateStr$vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD'$vqpInvoice->getAmount());
  1031.                 }
  1032.             }
  1033.         }
  1034.         return round($vendorInvoicesTotalPaid2PHP_ROUND_HALF_EVEN);
  1035.     }
  1036.     /**
  1037.      * @return Collection<int, ProjectMember>
  1038.      */
  1039.     public function getProjectMembers(): Collection
  1040.     {
  1041.         return $this->projectMembers;
  1042.     }
  1043.     public function getProjectMember($user)
  1044.     {
  1045.         if (is_object($user)) {
  1046.             foreach ($this->projectMembers as $member) {
  1047.                 if ($member->getUser() == $user) return $member;
  1048.             };
  1049.         } else {
  1050.             foreach ($this->projectMembers as $member) {
  1051.                 if ($member->getUser()->getId() == $user) return $member;
  1052.             };
  1053.         }
  1054.         return false;
  1055.     }
  1056.     public function getIsIncluded($user)
  1057.     {
  1058.         foreach ($this->projectMembers as $member) {
  1059.             if ($member->getUser() == $user) return true;
  1060.         };
  1061.         return false;
  1062.     }
  1063.     public function getProjectMembersByDepartmentId($departmentId)
  1064.     {
  1065.         $members = [];
  1066.         foreach ($this->projectMembers as $member) {
  1067.             if (($member->getUser()->getDepartment() !== null) && ($member->getUser()->getDepartment()->getId() == $departmentId)) {
  1068.                 // array_push($members, $member);
  1069.                 $members[] = $member;
  1070.             }
  1071.         }
  1072.         return $members;
  1073.     }
  1074.     public function addProjectMember(ProjectMember $projectMember): self
  1075.     {
  1076.         if (!$this->projectMembers->contains($projectMember)) {
  1077.             $this->projectMembers[] = $projectMember;
  1078.             $projectMember->setProject($this);
  1079.         }
  1080.         return $this;
  1081.     }
  1082.     public function removeProjectMember(ProjectMember $projectMember): self
  1083.     {
  1084.         if ($this->projectMembers->removeElement($projectMember)) {
  1085.             // set the owning side to null (unless already changed)
  1086.             if ($projectMember->getProject() === $this) {
  1087.                 $projectMember->setProject(null);
  1088.             }
  1089.         }
  1090.         return $this;
  1091.     }
  1092.     public function getDeletedAt(): ?\DateTimeImmutable
  1093.     {
  1094.         return $this->deletedAt;
  1095.     }
  1096.     public function setDeletedAt(?\DateTimeImmutable $deletedAt): self
  1097.     {
  1098.         $this->deletedAt $deletedAt;
  1099.         return $this;
  1100.     }
  1101.     /**
  1102.      * @return Collection<int, Department>
  1103.      */
  1104.     public function getDepartment(): Collection
  1105.     {
  1106.         return $this->department;
  1107.     }
  1108.     public function addDepartment(Department $department): self
  1109.     {
  1110.         if (!$this->department->contains($department)) {
  1111.             $this->department[] = $department;
  1112.         }
  1113.         return $this;
  1114.     }
  1115.     public function removeDepartment(Department $department): self
  1116.     {
  1117.         $this->department->removeElement($department);
  1118.         return $this;
  1119.     }
  1120.     function departmentNames()
  1121.     {
  1122.         $departments = [];
  1123.         foreach ($this->getDepartment() as $department) {
  1124.             if (!in_array($department->getName(), $departments))
  1125.                 array_push($departments$department->getName());
  1126.         }
  1127.         return implode(', '$departments);
  1128.     }
  1129.     public function getRetainer(): ?bool
  1130.     {
  1131.         return $this->retainer;
  1132.     }
  1133.     public function setRetainer(bool $retainer): self
  1134.     {
  1135.         $this->retainer $retainer;
  1136.         return $this;
  1137.     }
  1138.     public function getLead(): ?int
  1139.     {
  1140.         // return $this->lead;
  1141.         return $this->leadStatus $this->leadStatus->getLead() : $this->lead;
  1142.     }
  1143.     public function setLead(?int $lead): self
  1144.     {
  1145.         global $kernel;
  1146.         $projectService $kernel->getContainer()->get('ProjectService');
  1147.         $projectLeadStatus $projectService->getProjectLeadStatus($lead);
  1148.         $this->setProbability($projectLeadStatus $projectLeadStatus->getProbability() : $this->probability);
  1149.         $this->setLeadStatus($projectLeadStatus);
  1150.         $this->lead $lead;
  1151.         return $this;
  1152.     }
  1153.     public function getType(): ?string
  1154.     {
  1155.         return $this->type;
  1156.     }
  1157.     public function setType(string $type): self
  1158.     {
  1159.         $this->type $type;
  1160.         return $this;
  1161.     }
  1162.     public function getLeadDate(): ?\DateTimeInterface
  1163.     {
  1164.         return $this->leadDate;
  1165.     }
  1166.     public function setLeadDate(?\DateTimeInterface $leadDate): self
  1167.     {
  1168.         $this->leadDate $leadDate;
  1169.         return $this;
  1170.     }
  1171.     public function getProposalDate(): ?\DateTimeInterface
  1172.     {
  1173.         return $this->proposalDate;
  1174.     }
  1175.     public function setProposalDate(?\DateTimeInterface $proposalDate): self
  1176.     {
  1177.         $this->proposalDate $proposalDate;
  1178.         return $this;
  1179.     }
  1180.     public function leadStatusText($id null)
  1181.     {
  1182.         return $this->leadStatus->getName() || 'Unknown';
  1183.     }
  1184.     public function getPlanURL(): ?string
  1185.     {
  1186.         return $this->planURL;
  1187.     }
  1188.     public function setPlanURL(?string $planURL): self
  1189.     {
  1190.         $this->planURL $planURL;
  1191.         return $this;
  1192.     }
  1193.     public function getEstimatedProfit(): ?float
  1194.     {
  1195.         return $this->plannedRevenue $this->estimatedVendorCost;
  1196.         // return $this->estimatedProfit;
  1197.     }
  1198.     public function setEstimatedProfit(?float $estimatedProfit): self
  1199.     {
  1200.         $this->estimatedProfit $estimatedProfit;
  1201.         return $this;
  1202.     }
  1203.     public function getEstimatedProfitUsd()
  1204.     {
  1205.         // if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->getEstimatedProfit();
  1206.         // global $kernel;
  1207.         // $currencyService = $kernel->getContainer()->get('CurrencyService');
  1208.         // $dateStr = $this->createdAt->format('Y-m-d');
  1209.         // return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->getEstimatedProfit());
  1210.         return round($this->plannedRevenueUsd $this->estimatedVendorCostUsd2PHP_ROUND_HALF_EVEN);
  1211.     }
  1212.     public function actualStatus()
  1213.     {
  1214.         if ($this->type == "LEAD") {
  1215.             return $this->lead ' - ' $this->getLeadStatus()->getName();
  1216.         } else {
  1217.             return $this->status;
  1218.         }
  1219.     }
  1220.     public function getEstimatedVendorCost(): ?float
  1221.     {
  1222.         return $this->estimatedVendorCost;
  1223.     }
  1224.     public function setEstimatedVendorCost(float $estimatedVendorCost): self
  1225.     {
  1226.         $this->estimatedVendorCost $estimatedVendorCost;
  1227.         $this->estimatedVendorCostUsd $this->getEstimatedVendorCostToUsd($estimatedVendorCost);
  1228.         return $this;
  1229.     }
  1230.     /**
  1231.      * @return Collection<int, ProjectSalesOrder>
  1232.      */
  1233.     public function getProjectSalesOrders(): Collection
  1234.     {
  1235.         return $this->projectSalesOrders;
  1236.     }
  1237.     public function addProjectSalesOrder(ProjectSalesOrder $projectSalesOrder): self
  1238.     {
  1239.         if (!$this->projectSalesOrders->contains($projectSalesOrder)) {
  1240.             $this->projectSalesOrders[] = $projectSalesOrder;
  1241.             $projectSalesOrder->setProject($this);
  1242.         }
  1243.         return $this;
  1244.     }
  1245.     public function removeProjectSalesOrder(ProjectSalesOrder $projectSalesOrder): self
  1246.     {
  1247.         if ($this->projectSalesOrders->removeElement($projectSalesOrder)) {
  1248.             // set the owning side to null (unless already changed)
  1249.             if ($projectSalesOrder->getProject() === $this) {
  1250.                 $projectSalesOrder->setProject(null);
  1251.             }
  1252.         }
  1253.         return $this;
  1254.     }
  1255.     public function getProjectSalesOrderTotalAmountUsed(): ?float
  1256.     {
  1257.         $amountUsed 0;
  1258.         foreach ($this->projectSalesOrders as $projectSalesOrder) {
  1259.             $amountUsed += $projectSalesOrder->getAmount();
  1260.         }
  1261.         return $amountUsed;
  1262.     }
  1263.     public function getProjectSalesOrderTotalAmountUsedUsd(): ?float
  1264.     {
  1265.         global $kernel;
  1266.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1267.         $amount 0;
  1268.         // return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD',  $this->getProjectSalesOrderTotalAmountUsed());
  1269.         foreach ($this->projectSalesOrders as $projectSalesOrder) {
  1270.             $amount += $currencyService->convertAtDate($this->createdAt$projectSalesOrder->getSalesOrder()->getCurrency()->getIso(), 'USD',  $projectSalesOrder->getAmount());
  1271.         }
  1272.         return round($amount2PHP_ROUND_HALF_EVEN);
  1273.     }
  1274.     /**
  1275.      * @return Collection|ProjectAllocatedHours[]
  1276.      */
  1277.     public function getProjectAllocatedHours(): Collection
  1278.     {
  1279.         return $this->projectAllocatedHours;
  1280.     }
  1281.     public function addProjectAllocatedHour(ProjectAllocatedHours $projectAllocatedHour): self
  1282.     {
  1283.         if (!$this->projectAllocatedHours->contains($projectAllocatedHour)) {
  1284.             $this->projectAllocatedHours[] = $projectAllocatedHour;
  1285.             $projectAllocatedHour->setProject($this);
  1286.         }
  1287.         return $this;
  1288.     }
  1289.     public function removeProjectAllocatedHour(ProjectAllocatedHours $projectAllocatedHour): self
  1290.     {
  1291.         if ($this->projectAllocatedHours->removeElement($projectAllocatedHour)) {
  1292.             // set the owning side to null (unless already changed)
  1293.             if ($projectAllocatedHour->getProject() === $this) {
  1294.                 $projectAllocatedHour->setProject(null);
  1295.             }
  1296.         }
  1297.         return $this;
  1298.     }
  1299.     public function getLeadSource(): ?string
  1300.     {
  1301.         return $this->leadSource;
  1302.     }
  1303.     public function setLeadSource(?string $leadSource): self
  1304.     {
  1305.         $this->leadSource $leadSource;
  1306.         return $this;
  1307.     }
  1308.     public function getLeadSourceFormatted(): ?string
  1309.     {
  1310.         if ($this->leadSource == "client") {
  1311.             return "Existing client";
  1312.         } else if ($this->leadSource == "other") {
  1313.             return "Other";
  1314.         } else {
  1315.             return $this->leadSource;
  1316.         }
  1317.     }
  1318.     public function getLastReminder(): ?\DateTimeImmutable
  1319.     {
  1320.         return $this->lastReminder;
  1321.     }
  1322.     public function setLastReminder(?\DateTimeImmutable $lastReminder): self
  1323.     {
  1324.         $this->lastReminder $lastReminder;
  1325.         return $this;
  1326.     }
  1327.     public function getGeneratedId(): ?string
  1328.     {
  1329.         return $this->generatedId;
  1330.     }
  1331.     public function setGeneratedId(?string $generatedId): self
  1332.     {
  1333.         $this->generatedId $generatedId;
  1334.         return $this;
  1335.     }
  1336.     public function getLeadFailDate(): ?\DateTimeImmutable
  1337.     {
  1338.         return $this->leadFailDate;
  1339.     }
  1340.     public function setLeadFailDate(?\DateTimeImmutable $leadFailDate): self
  1341.     {
  1342.         $this->leadFailDate $leadFailDate;
  1343.         return $this;
  1344.     }
  1345.     public function getLeadFailNote(): ?string
  1346.     {
  1347.         return $this->leadFailNote;
  1348.     }
  1349.     public function setLeadFailNote(?string $leadFailNote): self
  1350.     {
  1351.         $this->leadFailNote $leadFailNote;
  1352.         return $this;
  1353.     }
  1354.     public function getLeadFailRemindDate(): ?\DateTimeImmutable
  1355.     {
  1356.         return $this->leadFailRemindDate;
  1357.     }
  1358.     public function setLeadFailRemindDate(?\DateTimeImmutable $leadFailRemindDate): self
  1359.     {
  1360.         $this->leadFailRemindDate $leadFailRemindDate;
  1361.         return $this;
  1362.     }
  1363.     public function getClientPersonInCharge(): ?ClientContact
  1364.     {
  1365.         return $this->clientPersonInCharge;
  1366.     }
  1367.     public function setClientPersonInCharge(?ClientContact $clientPersonInCharge): self
  1368.     {
  1369.         $this->clientPersonInCharge $clientPersonInCharge;
  1370.         return $this;
  1371.     }
  1372.     /**
  1373.      * @return Collection|SalesOrderPurchaseOrder[]
  1374.      */
  1375.     public function getSalesOrderPurchaseOrders(): Collection
  1376.     {
  1377.         return $this->salesOrderPurchaseOrders;
  1378.     }
  1379.     public function addSalesOrderPurchaseOrder(SalesOrderPurchaseOrder $salesOrderPurchaseOrder): self
  1380.     {
  1381.         if (!$this->salesOrderPurchaseOrders->contains($salesOrderPurchaseOrder)) {
  1382.             $this->salesOrderPurchaseOrders[] = $salesOrderPurchaseOrder;
  1383.             $salesOrderPurchaseOrder->setProject($this);
  1384.         }
  1385.         return $this;
  1386.     }
  1387.     public function removeSalesOrderPurchaseOrder(SalesOrderPurchaseOrder $salesOrderPurchaseOrder): self
  1388.     {
  1389.         if ($this->salesOrderPurchaseOrders->removeElement($salesOrderPurchaseOrder)) {
  1390.             // set the owning side to null (unless already changed)
  1391.             if ($salesOrderPurchaseOrder->getProject() === $this) {
  1392.                 $salesOrderPurchaseOrder->setProject(null);
  1393.             }
  1394.         }
  1395.         return $this;
  1396.     }
  1397.     public function getPlannedRevenueUsd(): ?float
  1398.     {
  1399.         return $this->plannedRevenueUsd// already converted properly 
  1400.     }
  1401.     public function setPlannedRevenueUsd(?float $plannedRevenueUsd): self
  1402.     {
  1403.         $this->plannedRevenueUsd $plannedRevenueUsd;
  1404.         return $this;
  1405.     }
  1406.     public function getPlannedRevenueToUsd(): ?float
  1407.     {
  1408.         if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->plannedRevenue ?? 0;
  1409.         global $kernel;
  1410.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1411.         // $dateStr = $this->createdAt ? $this->createdAt->format('Y-m-d') : date('Y-m-d');
  1412.         // return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->plannedRevenue) ?? 0;
  1413.         $dateStr $this->createdAt ?? date('Y-m-d');
  1414.         $amount $currencyService->convertAtDate($dateStr$this->currency->getIso(), 'USD'$this->plannedRevenue) ?? 0;
  1415.         return round($amount2PHP_ROUND_HALF_EVEN);
  1416.     }
  1417.     public function getNoEstimatedVendorCost(): ?bool
  1418.     {
  1419.         return $this->noEstimatedVendorCost;
  1420.     }
  1421.     public function setNoEstimatedVendorCost(bool $noEstimatedVendorCost): self
  1422.     {
  1423.         $this->noEstimatedVendorCost $noEstimatedVendorCost;
  1424.         return $this;
  1425.     }
  1426.     public function getEstimatedVendorCostUsd(): ?float
  1427.     {
  1428.         return $this->estimatedVendorCostUsd// already converted properly
  1429.     }
  1430.     public function setEstimatedVendorCostUsd(float $estimatedVendorCostUsd): self
  1431.     {
  1432.         $this->estimatedVendorCostUsd $estimatedVendorCostUsd;
  1433.         return $this;
  1434.     }
  1435.     public function getEstimatedVendorCostToUsd(): ?float
  1436.     {
  1437.         if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->estimatedVendorCost ?? 0;
  1438.         global $kernel;
  1439.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1440.         // $dateStr = $this->startDate->format('Y-m-d');
  1441.         // $dateStr = !empty($this->startDate) ? $this->startDate->format('Y-m-d') : date('Y-m-d');
  1442.         // return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->estimatedVendorCost) ?? 0;
  1443.         $dateStr $this->createdAt ?? date('Y-m-d');
  1444.         $amount $currencyService->convertAtDate($dateStr$this->currency->getIso(), 'USD'$this->estimatedVendorCost) ?? 0;
  1445.         return round($amount2PHP_ROUND_HALF_EVEN);
  1446.     }
  1447.     public function getProbability(): ?int
  1448.     {
  1449.         return $this->probability;
  1450.     }
  1451.     public function setProbability(?int $probability): self
  1452.     {
  1453.         $this->probability $probability;
  1454.         return $this;
  1455.     }
  1456.     public function getProbabilityRate()
  1457.     {
  1458.         $probability  $this->probability ?? 0;
  1459.         if ($probability == 0) {
  1460.             // switch ($this->lead) {
  1461.             //     case 8:
  1462.             //         $probability = 100;
  1463.             //         break;
  1464.             //     case 9:
  1465.             //         $probability = 0;
  1466.             //         break;
  1467.             //     default:
  1468.             //         $probability = 10;
  1469.             //         break;
  1470.             // }
  1471.             $probability $this->leadStatus->getProbability();
  1472.         }
  1473.         return $probability;
  1474.     }
  1475.     public function getProbabilityText()
  1476.     {
  1477.         // $probability  = $this->probability;
  1478.         // switch ($probability) {
  1479.         //     case 100:
  1480.         //         return "100%";
  1481.         //         break;
  1482.         //     case 90:
  1483.         //         return "Above 80%";
  1484.         //         break;
  1485.         //     case 50:
  1486.         //         return "Between 50% to 80%";
  1487.         //         break;
  1488.         //     case 10:
  1489.         //         return "Below 50%";
  1490.         //         break;
  1491.         //     case 0:
  1492.         //         return "0%";
  1493.         //         break;
  1494.         //     default:
  1495.         //         return "-";
  1496.         //         break;
  1497.         // }
  1498.         return $this->getProbability() ?  $this->getProbability() . '%' '-';
  1499.     }
  1500.     public function getNoPresentation(): ?bool
  1501.     {
  1502.         return $this->noPresentation;
  1503.     }
  1504.     public function setNoPresentation(bool $noPresentation): self
  1505.     {
  1506.         $this->noPresentation $noPresentation;
  1507.         return $this;
  1508.     }
  1509.     public function getPresentationDate(): ?\DateTimeInterface
  1510.     {
  1511.         return $this->presentationDate;
  1512.     }
  1513.     public function setPresentationDate(?\DateTimeInterface $presentationDate): self
  1514.     {
  1515.         $this->presentationDate $presentationDate;
  1516.         return $this;
  1517.     }
  1518.     /**
  1519.      * @return Collection|ProjectClassification[]
  1520.      */
  1521.     public function getProjectTypes(): Collection
  1522.     {
  1523.         return $this->projectTypes;
  1524.     }
  1525.     public function addProjectType(ProjectClassification $projectType): self
  1526.     {
  1527.         if (!$this->projectTypes->contains($projectType)) {
  1528.             $this->projectTypes[] = $projectType;
  1529.         }
  1530.         return $this;
  1531.     }
  1532.     public function removeProjectType(ProjectClassification $projectType): self
  1533.     {
  1534.         $this->projectTypes->removeElement($projectType);
  1535.         return $this;
  1536.     }
  1537.     /**
  1538.      * @return Collection|IndustryClassification[]
  1539.      */
  1540.     public function getProjectIndustries(): Collection
  1541.     {
  1542.         return $this->projectIndustries;
  1543.     }
  1544.     public function addProjectIndustry(IndustryClassification $projectIndustry): self
  1545.     {
  1546.         if (!$this->projectIndustries->contains($projectIndustry)) {
  1547.             $this->projectIndustries[] = $projectIndustry;
  1548.         }
  1549.         return $this;
  1550.     }
  1551.     public function removeProjectIndustry(IndustryClassification $projectIndustry): self
  1552.     {
  1553.         $this->projectIndustries->removeElement($projectIndustry);
  1554.         return $this;
  1555.     }
  1556.     public function removeAllProjectIndustries()
  1557.     {
  1558.         $this->projectIndustries->clear();
  1559.     }
  1560.     public function getProposalFollowUpDate(): ?\DateTimeInterface
  1561.     {
  1562.         return $this->proposalFollowUpDate;
  1563.     }
  1564.     public function setProposalFollowUpDate(?\DateTimeInterface $proposalFollowUpDate): self
  1565.     {
  1566.         $this->proposalFollowUpDate $proposalFollowUpDate;
  1567.         return $this;
  1568.     }
  1569.     public function getLeadStatus(): ?ProjectLeadStatus
  1570.     {
  1571.         return $this->leadStatus;
  1572.     }
  1573.     public function setLeadStatus(?ProjectLeadStatus $leadStatus): self
  1574.     {
  1575.         $this->leadStatus $leadStatus;
  1576.         return $this;
  1577.     }
  1578.     /**
  1579.      * @return Collection|RevenuePlanning[]
  1580.      */
  1581.     public function getRevenuePlannings(): Collection
  1582.     {
  1583.         // return $this->revenuePlannings;
  1584.         $revenuePlannings $this->revenuePlannings->toArray();
  1585.         usort($revenuePlannings, function ($a$b) {
  1586.             $aDate $a->getYear() . $a->getMonth();
  1587.             $bDate $b->getYear() . $b->getMonth();
  1588.             return $aDate <=> $bDate;
  1589.         });
  1590.         return new ArrayCollection($revenuePlannings);
  1591.     }
  1592.     /**
  1593.      * Calculate and return the total revenue planning amount.
  1594.      *
  1595.      * @return float
  1596.      */
  1597.     public function getTotalRevenuePlanning(): float
  1598.     {
  1599.         $totalAmount 0;
  1600.         foreach ($this->revenuePlannings as $revenuePlanning) {
  1601.             $totalAmount += $revenuePlanning->getAmount();
  1602.         }
  1603.         return $totalAmount;
  1604.     }
  1605.     /**
  1606.      * Calculate and return the total revenue planning amount in USD.
  1607.      *
  1608.      * @return float
  1609.      */
  1610.     public function getTotalRevenuePlanningUsd(): float
  1611.     {
  1612.         global $kernel;
  1613.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1614.         $totalAmountUsd 0;
  1615.         foreach ($this->revenuePlannings as $revenuePlanning) {
  1616.             // $totalAmountUsd += $revenuePlanning->getAmountUsd();
  1617.             $totalAmountUsd += $currencyService->convertAtDate($this->createdAt$this->currency->getIso(), 'USD'$revenuePlanning->getAmount());
  1618.         }
  1619.         return round($totalAmountUsd2PHP_ROUND_HALF_EVEN);
  1620.     }
  1621.     public function getTotalRevenuePlanningDifference(): float
  1622.     {
  1623.         return abs($this->getTotalRevenuePlanning() - $this->getEstimatedProfit()) < 0.00001 $this->getTotalRevenuePlanning() - $this->getEstimatedProfit();
  1624.     }
  1625.     public function getTotalRevenuePlanningDifferenceUsd(): float
  1626.     {
  1627.         return abs($this->getTotalRevenuePlanningUsd() - $this->getEstimatedProfitUsd()) < 0.00001 $this->getTotalRevenuePlanningUsd() - $this->getEstimatedProfitUsd();
  1628.     }
  1629.     public function addRevenuePlanning(RevenuePlanning $revenuePlanning): self
  1630.     {
  1631.         if (!$this->revenuePlannings->contains($revenuePlanning)) {
  1632.             $this->revenuePlannings[] = $revenuePlanning;
  1633.             $revenuePlanning->setProject($this);
  1634.         }
  1635.         return $this;
  1636.     }
  1637.     public function removeRevenuePlanning(RevenuePlanning $revenuePlanning): self
  1638.     {
  1639.         if ($this->revenuePlannings->removeElement($revenuePlanning)) {
  1640.             // set the owning side to null (unless already changed)
  1641.             if ($revenuePlanning->getProject() === $this) {
  1642.                 $revenuePlanning->setProject(null);
  1643.             }
  1644.         }
  1645.         return $this;
  1646.     }
  1647.     public function getTotalVendorCost()
  1648.     {
  1649.         $total 0;
  1650.         $ratio 1;
  1651.         $projectSalesOrders $this->getProjectSalesOrders();
  1652.         foreach ($projectSalesOrders as $pso) {
  1653.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1654.             foreach ($soInvoices as $soInvoice) {
  1655.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  1656.                 // if($pso->getProject() == $this){
  1657.                 //     $ratio = $useRatio ? $pso->getAmount() / $soInvoice->getSalesOrder()->getSubTotal() : 1;
  1658.                 // }
  1659.                 // $ratio = $useRatio ? $soInvoice->getAmount() / $soInvoice->getSalesOrder()->getSubTotal() : 1;
  1660.                 $total += $soInvoice->getInvoice()->getVendorCost($this);
  1661.             }
  1662.         }
  1663.         return $total;
  1664.     }
  1665.     public function getInvVendorCostByFinancialYear($year null$isAllocated false)
  1666.     {
  1667.         $total 0;
  1668.         if ($year) {
  1669.             $start date('Y-m-d'strtotime('first day of November ' . ($year 1)));
  1670.             $end date('Y-m-d'strtotime('last day of October ' $year));
  1671.         }
  1672.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  1673.         if($vendorQuotationPlannings){
  1674.             foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  1675.                 $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  1676.                 foreach ($vqpInvoices as $vqpInvoice) {
  1677.                     $invoice $vqpInvoice->getVendorInvoice();
  1678.                     if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
  1679.                     $invoiceDate $invoice->getInvoiceDate()->format('Y-m-d');
  1680.                     if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
  1681.                         $total += $isAllocated $vqpInvoice->getAmount() : $invoice->getSubTotal();
  1682.                     }
  1683.                 }
  1684.             }
  1685.         }
  1686.         /*
  1687.         foreach ($projectSalesOrders as $pso) {
  1688.             $soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1689.             foreach ($soInvoices as $soInvoice) {
  1690.                 $invoice = $soInvoice->getInvoice();
  1691.                 if ($invoice->getXeroStatus() == 'VOIDED') continue;
  1692.                 $invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
  1693.                 if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
  1694.                     $total += $invoice->getSubTotal();
  1695.                 }
  1696.             }
  1697.         }
  1698.         */
  1699.         return $total;
  1700.     }
  1701.     public function getInvoices()
  1702.     {
  1703.         $invoices = [];
  1704.         $projectSalesOrders $this->getProjectSalesOrders();
  1705.         if ($projectSalesOrders) {
  1706.             foreach ($projectSalesOrders as $pso) {
  1707.                 $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1708.                 foreach ($soInvoices as $soInvoice) {
  1709.                     $invoice $soInvoice->getInvoice();
  1710.                     array_push($invoices$invoice);
  1711.                 }
  1712.             }
  1713.         }
  1714.         return $invoices;
  1715.     }
  1716.     public function getTotalVendorCostUsd()
  1717.     {
  1718.         global $kernel;
  1719.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1720.         $total 0;
  1721.         $projectSalesOrders $this->getProjectSalesOrders();
  1722.         foreach ($projectSalesOrders as $pso) {
  1723.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1724.             foreach ($soInvoices as $soInvoice) {
  1725.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  1726.                 // $total += $soInvoice->getInvoice()->getVendorCostUsd($this);
  1727.                 $total += $currencyService->convertAtDate($this->createdAt$soInvoice->getInvoice()->getCurrency()->getIso(), 'USD'$soInvoice->getInvoice()->getVendorCost($this));
  1728.             }
  1729.         }
  1730.         return round($total2PHP_ROUND_HALF_EVEN);
  1731.     }
  1732.     public function getInvVendorCostByFinancialYearSgd($year null$isAllocated false)
  1733.     {
  1734.         global $kernel;
  1735.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1736.         $total 0;
  1737.         if ($year) {
  1738.             $start date('Y-m-d'strtotime('first day of November ' . ($year 1)));
  1739.             $end date('Y-m-d'strtotime('last day of October ' $year));
  1740.         }
  1741.         // foreach ($projectSalesOrders as $pso) {
  1742.         //     $soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1743.         //     foreach ($soInvoices as $soInvoice) {
  1744.         //         $invoice = $soInvoice->getInvoice();
  1745.         //         if ($invoice->getXeroStatus() == 'VOIDED') continue;
  1746.         //         $invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
  1747.         //         if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
  1748.         //             $vendorCost = $invoice->getSubTotal();
  1749.         //             $currencyIso = $invoice->getCurrency()->getIso();
  1750.         //             $total += $currencyService->convertAtDate($this->createdAt, $currencyIso, 'SGD', $vendorCost);
  1751.         //         }
  1752.         //     }
  1753.         // }
  1754.         $vendorQuotationPlannings $this->getVendorQuotationPlannings();
  1755.         if($vendorQuotationPlannings){
  1756.             foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
  1757.                 $vqpInvoices $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
  1758.                 foreach ($vqpInvoices as $vqpInvoice) {
  1759.                     $invoice $vqpInvoice->getVendorInvoice();
  1760.                     if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
  1761.                     $invoiceDate $invoice->getInvoiceDate()->format('Y-m-d');
  1762.                     if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
  1763.                         $vendorCost $invoice->getSubTotal();
  1764.                         if($isAllocated$vendorCost $vqpInvoice->getAmount();
  1765.                         $currencyIso $invoice->getCurrency()->getIso();
  1766.                         $total += $currencyService->convertAtDate($this->createdAt$currencyIso'SGD'$vendorCost);
  1767.                     }
  1768.                 }
  1769.             }
  1770.         }
  1771.         return round($total2PHP_ROUND_HALF_EVEN);
  1772.     }
  1773.     public function getTotalRevenue()
  1774.     {
  1775.         $total 0;
  1776.         $projectSalesOrders $this->getProjectSalesOrders();
  1777.         foreach ($projectSalesOrders as $pso) {
  1778.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1779.             foreach ($soInvoices as $soInvoice) {
  1780.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  1781.                 $total += $soInvoice->getInvoice()->getRevenue($this);
  1782.             }
  1783.         }
  1784.         return $total;
  1785.     }
  1786.     public function getInvRevenueByFinancialYear($year null)
  1787.     {
  1788.         $total 0;
  1789.         $start $end null;
  1790.         if ($year) {
  1791.             $start date('Y-m-d'strtotime('first day of November ' . ($year 1)));
  1792.             $end date('Y-m-d'strtotime('last day of October ' $year));
  1793.         }
  1794.         foreach ($this->getProjectSalesOrders() as $pso) {
  1795.             foreach ($pso->getSalesOrder()->getSalesOrderInvoices($this->id) as $soInvoice) {
  1796.                 $invoice $soInvoice->getInvoice();
  1797.                 if ($invoice->getXeroStatus() == 'VOIDED') continue;
  1798.                 $invoiceDate $invoice->getInvoiceDate()->format('Y-m-d');
  1799.                 if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
  1800.                     $total += $soInvoice->getAmount();
  1801.                     // $total += $invoice->getSubTotal();
  1802.                 }
  1803.             }
  1804.         }
  1805.         return $total;
  1806.     }
  1807.     public function getInvRevenueByFinancialYearSgd($year null$isAllocated false)
  1808.     {
  1809.         global $kernel;
  1810.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1811.         $total 0;
  1812.         $projectSalesOrders $this->getProjectSalesOrders();
  1813.         // Determine the start and end dates if a year is provided  
  1814.         if ($year) {
  1815.             $start date('Y-m-d'strtotime('first day of November ' . ($year 1)));
  1816.             $end date('Y-m-d'strtotime('last day of October ' $year));
  1817.         }
  1818.         foreach ($projectSalesOrders as $pso) {
  1819.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1820.             foreach ($soInvoices as $soInvoice) {
  1821.                 $invoice $soInvoice->getInvoice();
  1822.                 if ($invoice->getXeroStatus() == 'VOIDED') continue;
  1823.                 $invoiceDate $invoice->getInvoiceDate()->format('Y-m-d');
  1824.                 if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
  1825.                     $revenue $invoice->getSubTotal();
  1826.                     if($isAllocated$revenue $soInvoice->getAmount();
  1827.                     $currencyIso $invoice->getCurrency()->getIso();
  1828.                     $total += $currencyService->convertAtDate($this->createdAt$currencyIso'SGD'$revenue);
  1829.                 }
  1830.             }
  1831.         }
  1832.         return round($total2PHP_ROUND_HALF_EVEN);
  1833.     }
  1834.     public function getTotalRevenueUsd()
  1835.     {
  1836.         global $kernel;
  1837.         $currencyService $kernel->getContainer()->get('CurrencyService');
  1838.         $total 0;
  1839.         $projectSalesOrders $this->getProjectSalesOrders();
  1840.         foreach ($projectSalesOrders as $pso) {
  1841.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
  1842.             foreach ($soInvoices as $soInvoice) {
  1843.                 if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
  1844.                 // $total += $soInvoice->getInvoice()->getRevenueUsd($this);
  1845.                 $total += $currencyService->convertAtDate($this->createdAt$soInvoice->getInvoice()->getCurrency()->getIso(), 'USD'$soInvoice->getInvoice()->getRevenue($this));
  1846.             }
  1847.         }
  1848.         return round($total2PHP_ROUND_HALF_EVEN);
  1849.     }
  1850.     public function getAllocatedCreditNotesTotal($status null): ?float
  1851.     {
  1852.         $total 0;
  1853.         $projectSalesOrders $this->getProjectSalesOrders();
  1854.         foreach ($projectSalesOrders as $pso) {
  1855.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  1856.             foreach ($soInvoices as $soInvoice) {
  1857.                 if ($soInvoice->getProject() !== $this) continue;
  1858.                 if ($status != null && $soInvoice->getInvoice()->getXeroStatus() != $status || !$soInvoice->getInvoice()->getXeroCreditNoteAllocation()) continue;
  1859.                 $total += $soInvoice->getInvoice()->getAllocatedCreditNote($this);
  1860.             }
  1861.         }
  1862.         return $total;
  1863.     }
  1864.     public function getAllocatedCreditNotesTotalUsd($status null): ?float
  1865.     {
  1866.         $total 0;
  1867.         $projectSalesOrders $this->getProjectSalesOrders();
  1868.         foreach ($projectSalesOrders as $pso) {
  1869.             $soInvoices $pso->getSalesOrder()->getSalesOrderInvoices();
  1870.             foreach ($soInvoices as $soInvoice) {
  1871.                 if ($soInvoice->getProject() !== $this) continue;
  1872.                 if ($status != null && $soInvoice->getInvoice()->getXeroStatus() != $status || !$soInvoice->getInvoice()->getXeroCreditNoteAllocation()) continue;
  1873.                 $total += $soInvoice->getInvoice()->getAllocatedCreditNoteUsd($this);
  1874.             }
  1875.         }
  1876.         return round($total2PHP_ROUND_HALF_EVEN);
  1877.     }
  1878.     public function getLeadLostReason($withNote true)
  1879.     {
  1880.         $text '';
  1881.         if ($this->projectLostFilter) {
  1882.             $mainReason $this->projectLostFilter->getMainReason() ? $this->projectLostFilter->getMainReason()->getTitle() : null;
  1883.             $subReason $this->projectLostFilter->getSubReason() ? $this->projectLostFilter->getSubReason()->getTitle() : null;
  1884.             $subReason $subReason ' - ' $subReason null;
  1885.             $text $mainReason $subReason;
  1886.         } else {
  1887.             if ($this->leadFail) {
  1888.                 $reasonTitle $this->leadFail $this->leadFail->getTitle() : null;
  1889.                 $text $reasonTitle;
  1890.             }
  1891.         }
  1892.         if ($withNote && $this->leadFailNote$text $text ': ' $this->leadFailNote;
  1893.         return $text;
  1894.     }
  1895.     public function getLeadFail(): ?ProjectLostReason
  1896.     {
  1897.         return $this->leadFail;
  1898.     }
  1899.     public function setLeadFail(?ProjectLostReason $leadFail): self
  1900.     {
  1901.         $this->leadFail $leadFail;
  1902.         return $this;
  1903.     }
  1904.     public function getProjectDeliverable(): ?ProjectDeliverable
  1905.     {
  1906.         return $this->projectDeliverable;
  1907.     }
  1908.     public function checkProjectDeliverable()
  1909.     {
  1910.         if (!empty($this->projectDeliverable)) {
  1911.             if (
  1912.                 !empty($this->projectDeliverable->getThumbnails()) ||
  1913.                 !empty($this->projectDeliverable->getProjectDeliverableFiles()->toArray())
  1914.             ) {
  1915.                 return true;
  1916.             }
  1917.         }
  1918.         return false;
  1919.     }
  1920.     public function setProjectDeliverable(?ProjectDeliverable $projectDeliverable): self
  1921.     {
  1922.         // unset the owning side of the relation if necessary
  1923.         if ($projectDeliverable === null && $this->projectDeliverable !== null) {
  1924.             $this->projectDeliverable->setProject(null);
  1925.         }
  1926.         // set the owning side of the relation if necessary
  1927.         if ($projectDeliverable !== null && $projectDeliverable->getProject() !== $this) {
  1928.             $projectDeliverable->setProject($this);
  1929.         }
  1930.         $this->projectDeliverable $projectDeliverable;
  1931.         return $this;
  1932.     }
  1933.     public function getFeedbackScore()
  1934.     {
  1935.         $scoreCount 0;
  1936.         $feedbackCount 0;
  1937.         $total 0;
  1938.         foreach ($this->clientFeedback as $feedback) {
  1939.             // if($feedback->getClientFeedbackForm()->getClientFeedbackTemplate() == $this->clientFeedbackTemplate ){
  1940.             if ($feedback->getRating() && $feedback->getDeletedAt() == NULL) {
  1941.                 $scoreCount += $feedback->getRating() ?: 0;
  1942.                 $feedbackCount++;
  1943.             }
  1944.             // }
  1945.         }
  1946.         if ($feedbackCount 0) {
  1947.             $total number_format($scoreCount $feedbackCount1);
  1948.         }
  1949.         return $total;
  1950.     }
  1951.     /**
  1952.      * @return Collection<int, ClientFeedback>
  1953.      */
  1954.     public function getClientFeedback(): Collection
  1955.     {
  1956.         return $this->clientFeedback;
  1957.     }
  1958.     public function getActiveClientFeedback($feedbackTemplate null)
  1959.     {
  1960.         $clientFeedbacks = [];
  1961.         foreach ($this->clientFeedback as $clientFeedback) {
  1962.             if (!$clientFeedback->isDeleted()) {
  1963.                 if ($feedbackTemplate === null || $clientFeedback->getFeedbackTemplate() === $feedbackTemplate) {
  1964.                     $clientFeedbacks[] = $clientFeedback;
  1965.                 }
  1966.                 // $clientFeedbacks[] = $clientFeedback;
  1967.             }
  1968.         }
  1969.         usort($clientFeedbacks, function ($a$b) {
  1970.             return $a->getCustomOrder() - $b->getCustomOrder();
  1971.         });
  1972.         return $clientFeedbacks;
  1973.     }
  1974.     public function addClientFeedback(ClientFeedback $clientFeedback): self
  1975.     {
  1976.         if (!$this->clientFeedback->contains($clientFeedback)) {
  1977.             $this->clientFeedback->add($clientFeedback);
  1978.             $clientFeedback->setProject($this);
  1979.         }
  1980.         return $this;
  1981.     }
  1982.     public function removeClientFeedback(ClientFeedback $clientFeedback): self
  1983.     {
  1984.         if ($this->clientFeedback->removeElement($clientFeedback)) {
  1985.             // set the owning side to null (unless already changed)
  1986.             if ($clientFeedback->getProject() === $this) {
  1987.                 $clientFeedback->setProject(null);
  1988.             }
  1989.         }
  1990.         return $this;
  1991.     }
  1992.     public function getFilledOutClientFeedback()
  1993.     {
  1994.         $filledOutBy = [];
  1995.         foreach ($this->clientFeedback as $clientfeedback) {
  1996.             $clientContactId $clientfeedback->getFilledBy();
  1997.             $clientContact $this->client->getClientContact($clientContactId);
  1998.             if ($clientContact) {
  1999.                 if (!in_array($clientContact->getName(), $filledOutBy)) {
  2000.                     $filledOutBy[] = $clientContact->getName();
  2001.                 }
  2002.             }
  2003.         }
  2004.         return $filledOutBy;
  2005.     }
  2006.     /*
  2007.     public function getClientFeedbackTemplate(): ?ClientFeedbackTemplate
  2008.     {
  2009.         return $this->clientFeedbackTemplate;
  2010.     }
  2011.     */
  2012.     /*
  2013.     public function checkFilledFeedbackTemplate(){
  2014.         
  2015.         
  2016.         if($this->clientFeedbackTemplate){
  2017.             foreach($this->clientFeedbackTemplate->getClientFeedbackForms() as $feedbackForm) {
  2018.                 // if(!$feedbackForm->getDeletedAt() && count($feedbackForm->getClientFeedbackByProjects($this->id)->toArray()) > 0){
  2019.                 if(!$feedbackForm->getDeletedAt() && count($feedbackForm->getClientFeedbackByProjects($this->id)->toArray()) > 0){
  2020.                     return true;
  2021.                 }elseif($feedbackForm->getDeletedAt() && count($feedbackForm->getClientFeedbackByProjects($this->id)->toArray()) > 0){
  2022.                     return true;
  2023.                 }
  2024.             }
  2025.         }
  2026.         if($this->clientFeedback){
  2027.             foreach($this->clientFeedback as $feedback) {
  2028.                 if(!$feedback->isDeleted() && !$feedback->isEmpty()){
  2029.                     return true;
  2030.                 }
  2031.             }
  2032.         }
  2033.         return false;
  2034.     }
  2035.     */
  2036.     public function isAllFeedbackText()
  2037.     {
  2038.         $activeFeedbacks = [];
  2039.         $result true;
  2040.         if ($this->clientFeedback) {
  2041.             foreach ($this->clientFeedback as $feedback) {
  2042.                 if (!$feedback->isDeleted()) {
  2043.                     $activeFeedbacks[] = $feedback;
  2044.                 }
  2045.             }
  2046.         }
  2047.         if ($activeFeedbacks) {
  2048.             foreach ($activeFeedbacks as $feedback) {
  2049.                 if ($feedback->getFeedbackType() != 'short_text') {
  2050.                     return false;
  2051.                 }
  2052.             }
  2053.         } else {
  2054.             return false;
  2055.         }
  2056.         return $result;
  2057.     }
  2058.     public function checkFilledFeedbackTemplate()
  2059.     {
  2060.         $activeFeedbacks = [];
  2061.         if ($this->clientFeedback) {
  2062.             foreach ($this->clientFeedback as $feedback) {
  2063.                 if (!$feedback->isDeleted()) {
  2064.                     $activeFeedbacks[] = $feedback;
  2065.                 }
  2066.             }
  2067.         }
  2068.         if ($activeFeedbacks) {
  2069.             $allFilled true;
  2070.             $anyFilled false;
  2071.             foreach ($activeFeedbacks as $feedback) {
  2072.                 if ($feedback->isEmpty()) {
  2073.                     $allFilled false;
  2074.                 } else {
  2075.                     $anyFilled true;
  2076.                 }
  2077.             }
  2078.             if ($allFilled == true && $anyFilled == true) {
  2079.                 return 'all';
  2080.             } elseif ($anyFilled) {
  2081.                 return true;
  2082.             }
  2083.         }
  2084.         return false;
  2085.     }
  2086.     public function isFeedbackDone($returnArray false)
  2087.     {
  2088.         $totalFeedback 0;
  2089.         $missingFeedback 0;
  2090.         if ($this->clientFeedbackTemplate) {
  2091.             foreach ($this->clientFeedback as $feedback) {
  2092.                 if (!$feedback->getDeletedAt()) {
  2093.                     $totalFeedback++;
  2094.                     if (!$feedback->getComment() && !$feedback->getRating()) {
  2095.                         $missingFeedback++;
  2096.                         if (!$returnArray) return false;
  2097.                     }
  2098.                 }
  2099.             }
  2100.         }
  2101.         if (!$returnArray) {
  2102.             return true;
  2103.         } else {
  2104.             return ['total' => $totalFeedback'filled' => $totalFeedback $missingFeedback'missing' => $missingFeedback'done' => $missingFeedback == 0];
  2105.         }
  2106.     }
  2107.     public function getClientFeedbackTemplate(): ?ClientFeedbackTemplate
  2108.     {
  2109.         if ($this->clientFeedbackTemplate !== null && $this->clientFeedbackTemplate->getDeletedAt() === null) {
  2110.             return $this->clientFeedbackTemplate;
  2111.         }
  2112.         return null;
  2113.     }
  2114.     public function setClientFeedbackTemplate(?ClientFeedbackTemplate $clientFeedbackTemplate): self
  2115.     {
  2116.         $this->clientFeedbackTemplate $clientFeedbackTemplate;
  2117.         return $this;
  2118.     }
  2119.     public function getScore(): ?float
  2120.     {
  2121.         return $this->score;
  2122.     }
  2123.     public function setScore(?float $score): self
  2124.     {
  2125.         $this->score $score;
  2126.         return $this;
  2127.     }
  2128.     public function getEmailLogFeedback($toAddress$title)
  2129.     {
  2130.         global $kernel;
  2131.         $projectService $kernel->getContainer()->get('ProjectService');
  2132.         $result $projectService->getEmailLogFeedback($toAddress$title);
  2133.         return $result;
  2134.     }
  2135.     public function getProjectLostFilter(): ?ProjectLostFilter
  2136.     {
  2137.         return $this->projectLostFilter;
  2138.     }
  2139.     public function setProjectLostFilter(?ProjectLostFilter $projectLostFilter): self
  2140.     {
  2141.         // unset the owning side of the relation if necessary
  2142.         if ($projectLostFilter === null && $this->projectLostFilter !== null) {
  2143.             $this->projectLostFilter->setProject(null);
  2144.         }
  2145.         // set the owning side of the relation if necessary
  2146.         if ($projectLostFilter !== null && $projectLostFilter->getProject() !== $this) {
  2147.             $projectLostFilter->setProject($this);
  2148.         }
  2149.         $this->projectLostFilter $projectLostFilter;
  2150.         return $this;
  2151.     }
  2152.     /**
  2153.      * @return Collection<int, ExpenseRequest>
  2154.      */
  2155.     public function getExpenseRequests(): Collection
  2156.     {
  2157.         return $this->expenseRequests;
  2158.     }
  2159.     public function addExpenseRequest(ExpenseRequest $expenseRequest): self
  2160.     {
  2161.         if (!$this->expenseRequests->contains($expenseRequest)) {
  2162.             $this->expenseRequests->add($expenseRequest);
  2163.             $expenseRequest->setProject($this);
  2164.         }
  2165.         return $this;
  2166.     }
  2167.     /* 
  2168.      * @return Collection<int, Checklist>
  2169.      */
  2170.     public function getChecklists(): Collection
  2171.     {
  2172.         return $this->checklists;
  2173.     }
  2174.     public function getChecklistById(int $id): ?Checklist
  2175.     {
  2176.         foreach ($this->checklists as $checklist) {
  2177.             if ($checklist->getId() === $id) {
  2178.                 return $checklist;
  2179.             }
  2180.         }
  2181.         return null;
  2182.     }
  2183.     public function addChecklist(Checklist $checklist): self
  2184.     {
  2185.         if (!$this->checklists->contains($checklist)) {
  2186.             $this->checklists->add($checklist);
  2187.             $checklist->setProject($this);
  2188.         }
  2189.         return $this;
  2190.     }
  2191.     public function removeExpenseRequest(ExpenseRequest $expenseRequest): self
  2192.     {
  2193.         if ($this->expenseRequests->removeElement($expenseRequest)) {
  2194.             // set the owning side to null (unless already changed)
  2195.             if ($expenseRequest->getProject() === $this) {
  2196.                 $expenseRequest->setProject(null);
  2197.             }
  2198.             return $this;
  2199.         }
  2200.     }
  2201.     public function removeChecklist(Checklist $checklist): self
  2202.     {
  2203.         if ($this->checklists->removeElement($checklist)) {
  2204.             // set the owning side to null (unless already changed)
  2205.             if ($checklist->getProject() === $this) {
  2206.                 $checklist->setProject(null);
  2207.             }
  2208.         }
  2209.         return $this;
  2210.     }
  2211.     public function getBrief(): ?string
  2212.     {
  2213.         return $this->brief;
  2214.     }
  2215.     public function setBrief(?string $brief): self
  2216.     {
  2217.         $this->brief $brief;
  2218.         return $this;
  2219.     }
  2220.     public function getMattermost(): ?string
  2221.     {
  2222.         return $this->mattermost;
  2223.     }
  2224.     public function setMattermost(?string $mattermost): self
  2225.     {
  2226.         $this->mattermost $mattermost;
  2227.         return $this;
  2228.     }
  2229.     public function getMattermostName(): ?string
  2230.     {
  2231.         $group explode('/'$this->mattermost);
  2232.         $name end($group);
  2233.         $parts explode('_'$name);
  2234.         $lastPart end($parts);
  2235.         if (ctype_digit($lastPart) && (strlen($lastPart) === 10 || strlen($lastPart) === 13)) {
  2236.             array_pop($parts);
  2237.         }
  2238.         $name implode(' '$parts);
  2239.         return ucwords($name);
  2240.     }
  2241.     /**
  2242.      * @return Collection<int, ProjectDynamicField>
  2243.      */
  2244.     public function getProjectDynamicFields(): Collection
  2245.     {
  2246.         return $this->projectDynamicFields;
  2247.     }
  2248.     public function addProjectDynamicField(ProjectDynamicField $projectDynamicField): self
  2249.     {
  2250.         if (!$this->projectDynamicFields->contains($projectDynamicField)) {
  2251.             $this->projectDynamicFields->add($projectDynamicField);
  2252.             $projectDynamicField->setProject($this);
  2253.         }
  2254.         return $this;
  2255.     }
  2256.     public function removeProjectDynamicField(ProjectDynamicField $projectDynamicField): self
  2257.     {
  2258.         if ($this->projectDynamicFields->removeElement($projectDynamicField)) {
  2259.             // set the owning side to null (unless already changed)
  2260.             if ($projectDynamicField->getProject() === $this) {
  2261.                 $projectDynamicField->setProject(null);
  2262.             }
  2263.         }
  2264.         return $this;
  2265.     }
  2266.     public function getProjectHosting(): ?ProjectHosting
  2267.     {
  2268.         return $this->projectHosting;
  2269.     }
  2270.     public function setProjectHosting(?ProjectHosting $projectHosting): self
  2271.     {
  2272.         // unset the owning side of the relation if necessary
  2273.         if ($projectHosting === null && $this->projectHosting !== null) {
  2274.             $this->projectHosting->setProject(null);
  2275.         }
  2276.         // set the owning side of the relation if necessary
  2277.         if ($projectHosting !== null && $projectHosting->getProject() !== $this) {
  2278.             $projectHosting->setProject($this);
  2279.         }
  2280.         $this->projectHosting $projectHosting;
  2281.         return $this;
  2282.     }
  2283. }