Merge branch 'master' of gitlab.com:jankstudio/resq

This commit is contained in:
Ramon Gutierrez 2018-02-01 04:18:34 +08:00
commit 1efd5250e8
5 changed files with 410 additions and 1 deletions

View file

@ -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)
* @Assert\NotBlank()

View file

@ -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;
}
}

100
src/Entity/InvoiceItem.php Normal file
View file

@ -0,0 +1,100 @@
<?php
namespace App;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="invoice_item")
*/
class InvoiceItem
{
// unique id
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// invoice the item is linked to
/**
* @ORM\ManyToOne(targetEntity="Invoice", inversedBy="items")
* @ORM\JoinColumn(name="invoice_id", referencedColumnName="id")
*/
protected $invoice;
// title of item
/**
* @ORM\Column(type="string", length=80)
*/
protected $title;
// quantity
/**
* @ORM\Column(type="smallint")
*/
protected $qty;
// price of item, negative for discounts
/**
* @ORM\Column(type="decimal", precision=9, scale=2)
*/
protected $price;
public function __construct()
{
$this->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;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Ramcar;
use App\Entity\Battery;
class InvoiceCriteria
{
protected $batteries;
protected $promos;
protected $trade_in;
public function __construct()
{
$this->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;
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace App\Service;
use App\Ramcar\InvoiceCriteria;
use App\Entity\Invoice;
use App\Entity\InvoiceItem;
use App\Entity\User;
class InvoiceCreator
{
const VAT_RATE = 0.12;
const TIRATE_MOTOLITE = 300.00;
const TIRATE_OTHER = 150.00;
// creates invoice based on the criteria sent
public function __construct()
{
}
public function getVATAmount($price)
{
$vat_ex_price = $this->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;
}
}