<?php
namespace MedBrief\MSR\Entity;
use DH\Auditor\Provider\Doctrine\Auditing\Annotation as Audit;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use MedBrief\MSR\Repository\InvoiceRepository;
/**
* Represents an Invoice.
*
* Invoice can contain multiple invoiceItems.
*
* @ORM\Table(name="Invoice")
*
* @ORM\Entity(repositoryClass=InvoiceRepository::class)
*
* @Audit\Auditable
*
* @Audit\Security(view={"ROLE_ALLOWED_TO_AUDIT"})
*/
class Invoice
{
// Status constants
public const STATUS_AWAITING_PAYMENT = 1; // Not used
public const STATUS_PAID = 2; // Not used
public const STATUS_CANCELLED = 3; // Not used
public const STATUS_DRAFT = 4;
public const STATUS_SUBMITTED = 5;
// Currently only support one currency for invoices.
public const DEFAULT_CURRENCY = 'GBP';
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
*
* @ORM\Id
*
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @var string|null
*
* @ORM\Column(name="referenceId", type="string", nullable=true)
*/
protected $referenceId;
/**
* @var \DateTime|null
*
* @ORM\Column(name="invoiceDate", type="date", nullable=true)
*/
protected $invoiceDate;
/**
* @var int|null
*
* @ORM\Column(name="status", type="integer", nullable=true)
*/
protected $status;
/**
* @var \DateTime|null
*
* @ORM\Column(name="dueDate", type="date", nullable=true)
*/
protected $dueDate;
/**
* The InvoiceItems associated with this Invoice.
*
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="MedBrief\MSR\Entity\InvoiceItem", mappedBy="invoice", cascade={"persist","remove"}, orphanRemoval=true)
*/
protected $items;
/**
* Guid provided by accounting system.
*
* @var string|null
*
* @ORM\Column(name="guid", type="string", nullable=true)
*/
protected $guid;
/**
* The date the invoice was last synced to Xero.
*
* @var \DateTime|null
*
* @ORM\Column(name="syncDate", type="datetime", nullable=true)
*/
protected $syncDate;
/**
* Maintains an identifier for the invoice to the Project it belongs to,
* event after the Project gets deleted.
*
* @var string|null
*
* @ORM\Column(name="projectReferenceNumber", type="string", nullable=true)
*/
protected $projectReferenceNumber;
/**
* Maintains an identifier for the invoice to the Project it belongs to,
* event after the Project gets deleted.
*
* @var int|null
*
* @ORM\Column(name="projectId", type="integer", nullable=true)
*/
protected $projectId;
/**
* @var \DateTime
*
* @ORM\Column(name="created", type="datetime")
*
* @Gedmo\Timestampable(on="create")
*/
protected $created;
/**
* @var \DateTime
*
* @ORM\Column(name="updated", type="datetime")
*
* @Gedmo\Timestampable(on="update")
*/
protected $updated;
/**
* The ID of the associated Account
*
* @var int|null
*
* @ORM\Column(name="accountId", type="integer", nullable=true)
*/
protected $accountId;
/**
* Constructor
*/
public function __construct()
{
// Initialise ArrayCollections
$this->items = new ArrayCollection();
// Assign default dates
$this->invoiceDate = new \DateTime();
$this->dueDate = new \DateTime();
// Set the default status to Draft
$this->status = self::STATUS_DRAFT;
}
/**
* __toString
*
* @return string
*/
public function __toString()
{
return (string) $this->getReferenceId();
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set referenceId
*
* @param string $referenceId
*
* @return Invoice
*/
public function setReferenceId($referenceId)
{
$this->referenceId = $referenceId;
return $this;
}
/**
* Get referenceId
*
* @return string
*/
public function getReferenceId()
{
return $this->referenceId;
}
/**
* Set created
*
* @param \DateTime $created
*
* @return Invoice
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* @param \DateTime $updated
*
* @return Invoice
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* @return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Add item
*
* @param InvoiceItem $item
*
* @return Invoice
*/
public function addItem(InvoiceItem $item)
{
$this->items[] = $item;
return $this;
}
/**
* Remove item
*
* @param InvoiceItem $item
*/
public function removeItem(InvoiceItem $item)
{
$this->items->removeElement($item);
}
/**
* Get items
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getItems()
{
return $this->items;
}
/**
* Set invoiceDate
*
* @param \DateTime $invoiceDate
*
* @return Invoice
*/
public function setInvoiceDate($invoiceDate)
{
$this->invoiceDate = $invoiceDate;
return $this;
}
/**
* Get invoiceDate
*
* @return \DateTime
*/
public function getInvoiceDate()
{
return $this->invoiceDate;
}
/**
* Set dueDate
*
* @param \DateTime $dueDate
*
* @return Invoice
*/
public function setDueDate($dueDate)
{
$this->dueDate = $dueDate;
return $this;
}
/**
* Get dueDate
*
* @return \DateTime
*/
public function getDueDate()
{
return $this->dueDate;
}
/**
* Calculates the total value of the invoice.
*
* @return float
*/
public function getTotal()
{
return $this->getTotalExclVat() + $this->getVat();
}
/**
* Calculates the total VAT of the invoice,
* by reducing all the items associated with the Invoice
* to a value by aggregating their individual VAT totals.
*
* @return float
*/
public function getVat()
{
return array_reduce($this->getItems()->toArray(), function ($vat, InvoiceItem $item) {
return $vat += $item->getVat();
});
}
/**
* Calculates the total excl VAT of the invoice,
* by reducing all the items associated with the Invoice
* to a value by aggregating their individual VAT exclusive totals.
*
* @return float
*/
public function getTotalExclVat()
{
return array_reduce($this->getItems()->toArray(), function ($totalExclVat, InvoiceItem $item) {
return $totalExclVat += $item->getTotalExclVat();
});
}
/**
* Set status
*
* @param int $status
*
* @return Invoice
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* @return int
*/
public function getStatus()
{
return $this->status;
}
/**
* Get getStatusOptions
*
* @return array
*/
public static function getStatusOptions()
{
return [
self::STATUS_DRAFT => 'Draft',
self::STATUS_AWAITING_PAYMENT => 'Awaiting Payment',
self::STATUS_PAID => 'Paid',
self::STATUS_CANCELLED => 'Cancelled',
self::STATUS_SUBMITTED => 'Submitted',
];
}
/**
* These statuses indicate that the ServiceRequests that
* belong to these invoices don't need to be invoiced for.
*
* @return array
*/
public static function getBilledStatuses()
{
return [
self::STATUS_AWAITING_PAYMENT,
self::STATUS_PAID,
self::STATUS_SUBMITTED,
];
}
/**
* Convenience method to determine if the Invoice is in a billed
* status.
*
* @return void
*/
public function isBilledStatus()
{
return in_array($this->getStatus(), self::getBilledStatuses());
}
/**
* Get getStatusLabel
*
* @return int
*/
public function getStatusLabel()
{
$options = self::getStatusOptions();
// For the default label, we use STATUS_AWAITING_PAYMENT
return $options[$this->getStatus()] ?? $options[self::STATUS_AWAITING_PAYMENT];
}
/**
* Convenience function to determine if the Invoice has been paid.
*
* @return bool
*/
public function isPaid()
{
return $this->getStatus() === self::STATUS_PAID;
}
/**
* Convenience function to determine if the Invoice has been cancelled.
*
* @return bool
*/
public function isCancelled()
{
return $this->getStatus() === self::STATUS_CANCELLED;
}
/**
* Convenience function to determine if the Invoice is awaiting payment.
*
* @return bool
*/
public function isAwaitingPayment()
{
return $this->getStatus() === self::STATUS_AWAITING_PAYMENT;
}
/**
* Convenience function to determine if the Invoice is submitted.
*
* @return bool
*/
public function isSubmitted()
{
return $this->getStatus() === self::STATUS_SUBMITTED;
}
/**
* Convenience function to determine if the Invoice is draft.
*
* @return bool
*/
public function isDraft()
{
return $this->getStatus() === self::STATUS_DRAFT;
}
/**
* Set guid
*
* @param string $guid
*
* @return Invoice
*/
public function setGuid($guid)
{
$this->guid = $guid;
return $this;
}
/**
* Get guid
*
* @return string
*/
public function getGuid()
{
return $this->guid;
}
/**
* Set syncDate
*
* @param \DateTime $syncDate
*
* @return Invoice
*/
public function setSyncDate($syncDate)
{
$this->syncDate = $syncDate;
return $this;
}
/**
* Get syncDate
*
* @return \DateTime
*/
public function getSyncDate()
{
return $this->syncDate;
}
/**
* Set projectReferenceNumber
*
* @param string $projectReferenceNumber
*
* @return Invoice
*/
public function setProjectReferenceNumber($projectReferenceNumber)
{
$this->projectReferenceNumber = $projectReferenceNumber;
return $this;
}
/**
* Get projectReferenceNumber
*
* @return string
*/
public function getProjectReferenceNumber()
{
return $this->projectReferenceNumber;
}
/**
* Set projectId
*
* @param int $projectId
*
* @return Invoice
*/
public function setProjectId($projectId)
{
$this->projectId = $projectId;
return $this;
}
/**
* Get projectId
*
* @return int
*/
public function getProjectId()
{
return $this->projectId;
}
/**
* Set accountId
*
* @param int $accountId
*
* @return Invoice
*/
public function setAccountId($accountId)
{
$this->accountId = $accountId;
return $this;
}
/**
* Get accountId
*
* @return int
*/
public function getAccountId()
{
return $this->accountId;
}
}