Modify the invoice manager to be more generic. #744

This commit is contained in:
Korina Cordero 2023-07-04 06:05:34 -04:00
parent 783c26facc
commit b4bcc06e42
20 changed files with 744 additions and 910 deletions

View file

@ -45,6 +45,7 @@ class TestInvoiceManagerCommand extends Command
$this->testBatterySalesNoTradeInNoDiscountWithTax();
$this->testBatterySalesQuantityNoTradeInNoDiscountWithTax();
/*
// battery sales without tax
$this->testBatterySalesNoTradeInNoDiscountWithoutTax();
$this->testBatterySalesQuantityNoTradeInNoDiscountWithoutTax();
@ -153,7 +154,7 @@ class TestInvoiceManagerCommand extends Command
$this->testGenerateDraftInvoiceBatterySalesNoPromo();
// test generateInvoiceInvoice call from ajax call
$this->testGenerateInvoice();
$this->testGenerateInvoice(); */
return 0;
}
@ -172,11 +173,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addEntry($battery, null, 1);
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -207,11 +204,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addEntry($battery, null, 2);
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -242,11 +235,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addEntry($battery, null, 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -276,11 +265,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addEntry($battery, null, 2);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -316,11 +301,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addEntry($battery, 'premium', 1);
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -354,11 +335,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -392,11 +369,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -433,11 +406,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -474,11 +443,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -515,11 +480,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -556,11 +517,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -593,11 +550,7 @@ class TestInvoiceManagerCommand extends Command
// add battery for trade in
$criteria->addEntry($battery, 'premium', 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -629,11 +582,7 @@ class TestInvoiceManagerCommand extends Command
// add battery for trade in
$criteria->addEntry($battery, 'motolite', 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -665,11 +614,7 @@ class TestInvoiceManagerCommand extends Command
// add battery for trade in
$criteria->addEntry($battery, 'other', 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -704,11 +649,7 @@ class TestInvoiceManagerCommand extends Command
// add battery for trade in
$criteria->addEntry($trade_battery, 'premium', 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -743,11 +684,7 @@ class TestInvoiceManagerCommand extends Command
// add battery for trade in
$criteria->addEntry($trade_battery, 'motolite', 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -782,11 +719,7 @@ class TestInvoiceManagerCommand extends Command
// add battery for trade in
$criteria->addEntry($trade_battery, 'other', 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -821,11 +754,7 @@ class TestInvoiceManagerCommand extends Command
// add battery for trade in
$criteria->addEntry($trade_battery, 'other', 3);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -861,11 +790,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -904,11 +829,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addPromo($promo);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -952,11 +873,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -1003,11 +920,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1044,11 +957,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addPromo($promo);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
// error_log(print_r(json_encode($invoice_data), true));
@ -1093,11 +1002,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addPromo($promo);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1128,11 +1033,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1161,11 +1062,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->addEntry($battery, null, 1);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1197,11 +1094,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1232,11 +1125,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1267,11 +1156,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1302,11 +1187,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1336,11 +1217,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1369,11 +1246,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1402,11 +1275,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1435,11 +1304,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1465,11 +1330,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1493,11 +1354,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setServiceType(ServiceType::JUMPSTART_TROUBLESHOOT);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1523,11 +1380,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1551,11 +1404,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setServiceType(ServiceType::JUMPSTART_WARRANTY);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1587,11 +1436,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setHasCoolant();
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1621,11 +1466,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1656,11 +1497,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$criteria->setHasCoolant();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1689,11 +1526,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1719,11 +1552,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1747,11 +1576,7 @@ class TestInvoiceManagerCommand extends Command
// TEST SCENARIO: post recharged with tax
$criteria->setServiceType(ServiceType::POST_RECHARGED);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1777,11 +1602,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1807,11 +1628,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1843,11 +1660,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1878,11 +1691,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setIsTaxable();
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1912,11 +1721,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{
@ -1945,11 +1750,7 @@ class TestInvoiceManagerCommand extends Command
$criteria->setCustomerVehicle($cv);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_data = $this->inv_manager->compute($criteria, $rules);
$invoice_data = $this->inv_manager->compute($criteria);
foreach ($invoice_data as $data)
{

View file

@ -1,67 +0,0 @@
<?php
namespace App\Invoice;
use App\InvoiceInterface;
class BatteryReplacementWarranty implements InvoiceInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
return 'invoice/battery.html.twig';
}
public function getID()
{
return 'battery_warranty';
}
public function compute($criteria, $stype_fees, &$total)
{
$stype = $criteria->getServiceType();
$items = [];
if ($stype == $this->getID())
{
// get the entries
$entries = $criteria->getEntries();
$stype_fee_id = $this->getID() . '_fee';
foreach($entries as $entry)
{
$batt = $entry['battery'];
$qty = 1;
$price = $stype_fees[$stype_fee_id];
$items[] = [
'service_type' => $this->getID(),
'battery' => $batt,
'qty' => $qty,
'title' => $this->getTitle($batt),
'price' => $price,
];
$qty_price = bcmul($price, $qty, 2);
$total['total_price'] = bcadd($total['total_price'], $qty_price, 2);
}
}
return $items;
}
protected function getTitle($battery)
{
$title = $battery->getModel()->getName() . ' ' . $battery->getSize()->getName() . ' - Service Unit';
return $title;
}
}

View file

@ -1,77 +0,0 @@
<?php
namespace App\Invoice;
use App\InvoiceInterface;
class BatterySales implements InvoiceInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
return 'invoice/battery.html.twig';
}
public function getID()
{
return 'battery_new';
}
public function compute($criteria, $stype_fees, &$total)
{
$stype = $criteria->getServiceType();
$items = [];
if ($stype == $this->getID())
{
// get the entries
$entries = $criteria->getEntries();
foreach($entries as $entry)
{
$batt = $entry['battery'];
$qty = $entry['qty'];
$trade_in = null;
if (isset($entry['trade_in']))
$trade_in = $entry['trade_in'];
$size = $batt->getSize();
if ($trade_in == null)
{
// battery purchase
$price = $batt->getSellingPrice();
$items[] = [
'service_type' => $this->getID(),
'battery' => $batt,
'qty' => $qty,
'title' => $this->getTitle($batt),
'price' => $price,
];
$qty_price = bcmul($price, $qty, 2);
$total['sell_price'] = bcadd($total['sell_price'], $qty_price, 2);
$total['total_price'] = bcadd($total['total_price'], $qty_price, 2);
}
}
}
return $items;
}
protected function getTitle($battery)
{
$title = $battery->getModel()->getName() . ' ' . $battery->getSize()->getName();
return $title;
}
}

View file

@ -1,30 +0,0 @@
<?php
namespace App\Invoice;
use App\InvoiceInterface;
class ServiceType implements InvoiceInterface
{
public function check($criteria)
{
if ($criteria->getServiceType() != null)
return true;
return false;
}
public function getTemplate()
{
return 'invoice/service_type.html.twig';
}
public function getID()
{
return 'service_type';
}
public function compute($criteria, $stype_fees)
{
}
}

View file

@ -1,91 +0,0 @@
<?php
namespace App\Invoice;
use App\InvoiceInterface;
class Tax implements InvoiceInterface
{
public function check($criteria)
{
if (!empty($criteria->isTaxable()))
return true;
return false;
}
public function getTemplate()
{
return 'invoice/tax.html.twig';
}
public function getID()
{
return 'tax';
}
public function compute($tax_rate, $items, &$total)
{
$is_battery_sales = false;
$total_price = 0;
foreach ($items as $item)
{
$price = $item['price'];
$qty = $item['qty'];
if (isset($item['service_type']))
{
// battery sales is a special case since vat is computed per battery
if ($item['service_type'] == 'battery_new')
{
$is_battery_sales = true;
// battery purchase
if (isset($item['battery']))
{
// battery purchase
$vat = $this->getTaxAmount($price, $tax_rate);
$qty_price = bcmul($price, $qty, 2);
$qty_vat = bcmul($vat, $qty, 2);
$price_minus_vat = bcsub($price, $vat, 2);
$qty_price_minus_vat = bcmul($price_minus_vat, $qty, 2);
$total['vat'] = bcadd($total['vat'], $qty_vat, 2);
$total['vat_ex_price'] = bcadd($total['vat_ex_price'], $qty_price_minus_vat, 2);
}
}
}
}
// compute VAT after adding all item costs, if service type is not battery sales
if (!$is_battery_sales)
{
$total_price = $total['total_price'];
$vat_ex_price = $this->getTaxExclusivePrice($total_price, $tax_rate);
$vat = bcsub($total_price, $vat_ex_price, 2);
$total['vat_ex_price'] = $vat_ex_price;
$total['vat'] = $vat;
}
}
protected function getTaxAmount($price, $tax_rate)
{
$vat_ex_price = $this->getTaxExclusivePrice($price, $tax_rate);
$tax_amount = bcsub($price, $vat_ex_price, 2);
return $tax_amount;
}
protected function getTaxExclusivePrice($price, $tax_rate)
{
$tax_ex_price = bcdiv($price, bcadd(1, $tax_rate, 2), 2);
return $tax_ex_price;
}
}

View file

@ -1,12 +0,0 @@
<?php
namespace App;
interface InvoiceInterface
{
// check if the invoice rule is in the criteria
public function check($criteria);
// display the html partial for the form
public function getTemplate();
}

View file

@ -0,0 +1,119 @@
<?php
namespace App\InvoiceRule;
use App\InvoiceRuleInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Ramcar\ServiceType;
use App\Ramcar\TradeInType;
use App\Entity\Battery;
class BatteryReplacementWarranty implements InvoiceRuleInterface
{
protected $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function getID()
{
return 'battery_warranty';
}
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
$items = [];
if ($stype == $this->getID())
{
// get the entries
$entries = $criteria->getEntries();
foreach($entries as $entry)
{
$batt = $entry['battery'];
$qty = 1;
$price = $this->getServiceTypeFee();
$items[] = [
'service_type' => $this->getID(),
'battery' => $batt,
'qty' => $qty,
'title' => $this->getTitle($batt),
'price' => $price,
];
$qty_price = bcmul($price, $qty, 2);
$total['total_price'] = bcadd($total['total_price'], $qty_price, 2);
}
}
return $items;
}
public function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 0;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
// check service type. Only battery sales and battery warranty should have invoice items
$stype = $criteria->getServiceType();
if ($stype != ServiceType::BATTERY_REPLACEMENT_NEW && $stype != ServiceType::BATTERY_REPLACEMENT_WARRANTY)
return null;
// return error if there's a problem, false otherwise
if (!empty($invoice_items))
{
// check if this is a valid battery
foreach ($invoice_items as $item)
{
$battery = $this->em->getRepository(Battery::class)->find($item['battery']);
if (empty($battery))
{
$error = 'Invalid battery specified.';
return $error;
}
// quantity
$qty = $item['quantity'];
if ($qty < 1)
continue;
// if this is a trade in, add trade in
if (!empty($item['trade_in']) && TradeInType::validate($item['trade_in']))
$trade_in = $item['trade_in'];
else
$trade_in = null;
$criteria->addEntry($battery, $trade_in, $qty);
}
}
return null;
}
protected function getTitle($battery)
{
$title = $battery->getModel()->getName() . ' ' . $battery->getSize()->getName() . ' - Service Unit';
return $title;
}
}

View file

@ -0,0 +1,122 @@
<?php
namespace App\InvoiceRule;
use Doctrine\ORM\EntityManagerInterface;
use App\InvoiceRuleInterface;
use App\Ramcar\TradeInType;
use App\Ramcar\ServiceType;
use App\Entity\Battery;
class BatterySales implements InvoiceRuleInterface
{
protected $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function getID()
{
return 'battery_new';
}
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
$items = [];
if ($stype == $this->getID())
{
// get the entries
$entries = $criteria->getEntries();
foreach($entries as $entry)
{
$batt = $entry['battery'];
$qty = $entry['qty'];
$trade_in = null;
if (isset($entry['trade_in']))
$trade_in = $entry['trade_in'];
$size = $batt->getSize();
if ($trade_in == null)
{
// battery purchase
$price = $batt->getSellingPrice();
$items[] = [
'service_type' => $this->getID(),
'battery' => $batt,
'qty' => $qty,
'title' => $this->getTitle($batt),
'price' => $price,
];
$qty_price = bcmul($price, $qty, 2);
$total['sell_price'] = bcadd($total['sell_price'], $qty_price, 2);
$total['total_price'] = bcadd($total['total_price'], $qty_price, 2);
}
}
}
return $items;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
// check service type. Only battery sales and battery warranty should have invoice items
$stype = $criteria->getServiceType();
if ($stype != ServiceType::BATTERY_REPLACEMENT_NEW && $stype != ServiceType::BATTERY_REPLACEMENT_WARRANTY)
return null;
// return error if there's a problem, false otherwise
if (!empty($invoice_items))
{
// check if this is a valid battery
foreach ($invoice_items as $item)
{
$battery = $this->em->getRepository(Battery::class)->find($item['battery']);
if (empty($battery))
{
$error = 'Invalid battery specified.';
return $error;
}
// quantity
$qty = $item['quantity'];
if ($qty < 1)
continue;
// if this is a trade in, add trade in
if (!empty($item['trade_in']) && TradeInType::validate($item['trade_in']))
$trade_in = $item['trade_in'];
else
$trade_in = null;
$criteria->addEntry($battery, $trade_in, $qty);
}
}
return null;
}
protected function getTitle($battery)
{
$title = $battery->getModel()->getName() . ' ' . $battery->getSize()->getName();
return $title;
}
}

View file

@ -1,39 +1,40 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\InvoiceRuleInterface;
use App\Ramcar\ServiceType;
use App\Ramcar\DiscountApply;
class DiscountType implements InvoiceInterface
use App\Entity\Promo;
class DiscountType implements InvoiceRuleInterface
{
public function check($criteria)
protected $em;
public function __construct(EntityManagerInterface $em)
{
if (!empty($criteria->getPromos()))
return true;
return false;
}
public function getTemplate()
{
return 'invoice/discount_type.html.twig';
$this->em = $em;
}
public function getID()
{
return 'discount_type';
return 'discount';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$items = [];
$promos = $criteria->getPromos();
// NOTE: only get first promo because only one is applicable anyway
if (empty($promos))
return $items;
// NOTE: only get first promo because only one is applicable anyway
$promo = $promos[0];
$rate = $promo->getDiscountRate();
@ -75,6 +76,36 @@ class DiscountType implements InvoiceInterface
return $items;
}
public function validatePromo($criteria, $promo_id)
{
// return error if there's a problem, false otherwise
// check service type
$stype = $criteria->getServiceType();
// discount/promo only applies for battery sales
if ($stype != ServiceType::BATTERY_REPLACEMENT_NEW)
return null;
if (empty($promo_id))
{
return false;
}
// check if this is a valid promo
$promo = $this->em->getRepository(Promo::class)->find($promo_id);
if (empty($promo))
return 'Invalid promo specified.';
$criteria->addPromo($promo);
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getTitle()
{
$title = 'Promo discount';

View file

@ -1,32 +1,20 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
use App\Ramcar\FuelType;
use App\Ramcar\ServiceType;
class Fuel implements InvoiceInterface
class Fuel implements InvoiceRuleInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
}
public function getID()
{
return 'fuel';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
@ -39,7 +27,7 @@ class Fuel implements InvoiceInterface
if ($cv->hasMotoliteBattery())
$fee = 0;
else
$fee = $stype_fees['service_fee'];
$fee = $this->getServiceTypeFee();
$ftype = $cv->getFuelType();
@ -55,14 +43,12 @@ class Fuel implements InvoiceInterface
$qty_fee = bcmul($qty, $fee, 2);
$total_price = $qty_fee;
$stype_fees_id = $this->getID() . '_fee_' . $ftype;
switch ($ftype)
{
case FuelType::GAS:
case FuelType::DIESEL:
$qty = 1;
$price = $stype_fees[$stype_fees_id];
$price = $this->getFuelFee();
$items[] = [
'service_type' => $this->getID(),
'qty' => $qty,
@ -96,6 +82,41 @@ class Fuel implements InvoiceInterface
return $items;
}
public function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any changes are to be made, we just edit the file
// instead of the code
return 300;
}
public function getFuelFee($fuel_type)
{
// TODO: we need to to put this somewhere like in .env
// so that if any changes are to be made, we just edit the file
// instead of the code
if ($fuel_type == FuelType::GAS)
{
// gas fuel fee
return 320;
}
else
{
// diesel fuel fee
return 340;
}
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getTitle($fuel_type)
{
$title = '4L - ' . ucfirst($fuel_type);

View file

@ -1,29 +1,17 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
class Jumpstart implements InvoiceInterface
class Jumpstart implements InvoiceRuleInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
}
public function getID()
{
return 'jumpstart_troubleshoot';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
@ -31,9 +19,7 @@ class Jumpstart implements InvoiceInterface
if ($stype == $this->getID())
{
$stype_fees_id = $this->getID() . '_fee';
$fee = $stype_fees[$stype_fees_id];
$fee = $this->getServiceTypeFee();
// add the service fee to items
$qty = 1;
@ -51,6 +37,24 @@ class Jumpstart implements InvoiceInterface
return $items;
}
public function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 150;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getServiceTitle()
{
$title = 'Service - Troubleshooting fee';

View file

@ -1,29 +1,17 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
class JumpstartWarranty implements InvoiceInterface
class JumpstartWarranty implements InvoiceRuleInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
}
public function getID()
{
return 'jumpstart_warranty';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
@ -31,9 +19,7 @@ class JumpstartWarranty implements InvoiceInterface
if ($stype == $this->getID())
{
$stype_fees_id = $this->getID() . '_fee';
$fee = $stype_fees[$stype_fees_id];
$fee = $this->getServiceTypeFee();
// add the service fee to items
$qty = 1;
@ -51,6 +37,24 @@ class JumpstartWarranty implements InvoiceInterface
return $items;
}
public function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 0;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getServiceTitle()
{
$title = 'Service - Troubleshooting fee';

View file

@ -1,31 +1,19 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
USE App\Ramcar\ServiceType;
use App\Ramcar\ServiceType;
class Overheat implements InvoiceInterface
class Overheat implements InvoiceRuleInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
}
public function getID()
{
return 'overheat';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
$has_coolant = $criteria->hasCoolant();
@ -39,7 +27,7 @@ class Overheat implements InvoiceInterface
if ($cv->hasMotoliteBattery())
$fee = 0;
else
$fee = $stype_fees['service_fee'];
$fee = $this->getServiceTypeFee();
// add the service fee to items
$qty = 1;
@ -55,7 +43,7 @@ class Overheat implements InvoiceInterface
if ($has_coolant)
{
$coolant_fee = $stype_fees['coolant_fee'];
$coolant_fee = $this->getCoolantFee();
$items[] = [
'service_type' => $this->getID(),
'qty' => $qty,
@ -73,6 +61,32 @@ class Overheat implements InvoiceInterface
return $items;
}
public function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 300;
}
public function getCoolantFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 1600;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getServiceTitle()
{
$title = 'Service - ' . ServiceType::getName(ServiceType::OVERHEAT_ASSISTANCE);

View file

@ -1,29 +1,17 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
class PostRecharged implements InvoiceInterface
class PostRecharged implements InvoiceRuleInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
}
public function getID()
{
return 'post_recharged';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
@ -31,7 +19,7 @@ class PostRecharged implements InvoiceInterface
if ($stype == $this->getID())
{
$fee = $stype_fees[$this->getID() . '_fee'];
$fee = $this->getServiceTypeFee();
$qty = 1;
$items[] = [
@ -49,6 +37,24 @@ class PostRecharged implements InvoiceInterface
return $items;
}
public function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 300;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getServiceTitle()
{
$title = 'Recharge fee';

View file

@ -1,29 +1,17 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
class PostReplacement implements InvoiceInterface
class PostReplacement implements InvoiceRuleInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
}
public function getID()
{
return 'post_replacement';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
@ -31,7 +19,7 @@ class PostReplacement implements InvoiceInterface
if ($stype == $this->getID())
{
$fee = $stype_fees['battery_replacement_fee'];
$fee = $this->getServiceTypeFee();
$qty = 1;
$items[] = [
@ -48,6 +36,24 @@ class PostReplacement implements InvoiceInterface
return $items;
}
public function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 0;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getServiceTitle()
{
$title = 'Battery replacement';

110
src/InvoiceRule/Tax.php Normal file
View file

@ -0,0 +1,110 @@
<?php
namespace App\InvoiceRule;
use App\InvoiceRuleInterface;
use App\Ramcar\ServiceType;
class Tax implements InvoiceRuleInterface
{
public function getID()
{
return 'tax';
}
public function compute($criteria, &$total)
{
// check if taxable
if (!$criteria->isTaxable())
{
// nothing to compute
return [];
}
$tax_rate = $this->getTaxRate();
$is_battery_sales = false;
$total_price = 0;
// compute tax per item if service type is battery sales
$stype = $criteria->getServiceType();
if ($stype == ServiceType::BATTERY_REPLACEMENT_NEW)
{
// get the entries
$entries = $criteria->getEntries();
foreach($entries as $entry)
{
// check if entry is trade-in
if (isset($entry['trade_in']))
{
// continue to next entry
continue;
}
$battery = $entry['battery'];
$qty = $entry['qty'];
$price = $battery->getSellingPrice();
$vat = $this->getTaxAmount($price, $tax_rate);
$qty_price = bcmul($price, $qty, 2);
$qty_vat = bcmul($vat, $qty, 2);
$price_minus_vat = bcsub($price, $vat, 2);
$qty_price_minus_vat = bcmul($price_minus_vat, $qty, 2);
$total['vat'] = bcadd($total['vat'], $qty_vat, 2);
$total['vat_ex_price'] = bcadd($total['vat_ex_price'], $qty_price_minus_vat, 2);
}
}
else
{
// compute VAT after adding all item costs, if service type is not battery sales
$total_price = $total['total_price'];
$vat_ex_price = $this->getTaxExclusivePrice($total_price, $tax_rate);
$vat = bcsub($total_price, $vat_ex_price, 2);
$total['vat_ex_price'] = $vat_ex_price;
$total['vat'] = $vat;
}
return [];
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getTaxAmount($price, $tax_rate)
{
$vat_ex_price = $this->getTaxExclusivePrice($price, $tax_rate);
$tax_amount = bcsub($price, $vat_ex_price, 2);
return $tax_amount;
}
protected function getTaxExclusivePrice($price, $tax_rate)
{
$tax_ex_price = bcdiv($price, bcadd(1, $tax_rate, 2), 2);
return $tax_ex_price;
}
protected function getTaxRate()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 0.12;
}
}

View file

@ -1,29 +1,17 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
class TireRepair implements InvoiceInterface
class TireRepair implements InvoiceRuleInterface
{
public function check($criteria)
{
if ($this->getID() == $criteria->getServiceType())
return true;
return false;
}
public function getTemplate()
{
}
public function getID()
{
return 'tire';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$stype = $criteria->getServiceType();
@ -36,7 +24,7 @@ class TireRepair implements InvoiceInterface
if ($cv->hasMotoliteBattery())
$fee = 0;
else
$fee = $stype_fees['service_fee'];
$fee = $this->getServiceTypeFee();
// add the service fee to items
$qty = 1;
@ -54,6 +42,24 @@ class TireRepair implements InvoiceInterface
return $items;
}
protected function getServiceTypeFee()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 300;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getServiceTitle()
{
$title = 'Service - Flat Tire';

View file

@ -1,41 +1,19 @@
<?php
namespace App\Invoice;
namespace App\InvoiceRule;
use App\InvoiceInterface;
use App\InvoiceRuleInterface;
use App\Ramcar\TradeInType;
class TradeIn implements InvoiceInterface
class TradeIn implements InvoiceRuleInterface
{
public function check($criteria)
{
// compare specified type ids with trade in entry of criteria
$entries = $criteria->getEntries();
foreach($entries as $entry)
{
if ($entry['trade_in'])
{
// just need to find one trade-in entry
return true;
}
}
return false;
}
public function getTemplate()
{
return 'invoice/trade_in.html.twig';
}
public function getID()
{
return 'trade_in';
return 'trade-in';
}
public function compute($criteria, $stype_fees, &$total)
public function compute($criteria, &$total)
{
$items = [];
@ -72,6 +50,16 @@ class TradeIn implements InvoiceInterface
return $items;
}
public function validatePromo($criteria, $promo_id)
{
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getTradeInRate($battery, $trade_in_type)
{
$size = $battery->getSize();

View file

@ -0,0 +1,15 @@
<?php
namespace App;
interface InvoiceRuleInterface
{
// validate promo
public function validatePromo($criteria, $promo_id);
// validate invoice items
public function validateInvoiceItems($criteria, $invoice_items);
// compute
public function compute($criteria, &$total);
}

View file

@ -7,7 +7,7 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Invoice;
use App\InvoiceRule;
use App\Service\InvoiceGeneratorInterface;
@ -16,7 +16,7 @@ use App\Ramcar\InvoiceStatus;
use App\Ramcar\ServiceType;
use App\Ramcar\TradeInType;
use App\Entity\Invoice as Inv;
use App\Entity\Invoice;
use App\Entity\InvoiceItem;
use App\Entity\User;
use App\Entity\Battery;
@ -42,49 +42,21 @@ class InvoiceManager implements InvoiceGeneratorInterface
{
// TODO: get list of invoice rules from .env or a json file?
return [
new Invoice\ServiceType(),
new Invoice\BatterySales(),
new Invoice\BatteryReplacementWarranty(),
new Invoice\Jumpstart(),
new Invoice\JumpstartWarranty(),
new Invoice\PostRecharged(),
new Invoice\PostReplacement(),
new Invoice\Overheat(),
new Invoice\Fuel(),
new Invoice\TireRepair(),
new Invoice\DiscountType(),
new Invoice\TradeIn(),
new Invoice\Tax(),
new InvoiceRule\BatterySales($this->em),
new InvoiceRule\BatteryReplacementWarranty($this->em),
new InvoiceRule\Jumpstart(),
new InvoiceRule\JumpstartWarranty(),
new InvoiceRule\PostRecharged(),
new InvoiceRule\PostReplacement(),
new InvoiceRule\Overheat(),
new InvoiceRule\Fuel(),
new InvoiceRule\TireRepair(),
new InvoiceRule\DiscountType($this->em),
new InvoiceRule\TradeIn(),
new InvoiceRule\Tax(),
];
}
public function getServiceTypeFees()
{
// TODO: we need to put this somewhere like a json file, so
// if any changes are to be made to fees, we just edit the file
// instead of the code
return [
'service_fee' => 300,
'coolant_fee' => 1600,
'post_recharged_fee' => 300,
'jumpstart_troubleshoot_fee' => 150,
'jumpstart_warranty_fee' => 0,
'battery_replacement_fee' => 0,
'battery_warranty_fee' => 0,
'other_services_fee' => 200,
'fuel_fee_gas' => 320,
'fuel_fee_diesel' => 340,
];
}
public function getTaxRate()
{
// TODO: we need to to put this somewhere like in .env
// so that if any chanages are to be made, we just edit the file
// instead of the code
return 0.12;
}
// this is called when JO is submitted
public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, &$error_array)
{
@ -98,12 +70,26 @@ class InvoiceManager implements InvoiceGeneratorInterface
// would mean adding it as a parameter to the call, impacting all calls
$criteria->setIsTaxable();
$ierror = $this->validatePromo($criteria, $promo_id);
foreach ($this->available_rules as $avail_rule)
{
$ierror = $avail_rule->validatePromo($criteria, $promo_id);
// break out of loop when error found
if ($ierror)
break;
}
if (!$ierror && !empty($invoice_items))
{
// validate the invoice items (batteries and trade ins)
$ierror = $this->validateInvoiceItems($criteria, $invoice_items);
foreach ($this->available_rules as $avail_rule)
{
$ierror = $avail_rule->validateInvoiceItems($criteria, $invoice_items);
// break out of loop when error found
if ($ierror)
break;
}
}
if ($ierror)
@ -142,12 +128,26 @@ class InvoiceManager implements InvoiceGeneratorInterface
// this is called by JobOrderController when JS script generateInvoice is called
public function generateDraftInvoice($criteria, $promo_id, $service_charges, $items)
{
$ierror = $this->validatePromo($criteria, $promo_id);
foreach ($this->available_rules as $avail_rule)
{
$ierror = $avail_rule->validatePromo($criteria, $promo_id);
// break out of loop when error found
if ($ierror)
break;
}
if (!$ierror && !empty($items))
{
// validate the invoice items (batteries and trade ins)
$ierror = $this->validateInvoiceItems($criteria, $items);
foreach ($this->available_rules as $avail_rule)
{
$ierror = $avail_rule->validateInvoiceItems($criteria, $items);
// break out of loop when error found
if ($ierror)
break;
}
}
return $ierror;
@ -163,31 +163,14 @@ class InvoiceManager implements InvoiceGeneratorInterface
{
// no need to validate since generateDraftInvoice was called before this was called
// generate the invoice and from APIController, the fields were validated
// check which rules to apply
$rules = $this->check($criteria);
$invoice_data = $this->compute($criteria, $rules);
$invoice_data = $this->compute($criteria);
$invoice = $this->createInvoice($invoice_data);
return $invoice;
}
// check what rules to use given the criteria
public function check($criteria)
{
$active_rules = [];
foreach ($this->available_rules as $rule)
{
$is_active = $rule->check($criteria);
if ($is_active)
$active_rules[$rule->getID()] = $rule;
}
return $active_rules;
}
public function compute($criteria, $active_rules)
public function compute($criteria)
{
// initialize
$total = [
@ -205,9 +188,6 @@ class InvoiceManager implements InvoiceGeneratorInterface
$promos = $criteria->getPromos();
$is_taxable = $criteria->isTaxable();
// get the service type fees
$stype_fees = $this->getServiceTypeFees();
$flag_trade_in = false;
foreach ($entries as $entry)
{
@ -219,164 +199,48 @@ class InvoiceManager implements InvoiceGeneratorInterface
$invoice_items = [];
$data = [];
foreach ($active_rules as $id => $active_rule)
foreach ($this->available_rules as $rule)
{
// each criteria can only have one service type
// find the rule for the service type
if ($id == $stype)
$items = $rule->compute($criteria, $total);
$promo = null;
foreach ($items as $item)
{
$items = [];
$title = $item['title'];
$quantity = $item['qty'];
$price = $item['price'];
$computed_items = $active_rule->compute($criteria, $stype_fees, $total);
foreach ($computed_items as $computed_item)
{
if (!empty($computed_item))
{
$items[] = $computed_item;
}
}
// check if tax is needed
if ($is_taxable)
{
$tax_rate = $this->getTaxRate();
if (isset($active_rules['tax']))
{
$active_rules['tax']->compute($tax_rate, $items, $total);
}
}
// process trade-ins by calling the trade-in rule if there are trade-ins among the entries
if ($flag_trade_in)
{
if (isset($active_rules['trade_in']))
{
$tradein_items = $active_rules['trade_in']->compute($criteria, $stype_fees, $total);
foreach ($tradein_items as $tradein_item)
{
$items[] = $tradein_item;
}
}
}
// process promos, if any
if (count($promos) > 0)
{
if (isset($active_rules['discount_type']))
{
$discount_items = $active_rules['discount_type']->compute($criteria, $stype_fees, $total);
foreach ($discount_items as $discount_item)
{
$items[] = $discount_item;
}
}
}
$battery = null;
if (isset($item['battery']))
$battery = $item['battery'];
$promo = null;
foreach ($items as $item)
{
$title = $item['title'];
$quantity = $item['qty'];
$price = $item['price'];
if (isset($item['promo']))
$promo = $item['promo'];
$battery = null;
if (isset($item['battery']))
$battery = $item['battery'];
$promo = null;
if (isset($item['promo']))
$promo = $item['promo'];
$invoice_items[] = [
'title' => $title,
'quantity' => $quantity,
'price' => $price,
'battery' => $battery,
'promo' => $promo,
];
}
// also need to return the total and the promo
$data[] = [
$invoice_items[] = [
'title' => $title,
'quantity' => $quantity,
'price' => $price,
'battery' => $battery,
'promo' => $promo,
'invoice_items' => $invoice_items,
'total' => $total,
];
}
// also need to return the total and the promo
$data[] = [
'promo' => $promo,
'invoice_items' => $invoice_items,
'total' => $total,
];
}
return $data;
}
protected function validatePromo($criteria, $promo_id)
{
// return error if there's a problem, false otherwise
// check service type
$stype = $criteria->getServiceType();
// discount/promo only applies for battery sales
if ($stype != ServiceType::BATTERY_REPLACEMENT_NEW)
return null;
if (empty($promo_id))
{
return false;
}
// check if this is a valid promo
$promo = $this->em->getRepository(Promo::class)->find($promo_id);
if (empty($promo))
return 'Invalid promo specified.';
$criteria->addPromo($promo);
return false;
}
protected function validateInvoiceItems($criteria, $invoice_items)
{
// check service type. Only battery sales and battery warranty should have invoice items
$stype = $criteria->getServiceType();
if ($stype != ServiceType::BATTERY_REPLACEMENT_NEW && $stype != ServiceType::BATTERY_REPLACEMENT_WARRANTY)
return null;
// return error if there's a problem, false otherwise
if (!empty($invoice_items))
{
// check if this is a valid battery
foreach ($invoice_items as $item)
{
$battery = $this->em->getRepository(Battery::class)->find($item['battery']);
if (empty($battery))
{
$error = 'Invalid battery specified.';
return $error;
}
// quantity
$qty = $item['quantity'];
if ($qty < 1)
continue;
// if this is a trade in, add trade in
if (!empty($item['trade_in']) && TradeInType::validate($item['trade_in']))
$trade_in = $item['trade_in'];
else
$trade_in = null;
$criteria->addEntry($battery, $trade_in, $qty);
}
}
return null;
}
protected function createInvoice($invoice_data)
{
$invoice = new Inv();
$invoice = new Invoice();
// get current user
$user = $this->security->getUser();