<?php
namespace App\Entity;
use App\Repository\ExpenseRequestRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
#[ORM\Entity(repositoryClass: ExpenseRequestRepository::class)]
#[ORM\HasLifecycleCallbacks]
class ExpenseRequest
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
#[Groups(['LogService'])]
private ?int $id = null;
#[ORM\Column(length: 10, nullable: true)]
#[Groups(['LogService'])]
private ?string $generatedId = null;
#[ORM\Column(length: 255)]
#[Groups(['LogService'])]
private ?string $title = null;
#[ORM\ManyToOne(inversedBy: 'expenseRequests')]
private ?User $requester = null;
#[ORM\Column(length: 255, nullable: true)]
#[Groups(['LogService'])]
private ?string $expenditureType = null;
#[ORM\Column]
private ?\DateTimeImmutable $createdAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $updatedAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $deletedAt = null;
#[ORM\Column(length: 10, nullable: true)]
private ?string $status = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $supplierName = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $supplierUrl = null;
#[ORM\ManyToOne(inversedBy: 'expenseRequests')]
#[Groups(['LogService'])]
private ?Currency $currency = null;
#[ORM\Column(length: 255, nullable: true)]
#[Groups(['LogService'])]
private ?string $amount = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $costJustification = null;
#[ORM\ManyToOne(inversedBy: 'expenseRequests')]
private ?Client $client = null;
#[ORM\ManyToOne(inversedBy: 'expenseRequests')]
private ?Project $project = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $ProjectLink = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $paymentScheduled = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $paymentMethod = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $paymentDate = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $invoiceNo = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $invoiceFile = null;
#[ORM\Column(length: 255, nullable: true)]
#[Groups(['LogService'])]
private ?string $finalStep = null;
#[ORM\ManyToOne(inversedBy: 'expenseRequests')]
private ?Vendor $supplier = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $recurring = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $paymentEndDate = null;
#[ORM\Column(nullable: true)]
#[Groups(['LogService'])]
private ?bool $isApproved = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $draftedAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $submittedAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $approvedAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $rejectedAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $processedAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $archivedAt = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $notes = null;
#[ORM\OneToMany(mappedBy: 'expenseRequest', targetEntity: ExpenseRequestInvoice::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[Groups(['LogService'])]
private Collection $expenseRequestInvoices;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $lastReminder = null;
#[ORM\OneToMany(mappedBy: 'expenseRequest', targetEntity: ExpenseRequestFile::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[Groups(['LogService'])]
private Collection $expenseRequestFiles;
public function __construct()
{
$this->expenseRequestInvoices = new ArrayCollection();
$this->expenseRequestFiles = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getGeneratedId(): ?string
{
return $this->generatedId;
}
public function setGeneratedId(?string $generatedId): self
{
$this->generatedId = $generatedId;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getRequester(): ?User
{
return $this->requester;
}
public function setRequester(?User $requester): self
{
$this->requester = $requester;
return $this;
}
public function getExpenditureType(): ?string
{
return $this->expenditureType;
}
public function setExpenditureType(?string $expenditureType): self
{
$this->expenditureType = $expenditureType;
return $this;
}
#[ORM\PrePersist]
public function setCreatedAtValue(): void
{
$this->createdAt = new \DateTimeImmutable();
}
public function getCreatedAt(): ?\DateTimeImmutable
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeImmutable $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeImmutable
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getDeletedAt(): ?\DateTimeImmutable
{
return $this->deletedAt;
}
public function setDeletedAt(?\DateTimeImmutable $deletedAt): self
{
$this->deletedAt = $deletedAt;
return $this;
}
public function getStatus(): ?string
{
return intval($this->status);
}
public function setStatus(?string $status): self
{
$this->status = $status;
return $this;
}
public function getStatusChoices()
{
$processed = 'processed';
if($this->recurring == NULL){
// if($this->expenseRequestInvoices){
// foreach($this->expenseRequestInvoices as $invoice){
// if($invoice->getXeroStatus()){
// $status = $invoice->getXeroStatus();
// $processed .= ' - [' . substr($status, 0, 1) . ']';
// }
// }
// }
if (count($this->expenseRequestInvoices) > 1) {
$initials = [];
foreach ($this->expenseRequestInvoices as $invoice) {
if ($invoice->getXeroStatus() && $invoice->getXeroStatus() != 'DELETED') {
$initials[] = substr($invoice->getXeroStatus(), 0, 1);
}
}
$processed .= ' - [' . implode(', ', $initials) . ']';
} else {
foreach ($this->expenseRequestInvoices as $invoice) {
if ($invoice->getXeroStatus()) {
$processed .= ' - [' . $invoice->getXeroStatus() . ']';
}
}
}
}
$approvalMade = $this->isIsApproved() == true ? 'Approved' : ($this->isIsApproved() == false ? 'Rejected' : 'Approval Made');
return [
'Draft' => 1,
'Pending Approval' => 2,
$approvalMade => 3,
'Finance to Process' => 4,
$processed => 5,
'Archived' => 6,
];
}
public function getStatusBadgeClass()
{
$status = $this->getStatus();
$isApproved = $this->isIsApproved();
$badge = 'badge badge-secondary';
switch ($status) {
case 1:
$badge = 'badge badge-light';
break;
case 2:
$badge = 'badge badge-warning';
break;
case 3:
if ($isApproved === true) {
$badge = 'badge badge-success';
} elseif ($isApproved === false) {
$badge = 'badge badge-danger';
}
break;
case 4:
$badge = 'badge badge-info';
break;
case 5:
$badge = 'badge badge-primary';
break;
case 6:
$badge = 'badge badge-secondary';
break;
default:
$badge = 'badge badge-secondary';
}
return $badge;
}
public function getStatusText()
{
$status = $this->getStatus();
$isApproved = $this->isIsApproved();
$statuses = array_flip($this->getStatusChoices());
return isset($statuses[$status]) ? $statuses[$status] : null;
}
public function getStatusDesc()
{
$status = $this->getStatus();
$isApproved = $this->isIsApproved();
$desc = '';
switch ($status) {
case 1:
$desc = 'User started completing the Expense request form but did not submit it for approval.';
break;
case 2:
$desc = 'User completed the Expense request form and it is now pending management approval.';
break;
case 3:
if ($isApproved === true) {
$desc = 'Management approved the Expense request form. Requester needs to upload the Invoice and submit it to finance. It will be automatically saved as Draft in Xero.';
} elseif ($isApproved === false) {
$desc = 'Management rejected the Expense request form.';
}
break;
case 4:
$desc = 'Finance needs to approve the invoice in Xero and ask Requester to input the invoice in the Vendor planning section of HRP’s project.';
break;
case 5:
$desc = 'Finance has processed the payment or reimbursement of the invoice. Other invoices can be added to the project (especially for projects with recurring invoices). Expense request ID form is still active.';
break;
case 6:
$desc = 'Finance has processed the payment or reimbursement of the invoice(s) and consider the Expense request ID form terminated.';
break;
default:
$desc = '';
}
return $desc;
}
public function getSupplierName(): ?string
{
return $this->supplierName;
}
public function setSupplierName(?string $supplierName): self
{
$this->supplierName = $supplierName;
return $this;
}
public function getSupplierUrl(): ?string
{
return $this->supplierUrl;
}
public function setSupplierUrl(?string $supplierUrl): self
{
$this->supplierUrl = $supplierUrl;
return $this;
}
public function getCurrency(): ?Currency
{
return $this->currency;
}
public function setCurrency(?Currency $currency): self
{
$this->currency = $currency;
return $this;
}
public function getAmount(): ?string
{
return $this->amount;
}
public function getAmountUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$amountUsd = $currencyService->convertAtDate($this->createdAt, $this->currency->getIso(), 'USD', $this->amount);
return round($amountUsd, 2, PHP_ROUND_HALF_EVEN);
}
public function setAmount(?string $amount): self
{
$this->amount = $amount;
return $this;
}
public function getSpentAmount(){
$result = 0;
if($this->expenseRequestInvoices){
foreach( $this->expenseRequestInvoices as $invoice){
$result += floatval($invoice->getTotalAmount());
}
}
return $result;
}
public function getSpentAmountUsd()
{
global $kernel;
$currencyService = $kernel->getContainer()->get('CurrencyService');
$spentAmountUsd = 0;
if ($this->expenseRequestInvoices) {
foreach ($this->expenseRequestInvoices as $invoice) {
$invoiceAmount = floatval($invoice->getTotalAmount());
$invoiceCurrency = $invoice->getCurrency() ? $invoice->getCurrency()->getIso() : 'USD';
$invoiceDate = $invoice->getCreatedAt();
$convertedAmount = $currencyService->convertAtDate($invoiceDate, $invoiceCurrency, 'USD', $invoiceAmount);
$spentAmountUsd += floatval($convertedAmount);
}
}
return $spentAmountUsd;
}
public function getInvoicesCurrency()
{
$currency = 'USD';
if ($this->expenseRequestInvoices) {
foreach ($this->expenseRequestInvoices as $invoice) {
$currency = $invoice->getCurrency() ? $invoice->getCurrency()->getIso() : 'USD';
}
}
return $currency;
}
public function getCostJustification(): ?string
{
return $this->costJustification;
}
public function setCostJustification(?string $costJustification): self
{
$this->costJustification = $costJustification;
return $this;
}
public function getClient(): ?Client
{
return $this->client;
}
public function setClient(?Client $client): self
{
$this->client = $client;
return $this;
}
public function getProject(): ?Project
{
return $this->project;
}
public function setProject(?Project $project): self
{
$this->project = $project;
return $this;
}
public function getProjectLink(): ?string
{
return $this->ProjectLink;
}
public function setProjectLink(?string $ProjectLink): self
{
$this->ProjectLink = $ProjectLink;
return $this;
}
public function getPaymentScheduled(): ?\DateTimeImmutable
{
return $this->paymentScheduled;
}
public function setPaymentScheduled(?\DateTimeImmutable $paymentScheduled): self
{
$this->paymentScheduled = $paymentScheduled;
return $this;
}
public function getPaymentMethod(): ?string
{
return $this->paymentMethod;
}
public function setPaymentMethod(?string $paymentMethod): self
{
$this->paymentMethod = $paymentMethod;
return $this;
}
public function getPaymentDate(): ?\DateTimeImmutable
{
return $this->paymentDate;
}
public function setPaymentDate(?\DateTimeImmutable $paymentDate): self
{
$this->paymentDate = $paymentDate;
return $this;
}
public function getInvoiceNo(): ?string
{
return $this->invoiceNo;
}
public function setInvoiceNo(?string $invoiceNo): self
{
$this->invoiceNo = $invoiceNo;
return $this;
}
public function getInvoiceFile(): ?string
{
return $this->invoiceFile;
}
public function setInvoiceFile(?string $invoiceFile): self
{
$this->invoiceFile = $invoiceFile;
return $this;
}
public function getFinalStep(): ?string
{
return $this->finalStep;
}
public function setFinalStep(?string $finalStep): self
{
$this->finalStep = $finalStep;
return $this;
}
public function getSupplier(): ?Vendor
{
return $this->supplier;
}
public function setSupplier(?Vendor $supplier): self
{
$this->supplier = $supplier;
return $this;
}
public function getRecurring(): ?string
{
return $this->recurring;
}
public function isRecurring(): ?bool
{
return !empty($this->recurring) ? true : false;
}
public function setRecurring(?string $recurring): self
{
$this->recurring = $recurring;
return $this;
}
public function getPaymentEndDate(): ?\DateTimeImmutable
{
return $this->paymentEndDate;
}
public function setPaymentEndDate(?\DateTimeImmutable $paymentEndDate): self
{
$this->paymentEndDate = $paymentEndDate;
return $this;
}
public function isIsApproved(): ?bool
{
return $this->isApproved;
}
public function setIsApproved(?bool $isApproved): self
{
$this->isApproved = $isApproved;
return $this;
}
public function getDraftedAt(): ?\DateTimeImmutable
{
return $this->draftedAt;
}
public function setDraftedAt(?\DateTimeImmutable $draftedAt): self
{
$this->draftedAt = $draftedAt;
return $this;
}
public function getSubmittedAt(): ?\DateTimeImmutable
{
return $this->submittedAt;
}
public function setSubmittedAt(?\DateTimeImmutable $submittedAt): self
{
$this->submittedAt = $submittedAt;
return $this;
}
public function getApprovedAt(): ?\DateTimeImmutable
{
return $this->approvedAt;
}
public function setApprovedAt(?\DateTimeImmutable $approvedAt): self
{
$this->approvedAt = $approvedAt;
return $this;
}
public function getRejectedAt(): ?\DateTimeImmutable
{
return $this->rejectedAt;
}
public function setRejectedAt(?\DateTimeImmutable $rejectedAt): self
{
$this->rejectedAt = $rejectedAt;
return $this;
}
public function getProcessedAt(): ?\DateTimeImmutable
{
return $this->processedAt;
}
public function setProcessedAt(?\DateTimeImmutable $processedAt): self
{
$this->processedAt = $processedAt;
return $this;
}
public function getArchivedAt(): ?\DateTimeImmutable
{
return $this->archivedAt;
}
public function setArchivedAt(?\DateTimeImmutable $archivedAt): self
{
$this->archivedAt = $archivedAt;
return $this;
}
public function getNotes(): ?string
{
return $this->notes;
}
public function setNotes(?string $notes): self
{
$this->notes = $notes;
return $this;
}
/**
* @return Collection<int, ExpenseRequestInvoice>
*/
public function getExpenseRequestInvoices(): Collection
{
return $this->expenseRequestInvoices;
}
public function getExpenseRequestInvoiceByInvNo(string $invoiceNo): ?ExpenseRequestInvoice
{
foreach ($this->expenseRequestInvoices as $file) {
if ($file->getInvoiceNo() === $invoiceNo) {
return $file;
}
}
return null;
}
public function addExpenseRequestInvoice(ExpenseRequestInvoice $expenseRequestInvoice): self
{
if (!$this->expenseRequestInvoices->contains($expenseRequestInvoice)) {
$this->expenseRequestInvoices->add($expenseRequestInvoice);
$expenseRequestInvoice->setExpenseRequest($this);
}
return $this;
}
public function removeExpenseRequestInvoice(ExpenseRequestInvoice $expenseRequestInvoice): self
{
if ($this->expenseRequestInvoices->removeElement($expenseRequestInvoice)) {
// set the owning side to null (unless already changed)
if ($expenseRequestInvoice->getExpenseRequest() === $this) {
$expenseRequestInvoice->setExpenseRequest(null);
}
}
return $this;
}
public function getLastReminder(): ?\DateTimeImmutable
{
return $this->lastReminder;
}
public function setLastReminder(?\DateTimeImmutable $lastReminder): self
{
$this->lastReminder = $lastReminder;
return $this;
}
public function isProcessed(){
if($this->expenseRequestInvoices->count() > 0){
foreach($this->expenseRequestInvoices as $expenseInv){
if($expenseInv->getProcessedAt() == null){
return false;
}
}
return true;
}
}
public function checkInvoices(){
if($this->expenseRequestInvoices->count() > 0){
foreach($this->expenseRequestInvoices as $expenseInv){
if(empty($expenseInv->getInvoiceFile())){
return false;
}
}
return true;
}
}
/**
* @return Collection<int, ExpenseRequestFile>
*/
public function getExpenseRequestFiles(): Collection
{
return $this->expenseRequestFiles;
}
public function getExpenseRequestFileByUuid(string $uuid): ?ExpenseRequestFile
{
foreach ($this->expenseRequestFiles as $file) {
if ($file->getUuid() === $uuid) {
return $file;
}
}
return null;
}
public function addExpenseRequestFile(ExpenseRequestFile $expenseRequestFile): self
{
if (!$this->expenseRequestFiles->contains($expenseRequestFile)) {
$this->expenseRequestFiles->add($expenseRequestFile);
$expenseRequestFile->setExpenseRequest($this);
}
return $this;
}
public function removeExpenseRequestFile(ExpenseRequestFile $expenseRequestFile): self
{
if ($this->expenseRequestFiles->removeElement($expenseRequestFile)) {
// set the owning side to null (unless already changed)
if ($expenseRequestFile->getExpenseRequest() === $this) {
$expenseRequestFile->setExpenseRequest(null);
}
}
return $this;
}
}