<?php
namespace App\Entity;
use App\Repository\ProjectRepository;
use App\Service\CurrencyService;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\Serializer\Annotation\Groups;
#[ORM\Entity(repositoryClass: ProjectRepository::class)]
class Project
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(['LogService'])]
private $id;
#[Groups(['LogService'])]
#[ORM\Column(type: 'string', length: 255)]
private $name;
#[ORM\Column(type: 'text', nullable: true)]
#[Groups(['LogService'])]
private $description;
#[ORM\ManyToOne(targetEntity: Client::class, inversedBy: 'projects')]
#[ORM\JoinColumn(nullable: true)]
private $client;
#[ORM\OneToMany(targetEntity: Task::class, mappedBy: 'project', fetch: 'EXTRA_LAZY')]
#[ORM\OrderBy(['week' => 'ASC'])]
private $tasks;
#[ORM\OneToMany(targetEntity: VendorQuotationPlanning::class, mappedBy: 'project', fetch: 'EXTRA_LAZY')]
private $vendorQuotationPlannings;
#[ORM\OneToMany(targetEntity: SalesOrder::class, mappedBy: 'project', fetch: 'EXTRA_LAZY')]
private $salesOrders;
#[ORM\Column(type: 'datetime', nullable: true)]
#[Groups(['LogService'])]
private $createdAt;
#[ORM\Column(type: 'datetime', nullable: true)]
#[Groups(['LogService'])]
private $updatedAt;
#[ORM\Column(type: 'date', nullable: true)]
private $winDate;
#[ORM\Column(type: 'date', nullable: true)]
private $startDate;
#[ORM\Column(type: 'date', nullable: true)]
private $endDate;
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'projects')]
private $createdBy;
#[Groups(['LogService'])]
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'projectsUserIsPIC')]
private $personInCharge;
#[Groups(['LogService'])]
#[ORM\Column(type: 'string', length: 20, nullable: true)]
private $status;
#[Groups(['LogService'])]
#[ORM\Column(type: 'float', nullable: true)]
private $plannedRevenue = 0;
#[ORM\Column(type: 'float', nullable: true)]
private $plannedRevenueUsd;
#[ORM\ManyToOne(targetEntity: Currency::class, inversedBy: 'projects')]
private $currency;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $planFilename;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $planFilepath;
#[ORM\Column(type: 'string', length: 192, nullable: true)]
private $planFiletype;
#[ORM\OneToMany(targetEntity: ProjectMember::class, mappedBy: 'project', orphanRemoval: true, fetch: 'EXTRA_LAZY')]
private $projectMembers;
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $deletedAt;
#[ORM\ManyToMany(targetEntity: Department::class)]
private $department;
#[ORM\Column(type: 'boolean', nullable: true)]
private $retainer;
#[Groups(['LogService'])]
#[ORM\Column(name: '`lead`', type: 'smallint', nullable: true)]
private $lead;
#[ORM\Column(type: 'string', length: 20, nullable: true)]
private $type;
#[ORM\Column(type: 'date', nullable: true)]
private $leadDate;
#[ORM\Column(type: 'date', nullable: true)]
private $proposalDate;
#[ORM\Column(type: 'text', nullable: true)]
private $planURL;
#[ORM\Column(type: 'float', nullable: true)]
private $estimatedProfit = 0;
#[ORM\Column(type: 'boolean', nullable: true, options: ['default' => false])]
private $noEstimatedVendorCost;
#[ORM\Column(type: 'float', nullable: true)]
private $estimatedVendorCost = 0;
#[ORM\Column(type: 'float', nullable: true)]
private $estimatedVendorCostUsd;
#[ORM\OneToMany(targetEntity: ProjectSalesOrder::class, mappedBy: 'project', fetch: 'EXTRA_LAZY')]
private $projectSalesOrders;
#[ORM\OneToMany(targetEntity: ProjectAllocatedHours::class, mappedBy: 'project', fetch: 'EXTRA_LAZY')]
private $projectAllocatedHours;
#[ORM\Column(type: 'string', length: 50, nullable: true)]
private $leadSource;
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $lastReminder;
#[ORM\Column(type: 'string', length: 9, nullable: true)]
private $generatedId;
#[Groups(['LogService'])]
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $leadFailDate;
#[Groups(['LogService'])]
#[ORM\Column(type: 'text', nullable: true)]
private $leadFailNote;
#[Groups(['LogService'])]
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $leadFailRemindDate;
#[Groups(['LogService'])]
#[ORM\ManyToOne(targetEntity: ClientContact::class, inversedBy: 'projects')]
private $clientPersonInCharge;
#[ORM\OneToMany(targetEntity: SalesOrderPurchaseOrder::class, mappedBy: 'project', fetch: 'EXTRA_LAZY')]
private $salesOrderPurchaseOrders;
#[ORM\Column(type: 'smallint', nullable: true)]
private $probability;
#[ORM\Column(type: 'boolean', nullable: true, options: ['default' => false])]
private $noPresentation;
#[ORM\Column(type: 'date', nullable: true)]
private $presentationDate;
#[ORM\ManyToMany(targetEntity: ProjectClassification::class, inversedBy: 'projectsOfType')]
private $projectTypes;
#[ORM\ManyToMany(targetEntity: IndustryClassification::class, inversedBy: 'projectsOfIndustry')]
private $projectIndustries;
#[ORM\Column(type: 'date', nullable: true)]
private $proposalFollowUpDate;
#[ORM\ManyToOne(targetEntity: ProjectLeadStatus::class)]
private $leadStatus;
#[ORM\OneToMany(targetEntity: RevenuePlanning::class, mappedBy: 'project', fetch: 'EXTRA_LAZY')]
private $revenuePlannings;
#[ORM\ManyToOne(inversedBy: 'projects')]
private ?ProjectLostReason $leadFail = null;
#[ORM\OneToOne(targetEntity: ProjectDeliverable::class, mappedBy: 'project', cascade: ['persist', 'remove'])]
private $projectDeliverable;
#[ORM\OneToMany(mappedBy: 'project', targetEntity: ClientFeedback::class, cascade: ['persist', 'remove'])]
private Collection $clientFeedback;
#[ORM\ManyToOne(inversedBy: 'projects')]
private ?ClientFeedbackTemplate $clientFeedbackTemplate = null;
#[ORM\Column(nullable: true)]
private ?float $score = null;
#[ORM\OneToMany(mappedBy: 'project', targetEntity: ExpenseRequest::class)]
private Collection $expenseRequests;
#[ORM\OneToMany(mappedBy: 'project', targetEntity: Checklist::class)]
#[ORM\OneToOne(mappedBy: 'project', cascade: ['persist', 'remove'])]
private ?ProjectLostFilter $projectLostFilter = null;
#[ORM\OneToMany(mappedBy: 'project', targetEntity: Checklist::class, cascade: ['persist'])]
private Collection $checklists;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $brief = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $mattermost = null;
#[ORM\OneToMany(mappedBy: 'project', targetEntity: ProjectDynamicField::class, orphanRemoval: true)]
private Collection $projectDynamicFields;
#[ORM\OneToOne(mappedBy: 'project', cascade: ['persist', 'remove'])]
private ?ProjectHosting $projectHosting = null;
public function __clone()
{
$this->id = null;
}
public function __construct()
{
$this->tasks = new ArrayCollection();
$this->vendorQuotationPlannings = new ArrayCollection();
$this->salesOrders = new ArrayCollection();
$this->projectMembers = new ArrayCollection();
$this->department = new ArrayCollection();
$this->projectSalesOrders = new ArrayCollection();
$this->projectAllocatedHours = new ArrayCollection();
$this->salesOrderPurchaseOrders = new ArrayCollection();
$this->projectTypes = new ArrayCollection();
$this->projectIndustries = new ArrayCollection();
$this->revenuePlannings = new ArrayCollection();
$this->clientFeedback = new ArrayCollection();
$this->expenseRequests = new ArrayCollection();
$this->checklists = new ArrayCollection();
$this->projectDynamicFields = new ArrayCollection();
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function fullName()
{
return $this->generatedId ? $this->generatedId . '-' . $this->name : $this->name;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getClient(): ?Client
{
return $this->client;
}
public function setClient(?Client $client): self
{
$this->client = $client;
return $this;
}
/**
* @return Collection<int, Task>
*/
public function getTasks(): Collection
{
return $this->tasks;
}
public function addTask(Task $task): self
{
if (!$this->tasks->contains($task)) {
$this->tasks[] = $task;
$task->setProject($this);
}
return $this;
}
public function removeTask(Task $task): self
{
if ($this->tasks->removeElement($task)) {
// set the owning side to null (unless already changed)
if ($task->getProject() === $this) {
$task->setProject(null);
}
}
return $this;
}
/**
* @return Collection<int, VendorQuotationPlanning>
*/
public function getVendorQuotationPlannings(): Collection
{
return $this->vendorQuotationPlannings;
}
public function addVendorQuotationPlanning(VendorQuotationPlanning $vendorQuotationPlanning): self
{
if (!$this->vendorQuotationPlannings->contains($vendorQuotationPlanning)) {
$this->vendorQuotationPlannings[] = $vendorQuotationPlanning;
$vendorQuotationPlanning->setProject($this);
}
return $this;
}
public function removeVendorQuotationPlanning(VendorQuotationPlanning $vendorQuotationPlanning): self
{
if ($this->vendorQuotationPlannings->removeElement($vendorQuotationPlanning)) {
// set the owning side to null (unless already changed)
if ($vendorQuotationPlanning->getProject() === $this) {
$vendorQuotationPlanning->setProject(null);
}
}
return $this;
}
/**
*
* @return Collection<int, SalesOrder>
*/
public function getSalesOrders(): Collection
{
return $this->salesOrders;
}
// public function addSalesOrder(SalesOrder $salesOrder): self
// {
// if (!$this->salesOrders->contains($salesOrder)) {
// $this->salesOrders[] = $salesOrder;
// $salesOrder->setProject($this);
// }
//
// return $this;
// }
public function removeSalesOrder(SalesOrder $salesOrder): self
{
if ($this->salesOrders->removeElement($salesOrder)) {
// set the owning side to null (unless already changed)
if ($salesOrder->getProject() === $this) {
$salesOrder->setProject(null);
}
}
return $this;
}
public function getWinDate(): ?\DateTimeInterface
{
return $this->winDate;
}
public function setWinDate(?\DateTimeInterface $winDate): self
{
$this->winDate = $winDate;
return $this;
}
public function getStartDate(): ?\DateTimeInterface
{
return $this->startDate;
}
public function setStartDate(?\DateTimeInterface $startDate): self
{
$this->startDate = $startDate;
return $this;
}
public function getEndDate(): ?\DateTimeInterface
{
return $this->endDate;
}
public function setEndDate(?\DateTimeInterface $endDate): self
{
$this->endDate = $endDate;
return $this;
}
public function getCreatedBy(): ?User
{
return $this->createdBy;
}
public function setCreatedBy(?User $createdBy): self
{
$this->createdBy = $createdBy;
return $this;
}
public function getPersonInCharge(): ?User
{
return $this->personInCharge;
}
public function setPersonInCharge(?User $personInCharge): self
{
$this->personInCharge = $personInCharge;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(?string $status): self
{
$this->status = $status;
return $this;
}
public function getPlannedRevenue(): ?float
{
return $this->plannedRevenue;
}
public function setPlannedRevenue(?float $plannedRevenue): self
{
$this->plannedRevenue = $plannedRevenue;
$this->plannedRevenueUsd = $this->getPlannedRevenueToUsd($plannedRevenue);
return $this;
}
// public function getPlannedRevenueUsd(): ?float
// {
// if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->plannedRevenue;
// global $kernel;
// $currencyService = $kernel->getContainer()->get('CurrencyService');
// $dateStr = $this->createdAt->format('Y-m-d');
// return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->plannedRevenue);
// }
public function getCurrency(): ?Currency
{
if (!$this->currency) {
global $kernel;
$currencyRepository = $kernel->getContainer()->get('doctrine')->getRepository(Currency::class);
return $currencyRepository->findOneBy(['id' => 1]);
}
return $this->currency;
}
public function setCurrency(?Currency $currency): self
{
$this->currency = $currency;
return $this;
}
public function getPlanFilename(): ?string
{
return $this->planFilename;
}
public function setPlanFilename(?string $planFilename): self
{
$this->planFilename = $planFilename;
return $this;
}
public function getPlanFilepath(): ?string
{
return $this->planFilepath;
}
public function setPlanFilepath(?string $planFilepath): self
{
$this->planFilepath = $planFilepath;
return $this;
}
public function getPlanFiletype(): ?string
{
return $this->planFiletype;
}
public function setPlanFiletype(?string $planFiletype): self
{
$this->planFiletype = $planFiletype;
return $this;
}
public function getSoTotal()
{
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$total += $pso->getAmount();
}
return $total;
}
public function getSoTotalUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
// $total += $pso->getAmountUsd();
$total += $currencyService->convertAtDate($this->createdAt, $pso->getSalesOrder()->getCurrency()->getIso(), 'USD', $pso->getAmount());
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getInvoicesTotalPaid()
{
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getProject()->getId() != $this->id) continue;
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
if ($soInvoice->getInvoice()->getAmountDue() == 0) {
$total += $soInvoice->getAmount();
}
}
}
return $total;
}
public function getInvoicesTotalPaidUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getProject()->getId() != $this->id) continue;
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
if ($soInvoice->getInvoice()->getAmountDue() == 0) {
$invDateStr = $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
// $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
$total += $currencyService->convertAtDate($this->createdAt, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
}
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getInvoicesTotal()
{
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getProject()->getId() != $this->id) continue;
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
$total += $soInvoice->getAmount();
}
}
return $total;
}
/**
* @throws GuzzleException
*/
public function getInvoicesTotalUsd($endDate = null)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
if ($endDate != null && $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d') > $endDate->format('Ymd')) continue;
if ($soInvoice->getProject()->getId() != $this->id) continue;
$invDateStr = $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
// $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
$total += $currencyService->convertAtDate($this->createdAt, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
/**
* @throws GuzzleException
*/
public function getInvoicesTotalUsdByMonth($startDate, $endDate)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
if ($soInvoice->getInvoice()->getInvoiceDate()->format('Ymd') < $startDate->format('Ymd')) continue;
if ($soInvoice->getInvoice()->getInvoiceDate()->format('Ymd') > $endDate->format('Ymd')) continue;
if ($soInvoice->getProject()->getId() != $this->id) continue;
$invDateStr = $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
// $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
$total += $currencyService->convertAtDate($this->createdAt, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
/**
* @throws GuzzleException
*/
public function getAllocatedInvoicesTotal($paid = false)
{
global $kernel;
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == "VOIDED" || $soInvoice->getProject() !== $this) continue;
if ($paid && $soInvoice->getInvoice()->getXeroStatus() == "PAID") continue;
$total += $soInvoice->getAmount();
if ($soInvoice->getInvoice()->getXeroCreditNoteAllocation()) {
$total -= $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmount();
}
}
}
return $total;
}
/**
* @throws GuzzleException
*/
public function getAllocatedInvoicesTotalUsd($paid = false)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == "VOIDED" || $soInvoice->getProject() !== $this) continue;
if ($paid && $soInvoice->getInvoice()->getXeroStatus() == "PAID") continue;
// $invDateStr = $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
// $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
// $total += $usValue;
// $total += $soInvoice->getAmountUsd();
$total += $currencyService->convertAtDate($this->createdAt, $this->currency->getIso(), 'USD', $soInvoice->getAmount());
if ($soInvoice->getInvoice()->getXeroCreditNoteAllocation()) {
// $total -= $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmountUsd();
$total -= $currencyService->convertAtDate($this->createdAt, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmount());
}
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
/**
* @throws GuzzleException
*/
public function getAllocatedInvoicesTotalSgd($paid = false)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == "VOIDED" || $soInvoice->getProject() !== $this) continue;
if ($paid && $soInvoice->getInvoice()->getXeroStatus() == "PAID") continue;
// $invDateStr = $soInvoice->getInvoice()->getInvoiceDate()->format('Y-m-d');
// $usValue = $currencyService->convertAtDate($invDateStr, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getAmount());
// $total += $usValue;
// $total += $soInvoice->getAmountUsd();
$total += $currencyService->convertAtDate($this->createdAt, $this->currency->getIso(), 'SGD', $soInvoice->getAmount());
if ($soInvoice->getInvoice()->getXeroCreditNoteAllocation()) {
// $total -= $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmountUsd();
$total -= $currencyService->convertAtDate($this->createdAt, $soInvoice->getInvoice()->getCurrency()->getIso(), 'SGD', $soInvoice->getInvoice()->getXeroCreditNoteAllocation()->getAmount());
}
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getTotalVQPPlannedAmt()
{
$total = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$total += $vendorQuotationPlanning->getAmountPlanned();
}
return $total;
}
public function getVendorQuotesTotalUSD()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vendorQuotations = $vendorQuotationPlanning->getVendorQuotations();
foreach ($vendorQuotations as $vendorQuotation) {
// $usValue = $currencyService->convertAtDate($vendorQuotation->getCreatedAt()->format('Y-m-d'), $vendorQuotation->getCurrency()->getIso(), 'USD', $vendorQuotation->getAmount());
$total += $currencyService->convertAtDate($this->createdAt, $vendorQuotation->getCurrency()->getIso(), 'USD', $vendorQuotation->getAmount());
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getVendorQuotesTotal()
{
$total = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vendorQuotations = $vendorQuotationPlanning->getVendorQuotations();
foreach ($vendorQuotations as $vendorQuotation) {
$total += $vendorQuotation->getAmount();
}
}
return $total;
}
public function getProjectManhour($endDate = null)
{
$total = 0;
$tasks = $this->getTasks();
foreach ($tasks as $task) {
$timeSpents = $task->getTimeSpents();
foreach ($timeSpents as $timeSpent) {
$timeSpentDate = $timeSpent->getDate()->format('Ymd');
//if ($this->startDate != null && $timeSpentDate < $this->startDate->format('Ymd')) continue;
if ($this->endDate != null && $timeSpentDate > $this->endDate->format('Ymd')) continue;
//if ($endDate != null && $timeSpentDate > $endDate->format('Ymd')) continue;
$hours = $timeSpent->getHours();
$total += $hours;
};
}
return $total;
}
public function getProjectManhourByMonth($startDate, $endDate)
{
$total = 0;
$tasks = $this->getTasks();
foreach ($tasks as $task) {
$timeSpents = $task->getTimeSpents();
foreach ($timeSpents as $timeSpent) {
$timeSpentDate = $timeSpent->getDate()->format('Ymd');
//if ($this->startDate != null && $timeSpentDate < $this->startDate->format('Ymd')) continue;
if ($this->endDate != null && $timeSpentDate > $this->endDate->format('Ymd')) continue;
$hours = $timeSpent->getHours();
$total += $hours;
};
}
return $total;
}
public function getProjectManhourCost($endDate = null) // FIX: error on manhourcost
{
// error_reporting(E_ALL);
// ini_set('display_errors', 1);
$total = 0;
$tasks = $this->getTasks();
foreach ($tasks as $task) {
// try {
// print_r($task->getTimeSpents());
// } catch (Exception $e) {
// echo 'Caught exception: ', $e->getMessage(), "\n";
// }
// return 0;
$timeSpents = $task->getTimeSpents();
foreach ($timeSpents as $timeSpent) {
$timeSpentDate = $timeSpent->getDate()->format('Ymd');
if ($this->startDate == null || $this->endDate == null) continue;
if ($this->endDate != null && $timeSpentDate > $this->endDate->format('Ymd')) continue;
$hours = $timeSpent->getHours() ?? 0;
$rate = $timeSpent->getUser()->getHourlyRateUsd($timeSpentDate) ?? 0;
$total += $hours * $rate;
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getProjectManhourCostByMonth($startDate, $endDate)
{
$total = 0;
$tasks = $this->getTasks();
foreach ($tasks as $task) {
$timeSpents = $task->getTimeSpents();
foreach ($timeSpents as $timeSpent) {
$timeSpentDate = $timeSpent->getDate()->format('Ymd');
//if ($this->startDate != null && $timeSpentDate < $this->startDate->format('Ymd')) continue;
if ($this->endDate != null && $timeSpentDate > $this->endDate->format('Ymd')) continue;
$hours = $timeSpent->getHours();
$rate = $timeSpent->getUser()->getHourlyRateUsd($timeSpentDate);
$total += $hours * $rate;
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getProjectCost()
{
return $this->getVendorInvoicesTotalUSD() + $this->getProjectManhourCost();
}
public function getProjectEstimatedCost()
{
$totalEstimatedManHourCost = 0;
foreach ($this->projectAllocatedHours as $allocation) {
$totalEstimatedManHourCost += intval($allocation->getHours() * $allocation->getUserRole()->getCost());
}
return $this->getEstimatedVendorCostUsd() + $totalEstimatedManHourCost;
}
public function getProjectEstimatedHourCost()
{
$totalEstimatedManHourCost = 0;
foreach ($this->projectAllocatedHours as $allocation) {
$totalEstimatedManHourCost += intval($allocation->getHours() * $allocation->getUserRole()->getCost());
}
return $totalEstimatedManHourCost;
}
public function getProjectEstimatedHour()
{
$totalEstimatedManHour = 0;
foreach ($this->projectAllocatedHours as $allocation) {
$totalEstimatedManHour += intval($allocation->getHours());
}
return $totalEstimatedManHour;
}
public function getProjectEstimatedCostUsd()
{
if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->getProjectEstimatedCost();
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$dateStr = $this->createdAt->format('Y-m-d');
$amount = $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->getProjectEstimatedCost());
return round($amount, 2, PHP_ROUND_HALF_EVEN);
}
/**
* [sum]Invoices sent to client - [sum] Vendors invoices - man hours = Total Profit
* @throws GuzzleException
*/
public function getProjectProfit1()
{
return round($this->getInvoicesTotalUsd() - $this->getProjectCost(), 2, PHP_ROUND_HALF_EVEN);
}
/**
* [sum]SalesOrders sent to client - [sum] Vendors invoices - man hours = Total Profit
*/
public function getProjectProfit2()
{
return round($this->getSoTotalUsd() - $this->getVendorInvoicesTotalUSD() - $this->getProjectManhourCost(), 2, PHP_ROUND_HALF_EVEN);
}
/**
* [sum]SalesOrders sent to client - [sum] Vendor Plan - man hours = Total Profit
*/
public function getProjectProfit3()
{
// return $this->getSoTotalUsd() - $this->getVendorQuotesTotalUSD() - $this->getProjectManhourCost();
return round($this->getSoTotalUsd() - $this->getVendorPlannedTotalUsd() - $this->getProjectManhourCost(), 2, PHP_ROUND_HALF_EVEN);
}
/**
* [sum]INV sent to client - [sum] Vendors plan - man hours = Total Profit
* @throws GuzzleException
*/
public function getProjectProfit4()
{
// return $this->getInvoicesTotalUsd() - $this->getVendorQuotesTotalUSD() - $this->getProjectManhourCost();
return round($this->getInvoicesTotalUsd() - $this->getVendorPlannedTotalUsd() - $this->getProjectManhourCost(), 2, PHP_ROUND_HALF_EVEN);
}
/**
* (Total Invoices - vendor invoice total- manhourCost) * 100 / total invoices
* @throws GuzzleException
*/
public function getProjectGrossmargin1()
{
if ($this->getInvoicesTotalUsd() == 0 || $this->getProjectProfit1() == 0) return 0;
return round($this->getProjectProfit1() / $this->getInvoicesTotalUsd() * 100, 2, PHP_ROUND_HALF_EVEN);
}
/**
*
* (SO total - Vendor INV total - manhourCost) * 100 / SO total
* @throws GuzzleException
*/
public function getProjectGrossmargin2()
{
if ($this->getSoTotalUsd() == 0 || $this->getProjectProfit2() == 0) return 0;
return round($this->getProjectProfit2() / $this->getSoTotalUsd() * 100, 2, PHP_ROUND_HALF_EVEN);
}
/**
* (SO total - Vendor plan total - manhourCost) * 100 / SO total
* @throws GuzzleException
*/
public function getProjectGrossmargin3()
{
if ($this->getSoTotalUsd() == 0 || $this->getProjectProfit3() == 0) return 0;
return round($this->getProjectProfit3() / $this->getSoTotalUsd() * 100, 2, PHP_ROUND_HALF_EVEN);
}
/**
* (Total Invoices - vendor plan total - manhourCost) * 100 / total invoices
* @throws GuzzleException
*/
public function getProjectGrossmargin4()
{
if ($this->getInvoicesTotalUsd() == 0 || $this->getProjectProfit4() == 0) return 0;
return round($this->getProjectProfit4() / $this->getInvoicesTotalUsd() * 100, 2, PHP_ROUND_HALF_EVEN);
}
/**
* @throws GuzzleException
*/
public function getInvPercentagePaid()
{
if ($this->getInvoicesTotal() > 0) {
$percentagePaid = round($this->getInvoicesTotalPaid() / $this->getInvoicesTotal() * 100, 2, PHP_ROUND_HALF_EVEN);
} else {
$percentagePaid = 0;
}
return $percentagePaid;
}
public function getVendorPlannedTotal()
{
$vendorPlannedTotal = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vendorPlannedTotal += $vendorQuotationPlanning->getAmountPlanned();
}
return $vendorPlannedTotal;
}
public function getVendorPlannedTotalUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$vendorPlannedTotalUSD = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$dateStr = $vendorQuotationPlanning->getCreatedAt()->format('Y-m-d');
// $usValue = $currencyService->convertAtDate($dateStr, $vendorQuotationPlanning->getCurrency()->getIso(), 'USD', $vendorQuotationPlanning->getAmountPlanned());
$usValue = $currencyService->convertAtDate($dateStr, $vendorQuotationPlanning->getCurrency()->getIso(), 'USD', $vendorQuotationPlanning->getAmountPlanned());
$vendorPlannedTotalUSD += $usValue;
}
return round($vendorPlannedTotalUSD, 2, PHP_ROUND_HALF_EVEN);
}
public function getVendorPaymentStatus()
{
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
$vendorPaidCount = 0;
$vendorNotPaidCount = 0;
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
$vendorInvoice = $vqpInvoice->getVendorInvoice();
if ($vendorInvoice->getXeroStatus() === "PAID") {
$vendorPaidCount++;
} else if ($vendorInvoice->getXeroStatus() === "UNPAID") {
$vendorNotPaidCount++;
}
}
}
$vendorPaymentStatus = "";
if ($vendorNotPaidCount === 0 && $vendorPaidCount > 0) {
$vendorPaymentStatus = "Fully Paid";
} else if ($vendorPaidCount > 0 && $vendorNotPaidCount > 0) {
$vendorPaymentStatus = "Partially Paid";
} else {
$vendorPaymentStatus = "Not Paid";
}
return $vendorPaymentStatus;
}
public function getVendorPercentagePaid()
{
if ($this->getVendorInvoicesTotal() > 0) {
// $percentagePaid = round($this->getVendorInvoicesTotalPaid() / $this->getVendorInvoicesTotal() * 100, 2);
$percentagePaid = round(($this->getVendorPlannedTotalUsd() - $this->getVendorInvoicesTotalUsd()) / $this->getVendorPlannedTotalUsd() * 100, 2, PHP_ROUND_HALF_EVEN);
} else {
$percentagePaid = 0;
}
return $percentagePaid;
}
public function getVendorInvoicesTotal()
{
$vendorInvoicesTotal = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
// here we get amount from allocation, not directly from Vendor Invoice
if($vqpInvoice->getVendorInvoice()->getXeroStatus() == 'VOIDED') continue;
$vendorInvoicesTotal += $vqpInvoice->getAmount();
// $vendorInvoicesTotal += $vqpInvoice->getVendorInvoice()->getSubTotal();
}
}
return $vendorInvoicesTotal;
}
public function getVendorInvoicesTotalUsd($endDate = null)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$vendorInvoicesTotalUSD = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
// if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
if($vqpInvoice->getVendorInvoice()->getXeroStatus() == 'VOIDED') continue;
if ($endDate != null && $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Ymd') > $endDate->format('Ymd')) continue;
// $vendorInvoicesTotalUSD += $vqpInvoice->getAmountUsd();
$dateStr = $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
$vendorInvoicesTotalUSD += $currencyService->convertAtDate($dateStr, $vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD', $vqpInvoice->getAmount());
}
}
return round($vendorInvoicesTotalUSD, 2, PHP_ROUND_HALF_EVEN);
}
public function getVendorInvoicesTotalSgd($endDate = null)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$vendorInvoicesTotalUSD = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
// if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
if($vqpInvoice->getVendorInvoice()->getXeroStatus() == 'VOIDED') continue;
if ($endDate != null && $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Ymd') > $endDate->format('Ymd')) continue;
// $vendorInvoicesTotalUSD += $vqpInvoice->getAmountUsd();
$dateStr = $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
$vendorInvoicesTotalUSD += $currencyService->convertAtDate($dateStr, $vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'SGD', $vqpInvoice->getAmount());
}
}
return round($vendorInvoicesTotalUSD, 2, PHP_ROUND_HALF_EVEN);
}
public function getVendorInvoices()
{
$vendorInvoices = [];
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
// here we get amount from allocation, not directly from Vendor Invoice
array_push($vendorInvoices, $vqpInvoice->getVendorInvoice());
// $vendorInvoicesTotal += $vqpInvoice->getVendorInvoice()->getSubTotal();
}
}
return $vendorInvoices;
}
public function getProjectBudgetRemaining()
{
return round($this->getVendorPlannedTotal() - $this->getVendorInvoicesTotal(), 2, PHP_ROUND_HALF_EVEN);
}
public function getProjectBudgetRemainingUsd()
{
return round($this->getVendorPlannedTotalUsd() - $this->getVendorInvoicesTotalUsd(), 2, PHP_ROUND_HALF_EVEN);
}
public function getVendorInvoicesTotalUsdByMonth($startDate, $endDate)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$vendorInvoicesTotalUSD = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
$vqpInvoiceDate = $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Ymd');
if ($vqpInvoiceDate >= $startDate->format('Ymd') && $vqpInvoiceDate <= $endDate->format('Ymd')) {
if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
// $vendorInvoicesTotalUSD += $vqpInvoice->getVendorInvoice()->getSubTotalUsd();
$dateStr = $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
$vendorInvoicesTotalUSD += $currencyService->convertAtDate($dateStr, $vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD', $vqpInvoice->getVendorInvoice()->getSubTotal());
}
}
}
return round($vendorInvoicesTotalUSD, 2, PHP_ROUND_HALF_EVEN);
}
public function getVendorInvoicesTotalPaid()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$vendorInvoicesTotalPaid = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
if ($vqpInvoice->getVendorInvoice()->getXeroStatus() === "PAID") {
$vendorInvoicesTotalPaid += $vqpInvoice->getAmount();
// $vendorInvoicesTotalPaid += $currencyService->convertAtDate($this->createdAt, $vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD', $vqpInvoice->getAmount());
}
}
}
return round($vendorInvoicesTotalPaid, 2, PHP_ROUND_HALF_EVEN);
}
public function getVendorInvoicesTotalPaidUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$vendorInvoicesTotalPaid = 0;
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
if ($vqpInvoice->getVendorInvoice()->getXeroStatus() === "PAID") {
// $vendorInvoicesTotalPaid += $vqpInvoice->getAmount();
$dateStr = $vqpInvoice->getVendorInvoice()->getInvoiceDate()->format('Y-m-d');
$vendorInvoicesTotalPaid += $currencyService->convertAtDate($dateStr, $vqpInvoice->getVendorInvoice()->getCurrency()->getIso(), 'USD', $vqpInvoice->getAmount());
}
}
}
return round($vendorInvoicesTotalPaid, 2, PHP_ROUND_HALF_EVEN);
}
/**
* @return Collection<int, ProjectMember>
*/
public function getProjectMembers(): Collection
{
return $this->projectMembers;
}
public function getProjectMember($user)
{
if (is_object($user)) {
foreach ($this->projectMembers as $member) {
if ($member->getUser() == $user) return $member;
};
} else {
foreach ($this->projectMembers as $member) {
if ($member->getUser()->getId() == $user) return $member;
};
}
return false;
}
public function getIsIncluded($user)
{
foreach ($this->projectMembers as $member) {
if ($member->getUser() == $user) return true;
};
return false;
}
public function getProjectMembersByDepartmentId($departmentId)
{
$members = [];
foreach ($this->projectMembers as $member) {
if (($member->getUser()->getDepartment() !== null) && ($member->getUser()->getDepartment()->getId() == $departmentId)) {
// array_push($members, $member);
$members[] = $member;
}
}
return $members;
}
public function addProjectMember(ProjectMember $projectMember): self
{
if (!$this->projectMembers->contains($projectMember)) {
$this->projectMembers[] = $projectMember;
$projectMember->setProject($this);
}
return $this;
}
public function removeProjectMember(ProjectMember $projectMember): self
{
if ($this->projectMembers->removeElement($projectMember)) {
// set the owning side to null (unless already changed)
if ($projectMember->getProject() === $this) {
$projectMember->setProject(null);
}
}
return $this;
}
public function getDeletedAt(): ?\DateTimeImmutable
{
return $this->deletedAt;
}
public function setDeletedAt(?\DateTimeImmutable $deletedAt): self
{
$this->deletedAt = $deletedAt;
return $this;
}
/**
* @return Collection<int, Department>
*/
public function getDepartment(): Collection
{
return $this->department;
}
public function addDepartment(Department $department): self
{
if (!$this->department->contains($department)) {
$this->department[] = $department;
}
return $this;
}
public function removeDepartment(Department $department): self
{
$this->department->removeElement($department);
return $this;
}
function departmentNames()
{
$departments = [];
foreach ($this->getDepartment() as $department) {
if (!in_array($department->getName(), $departments))
array_push($departments, $department->getName());
}
return implode(', ', $departments);
}
public function getRetainer(): ?bool
{
return $this->retainer;
}
public function setRetainer(bool $retainer): self
{
$this->retainer = $retainer;
return $this;
}
public function getLead(): ?int
{
// return $this->lead;
return $this->leadStatus ? $this->leadStatus->getLead() : $this->lead;
}
public function setLead(?int $lead): self
{
global $kernel;
$projectService = $kernel->getContainer()->get('ProjectService');
$projectLeadStatus = $projectService->getProjectLeadStatus($lead);
$this->setProbability($projectLeadStatus ? $projectLeadStatus->getProbability() : $this->probability);
$this->setLeadStatus($projectLeadStatus);
$this->lead = $lead;
return $this;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
public function getLeadDate(): ?\DateTimeInterface
{
return $this->leadDate;
}
public function setLeadDate(?\DateTimeInterface $leadDate): self
{
$this->leadDate = $leadDate;
return $this;
}
public function getProposalDate(): ?\DateTimeInterface
{
return $this->proposalDate;
}
public function setProposalDate(?\DateTimeInterface $proposalDate): self
{
$this->proposalDate = $proposalDate;
return $this;
}
public function leadStatusText($id = null)
{
return $this->leadStatus->getName() || 'Unknown';
}
public function getPlanURL(): ?string
{
return $this->planURL;
}
public function setPlanURL(?string $planURL): self
{
$this->planURL = $planURL;
return $this;
}
public function getEstimatedProfit(): ?float
{
return $this->plannedRevenue - $this->estimatedVendorCost;
// return $this->estimatedProfit;
}
public function setEstimatedProfit(?float $estimatedProfit): self
{
$this->estimatedProfit = $estimatedProfit;
return $this;
}
public function getEstimatedProfitUsd()
{
// if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->getEstimatedProfit();
// global $kernel;
// $currencyService = $kernel->getContainer()->get('CurrencyService');
// $dateStr = $this->createdAt->format('Y-m-d');
// return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->getEstimatedProfit());
return round($this->plannedRevenueUsd - $this->estimatedVendorCostUsd, 2, PHP_ROUND_HALF_EVEN);
}
public function actualStatus()
{
if ($this->type == "LEAD") {
return $this->lead . ' - ' . $this->getLeadStatus()->getName();
} else {
return $this->status;
}
}
public function getEstimatedVendorCost(): ?float
{
return $this->estimatedVendorCost;
}
public function setEstimatedVendorCost(float $estimatedVendorCost): self
{
$this->estimatedVendorCost = $estimatedVendorCost;
$this->estimatedVendorCostUsd = $this->getEstimatedVendorCostToUsd($estimatedVendorCost);
return $this;
}
/**
* @return Collection<int, ProjectSalesOrder>
*/
public function getProjectSalesOrders(): Collection
{
return $this->projectSalesOrders;
}
public function addProjectSalesOrder(ProjectSalesOrder $projectSalesOrder): self
{
if (!$this->projectSalesOrders->contains($projectSalesOrder)) {
$this->projectSalesOrders[] = $projectSalesOrder;
$projectSalesOrder->setProject($this);
}
return $this;
}
public function removeProjectSalesOrder(ProjectSalesOrder $projectSalesOrder): self
{
if ($this->projectSalesOrders->removeElement($projectSalesOrder)) {
// set the owning side to null (unless already changed)
if ($projectSalesOrder->getProject() === $this) {
$projectSalesOrder->setProject(null);
}
}
return $this;
}
public function getProjectSalesOrderTotalAmountUsed(): ?float
{
$amountUsed = 0;
foreach ($this->projectSalesOrders as $projectSalesOrder) {
$amountUsed += $projectSalesOrder->getAmount();
}
return $amountUsed;
}
public function getProjectSalesOrderTotalAmountUsedUsd(): ?float
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$amount = 0;
// return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->getProjectSalesOrderTotalAmountUsed());
foreach ($this->projectSalesOrders as $projectSalesOrder) {
$amount += $currencyService->convertAtDate($this->createdAt, $projectSalesOrder->getSalesOrder()->getCurrency()->getIso(), 'USD', $projectSalesOrder->getAmount());
}
return round($amount, 2, PHP_ROUND_HALF_EVEN);
}
/**
* @return Collection|ProjectAllocatedHours[]
*/
public function getProjectAllocatedHours(): Collection
{
return $this->projectAllocatedHours;
}
public function addProjectAllocatedHour(ProjectAllocatedHours $projectAllocatedHour): self
{
if (!$this->projectAllocatedHours->contains($projectAllocatedHour)) {
$this->projectAllocatedHours[] = $projectAllocatedHour;
$projectAllocatedHour->setProject($this);
}
return $this;
}
public function removeProjectAllocatedHour(ProjectAllocatedHours $projectAllocatedHour): self
{
if ($this->projectAllocatedHours->removeElement($projectAllocatedHour)) {
// set the owning side to null (unless already changed)
if ($projectAllocatedHour->getProject() === $this) {
$projectAllocatedHour->setProject(null);
}
}
return $this;
}
public function getLeadSource(): ?string
{
return $this->leadSource;
}
public function setLeadSource(?string $leadSource): self
{
$this->leadSource = $leadSource;
return $this;
}
public function getLeadSourceFormatted(): ?string
{
if ($this->leadSource == "client") {
return "Existing client";
} else if ($this->leadSource == "other") {
return "Other";
} else {
return $this->leadSource;
}
}
public function getLastReminder(): ?\DateTimeImmutable
{
return $this->lastReminder;
}
public function setLastReminder(?\DateTimeImmutable $lastReminder): self
{
$this->lastReminder = $lastReminder;
return $this;
}
public function getGeneratedId(): ?string
{
return $this->generatedId;
}
public function setGeneratedId(?string $generatedId): self
{
$this->generatedId = $generatedId;
return $this;
}
public function getLeadFailDate(): ?\DateTimeImmutable
{
return $this->leadFailDate;
}
public function setLeadFailDate(?\DateTimeImmutable $leadFailDate): self
{
$this->leadFailDate = $leadFailDate;
return $this;
}
public function getLeadFailNote(): ?string
{
return $this->leadFailNote;
}
public function setLeadFailNote(?string $leadFailNote): self
{
$this->leadFailNote = $leadFailNote;
return $this;
}
public function getLeadFailRemindDate(): ?\DateTimeImmutable
{
return $this->leadFailRemindDate;
}
public function setLeadFailRemindDate(?\DateTimeImmutable $leadFailRemindDate): self
{
$this->leadFailRemindDate = $leadFailRemindDate;
return $this;
}
public function getClientPersonInCharge(): ?ClientContact
{
return $this->clientPersonInCharge;
}
public function setClientPersonInCharge(?ClientContact $clientPersonInCharge): self
{
$this->clientPersonInCharge = $clientPersonInCharge;
return $this;
}
/**
* @return Collection|SalesOrderPurchaseOrder[]
*/
public function getSalesOrderPurchaseOrders(): Collection
{
return $this->salesOrderPurchaseOrders;
}
public function addSalesOrderPurchaseOrder(SalesOrderPurchaseOrder $salesOrderPurchaseOrder): self
{
if (!$this->salesOrderPurchaseOrders->contains($salesOrderPurchaseOrder)) {
$this->salesOrderPurchaseOrders[] = $salesOrderPurchaseOrder;
$salesOrderPurchaseOrder->setProject($this);
}
return $this;
}
public function removeSalesOrderPurchaseOrder(SalesOrderPurchaseOrder $salesOrderPurchaseOrder): self
{
if ($this->salesOrderPurchaseOrders->removeElement($salesOrderPurchaseOrder)) {
// set the owning side to null (unless already changed)
if ($salesOrderPurchaseOrder->getProject() === $this) {
$salesOrderPurchaseOrder->setProject(null);
}
}
return $this;
}
public function getPlannedRevenueUsd(): ?float
{
return $this->plannedRevenueUsd; // already converted properly
}
public function setPlannedRevenueUsd(?float $plannedRevenueUsd): self
{
$this->plannedRevenueUsd = $plannedRevenueUsd;
return $this;
}
public function getPlannedRevenueToUsd(): ?float
{
if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->plannedRevenue ?? 0;
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
// $dateStr = $this->createdAt ? $this->createdAt->format('Y-m-d') : date('Y-m-d');
// return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->plannedRevenue) ?? 0;
$dateStr = $this->createdAt ?? date('Y-m-d');
$amount = $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->plannedRevenue) ?? 0;
return round($amount, 2, PHP_ROUND_HALF_EVEN);
}
public function getNoEstimatedVendorCost(): ?bool
{
return $this->noEstimatedVendorCost;
}
public function setNoEstimatedVendorCost(bool $noEstimatedVendorCost): self
{
$this->noEstimatedVendorCost = $noEstimatedVendorCost;
return $this;
}
public function getEstimatedVendorCostUsd(): ?float
{
return $this->estimatedVendorCostUsd; // already converted properly
}
public function setEstimatedVendorCostUsd(float $estimatedVendorCostUsd): self
{
$this->estimatedVendorCostUsd = $estimatedVendorCostUsd;
return $this;
}
public function getEstimatedVendorCostToUsd(): ?float
{
if ($this->currency == null || $this->currency->getIso() == 'USD') return $this->estimatedVendorCost ?? 0;
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
// $dateStr = $this->startDate->format('Y-m-d');
// $dateStr = !empty($this->startDate) ? $this->startDate->format('Y-m-d') : date('Y-m-d');
// return $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->estimatedVendorCost) ?? 0;
$dateStr = $this->createdAt ?? date('Y-m-d');
$amount = $currencyService->convertAtDate($dateStr, $this->currency->getIso(), 'USD', $this->estimatedVendorCost) ?? 0;
return round($amount, 2, PHP_ROUND_HALF_EVEN);
}
public function getProbability(): ?int
{
return $this->probability;
}
public function setProbability(?int $probability): self
{
$this->probability = $probability;
return $this;
}
public function getProbabilityRate()
{
$probability = $this->probability ?? 0;
if ($probability == 0) {
// switch ($this->lead) {
// case 8:
// $probability = 100;
// break;
// case 9:
// $probability = 0;
// break;
// default:
// $probability = 10;
// break;
// }
$probability = $this->leadStatus->getProbability();
}
return $probability;
}
public function getProbabilityText()
{
// $probability = $this->probability;
// switch ($probability) {
// case 100:
// return "100%";
// break;
// case 90:
// return "Above 80%";
// break;
// case 50:
// return "Between 50% to 80%";
// break;
// case 10:
// return "Below 50%";
// break;
// case 0:
// return "0%";
// break;
// default:
// return "-";
// break;
// }
return $this->getProbability() ? $this->getProbability() . '%' : '-';
}
public function getNoPresentation(): ?bool
{
return $this->noPresentation;
}
public function setNoPresentation(bool $noPresentation): self
{
$this->noPresentation = $noPresentation;
return $this;
}
public function getPresentationDate(): ?\DateTimeInterface
{
return $this->presentationDate;
}
public function setPresentationDate(?\DateTimeInterface $presentationDate): self
{
$this->presentationDate = $presentationDate;
return $this;
}
/**
* @return Collection|ProjectClassification[]
*/
public function getProjectTypes(): Collection
{
return $this->projectTypes;
}
public function addProjectType(ProjectClassification $projectType): self
{
if (!$this->projectTypes->contains($projectType)) {
$this->projectTypes[] = $projectType;
}
return $this;
}
public function removeProjectType(ProjectClassification $projectType): self
{
$this->projectTypes->removeElement($projectType);
return $this;
}
/**
* @return Collection|IndustryClassification[]
*/
public function getProjectIndustries(): Collection
{
return $this->projectIndustries;
}
public function addProjectIndustry(IndustryClassification $projectIndustry): self
{
if (!$this->projectIndustries->contains($projectIndustry)) {
$this->projectIndustries[] = $projectIndustry;
}
return $this;
}
public function removeProjectIndustry(IndustryClassification $projectIndustry): self
{
$this->projectIndustries->removeElement($projectIndustry);
return $this;
}
public function removeAllProjectIndustries()
{
$this->projectIndustries->clear();
}
public function getProposalFollowUpDate(): ?\DateTimeInterface
{
return $this->proposalFollowUpDate;
}
public function setProposalFollowUpDate(?\DateTimeInterface $proposalFollowUpDate): self
{
$this->proposalFollowUpDate = $proposalFollowUpDate;
return $this;
}
public function getLeadStatus(): ?ProjectLeadStatus
{
return $this->leadStatus;
}
public function setLeadStatus(?ProjectLeadStatus $leadStatus): self
{
$this->leadStatus = $leadStatus;
return $this;
}
/**
* @return Collection|RevenuePlanning[]
*/
public function getRevenuePlannings(): Collection
{
// return $this->revenuePlannings;
$revenuePlannings = $this->revenuePlannings->toArray();
usort($revenuePlannings, function ($a, $b) {
$aDate = $a->getYear() . $a->getMonth();
$bDate = $b->getYear() . $b->getMonth();
return $aDate <=> $bDate;
});
return new ArrayCollection($revenuePlannings);
}
/**
* Calculate and return the total revenue planning amount.
*
* @return float
*/
public function getTotalRevenuePlanning(): float
{
$totalAmount = 0;
foreach ($this->revenuePlannings as $revenuePlanning) {
$totalAmount += $revenuePlanning->getAmount();
}
return $totalAmount;
}
/**
* Calculate and return the total revenue planning amount in USD.
*
* @return float
*/
public function getTotalRevenuePlanningUsd(): float
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$totalAmountUsd = 0;
foreach ($this->revenuePlannings as $revenuePlanning) {
// $totalAmountUsd += $revenuePlanning->getAmountUsd();
$totalAmountUsd += $currencyService->convertAtDate($this->createdAt, $this->currency->getIso(), 'USD', $revenuePlanning->getAmount());
}
return round($totalAmountUsd, 2, PHP_ROUND_HALF_EVEN);
}
public function getTotalRevenuePlanningDifference(): float
{
return abs($this->getTotalRevenuePlanning() - $this->getEstimatedProfit()) < 0.00001 ? 0 : $this->getTotalRevenuePlanning() - $this->getEstimatedProfit();
}
public function getTotalRevenuePlanningDifferenceUsd(): float
{
return abs($this->getTotalRevenuePlanningUsd() - $this->getEstimatedProfitUsd()) < 0.00001 ? 0 : $this->getTotalRevenuePlanningUsd() - $this->getEstimatedProfitUsd();
}
public function addRevenuePlanning(RevenuePlanning $revenuePlanning): self
{
if (!$this->revenuePlannings->contains($revenuePlanning)) {
$this->revenuePlannings[] = $revenuePlanning;
$revenuePlanning->setProject($this);
}
return $this;
}
public function removeRevenuePlanning(RevenuePlanning $revenuePlanning): self
{
if ($this->revenuePlannings->removeElement($revenuePlanning)) {
// set the owning side to null (unless already changed)
if ($revenuePlanning->getProject() === $this) {
$revenuePlanning->setProject(null);
}
}
return $this;
}
public function getTotalVendorCost()
{
$total = 0;
$ratio = 1;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
// if($pso->getProject() == $this){
// $ratio = $useRatio ? $pso->getAmount() / $soInvoice->getSalesOrder()->getSubTotal() : 1;
// }
// $ratio = $useRatio ? $soInvoice->getAmount() / $soInvoice->getSalesOrder()->getSubTotal() : 1;
$total += $soInvoice->getInvoice()->getVendorCost($this);
}
}
return $total;
}
public function getInvVendorCostByFinancialYear($year = null, $isAllocated = false)
{
$total = 0;
if ($year) {
$start = date('Y-m-d', strtotime('first day of November ' . ($year - 1)));
$end = date('Y-m-d', strtotime('last day of October ' . $year));
}
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
if($vendorQuotationPlannings){
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
$invoice = $vqpInvoice->getVendorInvoice();
if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
$invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
$total += $isAllocated ? $vqpInvoice->getAmount() : $invoice->getSubTotal();
}
}
}
}
/*
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
foreach ($soInvoices as $soInvoice) {
$invoice = $soInvoice->getInvoice();
if ($invoice->getXeroStatus() == 'VOIDED') continue;
$invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
$total += $invoice->getSubTotal();
}
}
}
*/
return $total;
}
public function getInvoices()
{
$invoices = [];
$projectSalesOrders = $this->getProjectSalesOrders();
if ($projectSalesOrders) {
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
foreach ($soInvoices as $soInvoice) {
$invoice = $soInvoice->getInvoice();
array_push($invoices, $invoice);
}
}
}
return $invoices;
}
public function getTotalVendorCostUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
// $total += $soInvoice->getInvoice()->getVendorCostUsd($this);
$total += $currencyService->convertAtDate($this->createdAt, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getInvoice()->getVendorCost($this));
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getInvVendorCostByFinancialYearSgd($year = null, $isAllocated = false)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
if ($year) {
$start = date('Y-m-d', strtotime('first day of November ' . ($year - 1)));
$end = date('Y-m-d', strtotime('last day of October ' . $year));
}
// foreach ($projectSalesOrders as $pso) {
// $soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
// foreach ($soInvoices as $soInvoice) {
// $invoice = $soInvoice->getInvoice();
// if ($invoice->getXeroStatus() == 'VOIDED') continue;
// $invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
// if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
// $vendorCost = $invoice->getSubTotal();
// $currencyIso = $invoice->getCurrency()->getIso();
// $total += $currencyService->convertAtDate($this->createdAt, $currencyIso, 'SGD', $vendorCost);
// }
// }
// }
$vendorQuotationPlannings = $this->getVendorQuotationPlannings();
if($vendorQuotationPlannings){
foreach ($vendorQuotationPlannings as $vendorQuotationPlanning) {
$vqpInvoices = $vendorQuotationPlanning->getVendorQuotationPlanningVendorInvoices();
foreach ($vqpInvoices as $vqpInvoice) {
$invoice = $vqpInvoice->getVendorInvoice();
if ($vqpInvoice->getVendorInvoice()->getXeroStatus() != 'PAID') continue;
$invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
$vendorCost = $invoice->getSubTotal();
if($isAllocated) $vendorCost = $vqpInvoice->getAmount();
$currencyIso = $invoice->getCurrency()->getIso();
$total += $currencyService->convertAtDate($this->createdAt, $currencyIso, 'SGD', $vendorCost);
}
}
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getTotalRevenue()
{
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
$total += $soInvoice->getInvoice()->getRevenue($this);
}
}
return $total;
}
public function getInvRevenueByFinancialYear($year = null)
{
$total = 0;
$start = $end = null;
if ($year) {
$start = date('Y-m-d', strtotime('first day of November ' . ($year - 1)));
$end = date('Y-m-d', strtotime('last day of October ' . $year));
}
foreach ($this->getProjectSalesOrders() as $pso) {
foreach ($pso->getSalesOrder()->getSalesOrderInvoices($this->id) as $soInvoice) {
$invoice = $soInvoice->getInvoice();
if ($invoice->getXeroStatus() == 'VOIDED') continue;
$invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
$total += $soInvoice->getAmount();
// $total += $invoice->getSubTotal();
}
}
}
return $total;
}
public function getInvRevenueByFinancialYearSgd($year = null, $isAllocated = false)
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
// Determine the start and end dates if a year is provided
if ($year) {
$start = date('Y-m-d', strtotime('first day of November ' . ($year - 1)));
$end = date('Y-m-d', strtotime('last day of October ' . $year));
}
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
foreach ($soInvoices as $soInvoice) {
$invoice = $soInvoice->getInvoice();
if ($invoice->getXeroStatus() == 'VOIDED') continue;
$invoiceDate = $invoice->getInvoiceDate()->format('Y-m-d');
if (!$year || ($invoiceDate >= $start && $invoiceDate <= $end)) {
$revenue = $invoice->getSubTotal();
if($isAllocated) $revenue = $soInvoice->getAmount();
$currencyIso = $invoice->getCurrency()->getIso();
$total += $currencyService->convertAtDate($this->createdAt, $currencyIso, 'SGD', $revenue);
}
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getTotalRevenueUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices($this->id);
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getInvoice()->getXeroStatus() == 'VOIDED') continue;
// $total += $soInvoice->getInvoice()->getRevenueUsd($this);
$total += $currencyService->convertAtDate($this->createdAt, $soInvoice->getInvoice()->getCurrency()->getIso(), 'USD', $soInvoice->getInvoice()->getRevenue($this));
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getAllocatedCreditNotesTotal($status = null): ?float
{
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getProject() !== $this) continue;
if ($status != null && $soInvoice->getInvoice()->getXeroStatus() != $status || !$soInvoice->getInvoice()->getXeroCreditNoteAllocation()) continue;
$total += $soInvoice->getInvoice()->getAllocatedCreditNote($this);
}
}
return $total;
}
public function getAllocatedCreditNotesTotalUsd($status = null): ?float
{
$total = 0;
$projectSalesOrders = $this->getProjectSalesOrders();
foreach ($projectSalesOrders as $pso) {
$soInvoices = $pso->getSalesOrder()->getSalesOrderInvoices();
foreach ($soInvoices as $soInvoice) {
if ($soInvoice->getProject() !== $this) continue;
if ($status != null && $soInvoice->getInvoice()->getXeroStatus() != $status || !$soInvoice->getInvoice()->getXeroCreditNoteAllocation()) continue;
$total += $soInvoice->getInvoice()->getAllocatedCreditNoteUsd($this);
}
}
return round($total, 2, PHP_ROUND_HALF_EVEN);
}
public function getLeadLostReason($withNote = true)
{
$text = '';
if ($this->projectLostFilter) {
$mainReason = $this->projectLostFilter->getMainReason() ? $this->projectLostFilter->getMainReason()->getTitle() : null;
$subReason = $this->projectLostFilter->getSubReason() ? $this->projectLostFilter->getSubReason()->getTitle() : null;
$subReason = $subReason ? ' - ' . $subReason : null;
$text = $mainReason . $subReason;
} else {
if ($this->leadFail) {
$reasonTitle = $this->leadFail ? $this->leadFail->getTitle() : null;
$text = $reasonTitle;
}
}
if ($withNote && $this->leadFailNote) $text = $text . ': ' . $this->leadFailNote;
return $text;
}
public function getLeadFail(): ?ProjectLostReason
{
return $this->leadFail;
}
public function setLeadFail(?ProjectLostReason $leadFail): self
{
$this->leadFail = $leadFail;
return $this;
}
public function getProjectDeliverable(): ?ProjectDeliverable
{
return $this->projectDeliverable;
}
public function checkProjectDeliverable()
{
if (!empty($this->projectDeliverable)) {
if (
!empty($this->projectDeliverable->getThumbnails()) ||
!empty($this->projectDeliverable->getProjectDeliverableFiles()->toArray())
) {
return true;
}
}
return false;
}
public function setProjectDeliverable(?ProjectDeliverable $projectDeliverable): self
{
// unset the owning side of the relation if necessary
if ($projectDeliverable === null && $this->projectDeliverable !== null) {
$this->projectDeliverable->setProject(null);
}
// set the owning side of the relation if necessary
if ($projectDeliverable !== null && $projectDeliverable->getProject() !== $this) {
$projectDeliverable->setProject($this);
}
$this->projectDeliverable = $projectDeliverable;
return $this;
}
public function getFeedbackScore()
{
$scoreCount = 0;
$feedbackCount = 0;
$total = 0;
foreach ($this->clientFeedback as $feedback) {
// if($feedback->getClientFeedbackForm()->getClientFeedbackTemplate() == $this->clientFeedbackTemplate ){
if ($feedback->getRating() && $feedback->getDeletedAt() == NULL) {
$scoreCount += $feedback->getRating() ?: 0;
$feedbackCount++;
}
// }
}
if ($feedbackCount > 0) {
$total = number_format($scoreCount / $feedbackCount, 1);
}
return $total;
}
/**
* @return Collection<int, ClientFeedback>
*/
public function getClientFeedback(): Collection
{
return $this->clientFeedback;
}
public function getActiveClientFeedback($feedbackTemplate = null)
{
$clientFeedbacks = [];
foreach ($this->clientFeedback as $clientFeedback) {
if (!$clientFeedback->isDeleted()) {
if ($feedbackTemplate === null || $clientFeedback->getFeedbackTemplate() === $feedbackTemplate) {
$clientFeedbacks[] = $clientFeedback;
}
// $clientFeedbacks[] = $clientFeedback;
}
}
usort($clientFeedbacks, function ($a, $b) {
return $a->getCustomOrder() - $b->getCustomOrder();
});
return $clientFeedbacks;
}
public function addClientFeedback(ClientFeedback $clientFeedback): self
{
if (!$this->clientFeedback->contains($clientFeedback)) {
$this->clientFeedback->add($clientFeedback);
$clientFeedback->setProject($this);
}
return $this;
}
public function removeClientFeedback(ClientFeedback $clientFeedback): self
{
if ($this->clientFeedback->removeElement($clientFeedback)) {
// set the owning side to null (unless already changed)
if ($clientFeedback->getProject() === $this) {
$clientFeedback->setProject(null);
}
}
return $this;
}
public function getFilledOutClientFeedback()
{
$filledOutBy = [];
foreach ($this->clientFeedback as $clientfeedback) {
$clientContactId = $clientfeedback->getFilledBy();
$clientContact = $this->client->getClientContact($clientContactId);
if ($clientContact) {
if (!in_array($clientContact->getName(), $filledOutBy)) {
$filledOutBy[] = $clientContact->getName();
}
}
}
return $filledOutBy;
}
/*
public function getClientFeedbackTemplate(): ?ClientFeedbackTemplate
{
return $this->clientFeedbackTemplate;
}
*/
/*
public function checkFilledFeedbackTemplate(){
if($this->clientFeedbackTemplate){
foreach($this->clientFeedbackTemplate->getClientFeedbackForms() as $feedbackForm) {
// if(!$feedbackForm->getDeletedAt() && count($feedbackForm->getClientFeedbackByProjects($this->id)->toArray()) > 0){
if(!$feedbackForm->getDeletedAt() && count($feedbackForm->getClientFeedbackByProjects($this->id)->toArray()) > 0){
return true;
}elseif($feedbackForm->getDeletedAt() && count($feedbackForm->getClientFeedbackByProjects($this->id)->toArray()) > 0){
return true;
}
}
}
if($this->clientFeedback){
foreach($this->clientFeedback as $feedback) {
if(!$feedback->isDeleted() && !$feedback->isEmpty()){
return true;
}
}
}
return false;
}
*/
public function isAllFeedbackText()
{
$activeFeedbacks = [];
$result = true;
if ($this->clientFeedback) {
foreach ($this->clientFeedback as $feedback) {
if (!$feedback->isDeleted()) {
$activeFeedbacks[] = $feedback;
}
}
}
if ($activeFeedbacks) {
foreach ($activeFeedbacks as $feedback) {
if ($feedback->getFeedbackType() != 'short_text') {
return false;
}
}
} else {
return false;
}
return $result;
}
public function checkFilledFeedbackTemplate()
{
$activeFeedbacks = [];
if ($this->clientFeedback) {
foreach ($this->clientFeedback as $feedback) {
if (!$feedback->isDeleted()) {
$activeFeedbacks[] = $feedback;
}
}
}
if ($activeFeedbacks) {
$allFilled = true;
$anyFilled = false;
foreach ($activeFeedbacks as $feedback) {
if ($feedback->isEmpty()) {
$allFilled = false;
} else {
$anyFilled = true;
}
}
if ($allFilled == true && $anyFilled == true) {
return 'all';
} elseif ($anyFilled) {
return true;
}
}
return false;
}
public function isFeedbackDone($returnArray = false)
{
$totalFeedback = 0;
$missingFeedback = 0;
if ($this->clientFeedbackTemplate) {
foreach ($this->clientFeedback as $feedback) {
if (!$feedback->getDeletedAt()) {
$totalFeedback++;
if (!$feedback->getComment() && !$feedback->getRating()) {
$missingFeedback++;
if (!$returnArray) return false;
}
}
}
}
if (!$returnArray) {
return true;
} else {
return ['total' => $totalFeedback, 'filled' => $totalFeedback - $missingFeedback, 'missing' => $missingFeedback, 'done' => $missingFeedback == 0];
}
}
public function getClientFeedbackTemplate(): ?ClientFeedbackTemplate
{
if ($this->clientFeedbackTemplate !== null && $this->clientFeedbackTemplate->getDeletedAt() === null) {
return $this->clientFeedbackTemplate;
}
return null;
}
public function setClientFeedbackTemplate(?ClientFeedbackTemplate $clientFeedbackTemplate): self
{
$this->clientFeedbackTemplate = $clientFeedbackTemplate;
return $this;
}
public function getScore(): ?float
{
return $this->score;
}
public function setScore(?float $score): self
{
$this->score = $score;
return $this;
}
public function getEmailLogFeedback($toAddress, $title)
{
global $kernel;
$projectService = $kernel->getContainer()->get('ProjectService');
$result = $projectService->getEmailLogFeedback($toAddress, $title);
return $result;
}
public function getProjectLostFilter(): ?ProjectLostFilter
{
return $this->projectLostFilter;
}
public function setProjectLostFilter(?ProjectLostFilter $projectLostFilter): self
{
// unset the owning side of the relation if necessary
if ($projectLostFilter === null && $this->projectLostFilter !== null) {
$this->projectLostFilter->setProject(null);
}
// set the owning side of the relation if necessary
if ($projectLostFilter !== null && $projectLostFilter->getProject() !== $this) {
$projectLostFilter->setProject($this);
}
$this->projectLostFilter = $projectLostFilter;
return $this;
}
/**
* @return Collection<int, ExpenseRequest>
*/
public function getExpenseRequests(): Collection
{
return $this->expenseRequests;
}
public function addExpenseRequest(ExpenseRequest $expenseRequest): self
{
if (!$this->expenseRequests->contains($expenseRequest)) {
$this->expenseRequests->add($expenseRequest);
$expenseRequest->setProject($this);
}
return $this;
}
/*
* @return Collection<int, Checklist>
*/
public function getChecklists(): Collection
{
return $this->checklists;
}
public function getChecklistById(int $id): ?Checklist
{
foreach ($this->checklists as $checklist) {
if ($checklist->getId() === $id) {
return $checklist;
}
}
return null;
}
public function addChecklist(Checklist $checklist): self
{
if (!$this->checklists->contains($checklist)) {
$this->checklists->add($checklist);
$checklist->setProject($this);
}
return $this;
}
public function removeExpenseRequest(ExpenseRequest $expenseRequest): self
{
if ($this->expenseRequests->removeElement($expenseRequest)) {
// set the owning side to null (unless already changed)
if ($expenseRequest->getProject() === $this) {
$expenseRequest->setProject(null);
}
return $this;
}
}
public function removeChecklist(Checklist $checklist): self
{
if ($this->checklists->removeElement($checklist)) {
// set the owning side to null (unless already changed)
if ($checklist->getProject() === $this) {
$checklist->setProject(null);
}
}
return $this;
}
public function getBrief(): ?string
{
return $this->brief;
}
public function setBrief(?string $brief): self
{
$this->brief = $brief;
return $this;
}
public function getMattermost(): ?string
{
return $this->mattermost;
}
public function setMattermost(?string $mattermost): self
{
$this->mattermost = $mattermost;
return $this;
}
public function getMattermostName(): ?string
{
$group = explode('/', $this->mattermost);
$name = end($group);
$parts = explode('_', $name);
$lastPart = end($parts);
if (ctype_digit($lastPart) && (strlen($lastPart) === 10 || strlen($lastPart) === 13)) {
array_pop($parts);
}
$name = implode(' ', $parts);
return ucwords($name);
}
/**
* @return Collection<int, ProjectDynamicField>
*/
public function getProjectDynamicFields(): Collection
{
return $this->projectDynamicFields;
}
public function addProjectDynamicField(ProjectDynamicField $projectDynamicField): self
{
if (!$this->projectDynamicFields->contains($projectDynamicField)) {
$this->projectDynamicFields->add($projectDynamicField);
$projectDynamicField->setProject($this);
}
return $this;
}
public function removeProjectDynamicField(ProjectDynamicField $projectDynamicField): self
{
if ($this->projectDynamicFields->removeElement($projectDynamicField)) {
// set the owning side to null (unless already changed)
if ($projectDynamicField->getProject() === $this) {
$projectDynamicField->setProject(null);
}
}
return $this;
}
public function getProjectHosting(): ?ProjectHosting
{
return $this->projectHosting;
}
public function setProjectHosting(?ProjectHosting $projectHosting): self
{
// unset the owning side of the relation if necessary
if ($projectHosting === null && $this->projectHosting !== null) {
$this->projectHosting->setProject(null);
}
// set the owning side of the relation if necessary
if ($projectHosting !== null && $projectHosting->getProject() !== $this) {
$projectHosting->setProject($this);
}
$this->projectHosting = $projectHosting;
return $this;
}
}