From 04cd0c59eb15b7da92b4f81c3fe97337861f8e3e Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Thu, 1 Feb 2018 01:35:47 +0800 Subject: [PATCH 1/2] Add initial invoice capability --- src/Entity/Battery.php | 2 +- src/Entity/Invoice.php | 158 +++++++++++++++++++++++++++++++++ src/Entity/InvoiceItem.php | 100 +++++++++++++++++++++ src/Ramcar/InvoiceCriteria.php | 60 +++++++++++++ src/Service/InvoiceCreator.php | 91 +++++++++++++++++++ 5 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 src/Entity/InvoiceItem.php create mode 100644 src/Ramcar/InvoiceCriteria.php create mode 100644 src/Service/InvoiceCreator.php diff --git a/src/Entity/Battery.php b/src/Entity/Battery.php index 87ed9666..8af81bcc 100644 --- a/src/Entity/Battery.php +++ b/src/Entity/Battery.php @@ -115,7 +115,7 @@ class Battery */ protected $total_height; - // selling price + // selling price (vat inclusive) /** * @ORM\Column(type="decimal", precision=7, scale=2, nullable=true) */ diff --git a/src/Entity/Invoice.php b/src/Entity/Invoice.php index c34f1c10..e28a8f77 100644 --- a/src/Entity/Invoice.php +++ b/src/Entity/Invoice.php @@ -3,8 +3,13 @@ namespace App; use Doctrine\ORM\Mapping as ORM; +use Doctrine\Common\Collections\ArrayCollection; use DateTime; +/** + * @ORM\Entity + * @ORM\Table(name="invoice") + */ class Invoice { // unique id @@ -40,9 +45,162 @@ class Invoice */ protected $created_by; + // the job order the invoice was created from + /** + * @ORM\ManyToOne(targetEntity="JobOrder", inversedBy="invoice") + * @ORM\JoinColumn(name="job_order_id", referencedColumnName="id") + */ + protected $job_order; + // invoice items + /** + * @ORM\OneToMany(targetEntity="InvoiceItem", mappedBy="invoice") + */ protected $invoice_items; + // total discount (amount, not %) + /** + * @ORM\Column(type="decimal", precision=9, scale=2) + */ + protected $discount; + + // total vat (amount, not %) + /** + * @ORM\Column(type="decimal", precision=9, scale=2) + */ + protected $vat; + + // total price (amount) + /** + * @ORM\Column(type="decimal", precision=9, scale=2) + */ + protected $total_price; + // status + /** + * @ORM\Column(type="string", length=40) + */ protected $status; + + public function __construct() + { + $this->date_create = new DateTime(); + $this->invoice_items = new ArrayCollection(); + } + + public function getID() + { + return $this->id; + } + + public function getDateCreate() + { + return $this->date_create; + } + + public function setDatePaid(DateTime $date) + { + $this->date_paid = $date; + return $this; + } + + public function getDatePaid() + { + return $this->date_paid; + } + + public function setDateCancel(DateTime $date) + { + $this->date_cancel = $date; + return $this; + } + + public function getDateCancel() + { + return $this->date_cancel; + } + + public function setCreatedBy(User $user) + { + $this->created_by = $user; + return $this; + } + + public function getCreatedBy() + { + return $this->created_by; + } + + public function setJobOrder(JobOrder $job_order) + { + $this->job_order = $job_order; + return $this; + } + + public function getJobOrder() + { + return $this->job_order; + } + + public function addItem(InvoiceItem $item) + { + $this->invoice_items->add($item); + $item->setInvoice($this); + return $this; + } + + public function clearItems() + { + $this->invoice_items->clear(); + return $this; + } + + public function getItems() + { + return $this->invoice_items; + } + + public function setDiscount($discount) + { + $this->discount = $discount; + return $this; + } + + public function getDiscount() + { + return $this->discount; + } + + public function setVAT($vat) + { + $this->vat = $vat; + return $this; + } + + public function getVAT() + { + return $this->vat; + } + + public function setTotalPrice($price) + { + $this->total_price = $price; + return $this; + } + + public function getTotalPrice() + { + return $this->total_price; + } + + public function setStatus($status) + { + $this->status = $status; + return $this; + } + + public function getStatus() + { + return $this->status; + } } diff --git a/src/Entity/InvoiceItem.php b/src/Entity/InvoiceItem.php new file mode 100644 index 00000000..31fb887e --- /dev/null +++ b/src/Entity/InvoiceItem.php @@ -0,0 +1,100 @@ +title = ''; + $this->price = 0.0; + } + + public function getID() + { + return $this->id; + } + + public function setInvoice(Invoice $invoice) + { + $this->invoice = $invoice; + return $this; + } + + public function getInvoice() + { + return $this->invoice; + } + + public function setTitle($title) + { + $this->title = $title; + return $this; + } + + public function getTitle() + { + return $this->title; + } + + public function setQuantity($qty) + { + $this->qty = $qty; + return $this; + } + + public function getQuantity() + { + return $this->qty; + } + + public function setPrice($price) + { + $this->price = $price; + return $this; + } + + public function getPrice() + { + return $this->price; + } +} diff --git a/src/Ramcar/InvoiceCriteria.php b/src/Ramcar/InvoiceCriteria.php new file mode 100644 index 00000000..11b1b926 --- /dev/null +++ b/src/Ramcar/InvoiceCriteria.php @@ -0,0 +1,60 @@ +batteries = []; + $this->promos = []; + $this->trade_ins = []; + } + + public function addBattery(Battery $battery) + { + $this->batteries[] = $battery; + return $this; + } + + public function getBatteries() + { + return $this->batteries; + } + + public function addPromo($promo) + { + $this->promos[] = $promo; + return $this; + } + + public function getPromos() + { + return $this->promos; + } + + public function addTradeIn($is_motolite) + { + // NOTE: this asumes that all the rates for trade-ins are standardized + // for motolite and non-motolite trade-ins + + if ($is_motolite) + $trade_in = 'motolite'; + else + $trade_in = 'other'; + + $this->trade_ins[] = $trade_in; + return $this; + } + + public function getTradeIns() + { + return $this->trade_ins; + } +} diff --git a/src/Service/InvoiceCreator.php b/src/Service/InvoiceCreator.php new file mode 100644 index 00000000..b31dad70 --- /dev/null +++ b/src/Service/InvoiceCreator.php @@ -0,0 +1,91 @@ +getVATExclusivePrice($price); + return round($vat_ex_price * self::VAT_RATE, 2); + } + + public function getVATExclusivePrice($price) + { + return round($price / (1 + self::VAT_RATE), 2); + } + + public function getTradeInRate($trade_in) + { + if ($trade_in == 'motolite') + return TIRATE_MOTOLITE; + + return TIRATE_OTHER; + } + + public function processCriteria(InvoiceCriteria $criteria) + { + $invoice = new Invoice(); + + $total = [ + 'sell_price' => 0.0, + 'vat' => 0.0, + 'vat_ex_price' => 0.0, + + 'ti_rate' => 0.0, + + 'total_price' => 0.0, + ]; + + // get batteries + $batts = $criteria->getBatteries(); + foreach ($batts as $batt) + { + $sell_price = $batt->getSellingPrice() + $vat = $this->getVATAmount($sell_price); + $vat_ex_price = $this->getVATExclusivePrice($sell_price); + + $total['sell_price'] += $sell_price; + $total['vat'] += $vat; + $total['vat_ex_price'] += $vat_ex_price; + + $total['total_price'] += $sell_price; + } + + // get trade-ins + $trade_ins = $criteria->getTradeIns(); + foreach ($trade_ins as $ti) + { + $ti_rate = $this->getTradeInRate($ti); + + $total['ti_rate'] += $ti_rate; + + $total['total_price'] -= $ti_rate; + } + + // TODO: check if any promo is applied + // apply discounts + $promos = $criteria->getPromos(); + + $invoice->setTotalPrice($total['total_price']) + ->setVAT($total['vat']) + ->setDiscount($total['ti_rate']); + + return $invoice; + } +} From b6ce9d8ad8f5147ae578ab4a02f8caf54fcb4a47 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Thu, 1 Feb 2018 03:00:17 +0800 Subject: [PATCH 2/2] Fix missing semicolon --- src/Service/InvoiceCreator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/InvoiceCreator.php b/src/Service/InvoiceCreator.php index b31dad70..3c3c3e1f 100644 --- a/src/Service/InvoiceCreator.php +++ b/src/Service/InvoiceCreator.php @@ -56,7 +56,7 @@ class InvoiceCreator $batts = $criteria->getBatteries(); foreach ($batts as $batt) { - $sell_price = $batt->getSellingPrice() + $sell_price = $batt->getSellingPrice(); $vat = $this->getVATAmount($sell_price); $vat_ex_price = $this->getVATExclusivePrice($sell_price);