Merge branch '744-new-invoice-service' into '746-resq-2-0-final'
Resolve "New invoice service" See merge request jankstudio/resq!860
This commit is contained in:
commit
f26d6284f3
28 changed files with 3651 additions and 6 deletions
|
|
@ -115,7 +115,10 @@ services:
|
||||||
App\Service\InvoiceGenerator\ResqInvoiceGenerator: ~
|
App\Service\InvoiceGenerator\ResqInvoiceGenerator: ~
|
||||||
|
|
||||||
# invoice generator interface
|
# invoice generator interface
|
||||||
App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\ResqInvoiceGenerator"
|
App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceManager"
|
||||||
|
|
||||||
|
# invoice manager
|
||||||
|
App\Service\InvoiceManager: ~
|
||||||
|
|
||||||
# job order generator
|
# job order generator
|
||||||
App\Service\JobOrderHandler\ResqJobOrderHandler:
|
App\Service\JobOrderHandler\ResqJobOrderHandler:
|
||||||
|
|
|
||||||
2106
src/Command/TestInvoiceManagerCommand.php
Normal file
2106
src/Command/TestInvoiceManagerCommand.php
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -2865,6 +2865,9 @@ class APIController extends Controller implements LoggedController
|
||||||
$icrit = new InvoiceCriteria();
|
$icrit = new InvoiceCriteria();
|
||||||
$icrit->setServiceType($stype);
|
$icrit->setServiceType($stype);
|
||||||
|
|
||||||
|
// set taxable
|
||||||
|
$icrit->setIsTaxable(true);
|
||||||
|
|
||||||
// check promo
|
// check promo
|
||||||
$promo_id = $req->request->get('promo_id');
|
$promo_id = $req->request->get('promo_id');
|
||||||
if (!empty($promo_id))
|
if (!empty($promo_id))
|
||||||
|
|
|
||||||
|
|
@ -1201,6 +1201,7 @@ class RiderAppController extends APIController
|
||||||
$crit->setServiceType($stype_id);
|
$crit->setServiceType($stype_id);
|
||||||
$crit->setCustomerVehicle($cv);
|
$crit->setCustomerVehicle($cv);
|
||||||
$crit->setHasCoolant($jo->hasCoolant());
|
$crit->setHasCoolant($jo->hasCoolant());
|
||||||
|
$crit->setIsTaxable();
|
||||||
|
|
||||||
if ($promo != null)
|
if ($promo != null)
|
||||||
$crit->addPromo($promo);
|
$crit->addPromo($promo);
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,9 @@ class InvoiceController extends ApiController
|
||||||
|
|
||||||
$icrit->addEntry($batt, $trade_in, 1);
|
$icrit->addEntry($batt, $trade_in, 1);
|
||||||
|
|
||||||
|
// set if taxable
|
||||||
|
$icrit->setIsTaxable();
|
||||||
|
|
||||||
// send to invoice generator
|
// send to invoice generator
|
||||||
$invoice = $ic->generateInvoice($icrit);
|
$invoice = $ic->generateInvoice($icrit);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -658,6 +658,9 @@ class JobOrderController extends ApiController
|
||||||
$icrit->addBattery($batt);
|
$icrit->addBattery($batt);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// NOTE: trade in is currently not supported. Would it be better
|
||||||
|
// if we remove trade-in as a required parameter? Or just leave it be
|
||||||
|
// and simply not process it?
|
||||||
// check trade-in
|
// check trade-in
|
||||||
// only allow motolite, other, none
|
// only allow motolite, other, none
|
||||||
switch ($trade_in) {
|
switch ($trade_in) {
|
||||||
|
|
@ -672,6 +675,9 @@ class JobOrderController extends ApiController
|
||||||
|
|
||||||
$icrit->addEntry($batt, $trade_in, 1);
|
$icrit->addEntry($batt, $trade_in, 1);
|
||||||
|
|
||||||
|
// set taxable
|
||||||
|
$icrit->setIsTaxable();
|
||||||
|
|
||||||
// send to invoice generator
|
// send to invoice generator
|
||||||
$invoice = $ic->generateInvoice($icrit);
|
$invoice = $ic->generateInvoice($icrit);
|
||||||
$jo->setInvoice($invoice);
|
$jo->setInvoice($invoice);
|
||||||
|
|
@ -1074,6 +1080,9 @@ class JobOrderController extends ApiController
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set taxable
|
||||||
|
$icrit->setIsTaxable();
|
||||||
|
|
||||||
$icrit->addEntry($batt, $trade_in, 1);
|
$icrit->addEntry($batt, $trade_in, 1);
|
||||||
|
|
||||||
// send to invoice generator
|
// send to invoice generator
|
||||||
|
|
|
||||||
|
|
@ -737,7 +737,8 @@ class JobOrderController extends Controller
|
||||||
// instantiate invoice criteria
|
// instantiate invoice criteria
|
||||||
$criteria = new InvoiceCriteria();
|
$criteria = new InvoiceCriteria();
|
||||||
$criteria->setServiceType($stype)
|
$criteria->setServiceType($stype)
|
||||||
->setCustomerVehicle($cv);
|
->setCustomerVehicle($cv)
|
||||||
|
->setIsTaxable();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,9 @@ class JobOrderController extends APIController
|
||||||
|
|
||||||
$icrit->setCustomerVehicle($data['customer_vehicle']);
|
$icrit->setCustomerVehicle($data['customer_vehicle']);
|
||||||
|
|
||||||
|
// set taxable
|
||||||
|
$icrit->setIsTaxable();
|
||||||
|
|
||||||
$icrit->addEntry($data['batt'], $data['trade_in_type'], 1);
|
$icrit->addEntry($data['batt'], $data['trade_in_type'], 1);
|
||||||
|
|
||||||
// send to invoice generator
|
// send to invoice generator
|
||||||
|
|
|
||||||
120
src/InvoiceRule/BatteryReplacementWarranty.php
Normal file
120
src/InvoiceRule/BatteryReplacementWarranty.php
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?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. Since this is the
|
||||||
|
// battery replacement warranty rule, we only check for battery replacement warranty.
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
if ($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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
123
src/InvoiceRule/BatterySales.php
Normal file
123
src/InvoiceRule/BatterySales.php
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?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. Since this is the battery sales
|
||||||
|
// rule, we only check for battery sales.
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
if ($stype != ServiceType::BATTERY_REPLACEMENT_NEW)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
116
src/InvoiceRule/DiscountType.php
Normal file
116
src/InvoiceRule/DiscountType.php
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
use App\Ramcar\ServiceType;
|
||||||
|
use App\Ramcar\DiscountApply;
|
||||||
|
|
||||||
|
use App\Entity\Promo;
|
||||||
|
|
||||||
|
class DiscountType implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
protected $em;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em)
|
||||||
|
{
|
||||||
|
$this->em = $em;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'discount';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
$promos = $criteria->getPromos();
|
||||||
|
|
||||||
|
if (empty($promos))
|
||||||
|
return $items;
|
||||||
|
|
||||||
|
// NOTE: only get first promo because only one is applicable anyway
|
||||||
|
$promo = $promos[0];
|
||||||
|
|
||||||
|
$rate = $promo->getDiscountRate();
|
||||||
|
$apply_to = $promo->getDiscountApply();
|
||||||
|
|
||||||
|
switch ($apply_to)
|
||||||
|
{
|
||||||
|
case DiscountApply::SRP:
|
||||||
|
$discount = bcmul($total['sell_price'], $rate, 2);
|
||||||
|
break;
|
||||||
|
case DiscountApply::OPL:
|
||||||
|
// $discount = round($total['sell_price'] * 0.6 / 0.7 * $rate, 2);
|
||||||
|
// $discount = round($total['sell_price'] * (1 - 1.5 / 0.7 * $rate), 2);
|
||||||
|
$num1 = bcdiv(1.5, 0.7, 9);
|
||||||
|
$num1_rate = bcmul($num1, $rate, 9);
|
||||||
|
$multiplier = bcsub(1, $num1_rate, 9);
|
||||||
|
|
||||||
|
$discount = bcmul($total['sell_price'], $multiplier, 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if discount is higher than 0, add to items
|
||||||
|
if ($discount > 0)
|
||||||
|
{
|
||||||
|
$qty = 1;
|
||||||
|
$price = bcmul(-1, $discount, 2);
|
||||||
|
|
||||||
|
$items[] = [
|
||||||
|
'promo' => $promo,
|
||||||
|
'title' => $this->getTitle(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'price' => $price,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$total['discount'] = $discount;
|
||||||
|
$total['total_price'] = bcsub($total['total_price'], $discount, 2);
|
||||||
|
|
||||||
|
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';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
133
src/InvoiceRule/Fuel.php
Normal file
133
src/InvoiceRule/Fuel.php
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
use App\Ramcar\FuelType;
|
||||||
|
use App\Ramcar\ServiceType;
|
||||||
|
|
||||||
|
class Fuel implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'fuel';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($stype == $this->getID())
|
||||||
|
{
|
||||||
|
// check if customer vehicle has a motolite battery
|
||||||
|
$cv = $criteria->getCustomerVehicle();
|
||||||
|
if ($cv->hasMotoliteBattery())
|
||||||
|
$fee = 0;
|
||||||
|
else
|
||||||
|
$fee = $this->getServiceTypeFee();
|
||||||
|
|
||||||
|
$ftype = $cv->getFuelType();
|
||||||
|
|
||||||
|
// add the service fee to items
|
||||||
|
$qty = 1;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceTitle($ftype),
|
||||||
|
'price' => $fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_fee = bcmul($qty, $fee, 2);
|
||||||
|
$total_price = $qty_fee;
|
||||||
|
|
||||||
|
switch ($ftype)
|
||||||
|
{
|
||||||
|
case FuelType::GAS:
|
||||||
|
case FuelType::DIESEL:
|
||||||
|
$qty = 1;
|
||||||
|
$price = $this->getFuelFee($ftype);
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getTitle($ftype),
|
||||||
|
'price' => $price,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($price, $qty, 2);
|
||||||
|
$total_price = bcadd($total_price, $qty_price, 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$qty = 1;
|
||||||
|
$price = 0;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getTitle('Unknown'),
|
||||||
|
'price' => $price,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($price, $qty, 2);
|
||||||
|
$total_price = bcadd($total_price, $qty_price, 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$total['total_price'] = bcadd($total['total_price'], $total_price, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getServiceTitle($fuel_type)
|
||||||
|
{
|
||||||
|
$title = 'Service - ' . ServiceType::getName(ServiceType::EMERGENCY_REFUEL);
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/InvoiceRule/Jumpstart.php
Normal file
64
src/InvoiceRule/Jumpstart.php
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
class Jumpstart implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'jumpstart_troubleshoot';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($stype == $this->getID())
|
||||||
|
{
|
||||||
|
$fee = $this->getServiceTypeFee();
|
||||||
|
|
||||||
|
// add the service fee to items
|
||||||
|
$qty = 1;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceTitle(),
|
||||||
|
'price' => $fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($fee, $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 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validatePromo($criteria, $promo_id)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validateInvoiceItems($criteria, $invoice_items)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getServiceTitle()
|
||||||
|
{
|
||||||
|
$title = 'Service - Troubleshooting fee';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/InvoiceRule/JumpstartWarranty.php
Normal file
64
src/InvoiceRule/JumpstartWarranty.php
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
class JumpstartWarranty implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'jumpstart_warranty';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($stype == $this->getID())
|
||||||
|
{
|
||||||
|
$fee = $this->getServiceTypeFee();
|
||||||
|
|
||||||
|
// add the service fee to items
|
||||||
|
$qty = 1;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceTitle(),
|
||||||
|
'price' => $fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($fee, $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)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getServiceTitle()
|
||||||
|
{
|
||||||
|
$title = 'Service - Troubleshooting fee';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
103
src/InvoiceRule/Overheat.php
Normal file
103
src/InvoiceRule/Overheat.php
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
use App\Ramcar\ServiceType;
|
||||||
|
|
||||||
|
class Overheat implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'overheat';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
$has_coolant = $criteria->hasCoolant();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($stype == $this->getID())
|
||||||
|
{
|
||||||
|
// check if customer vehicle has a motolite battery
|
||||||
|
$cv = $criteria->getCustomerVehicle();
|
||||||
|
if ($cv->hasMotoliteBattery())
|
||||||
|
$fee = 0;
|
||||||
|
else
|
||||||
|
$fee = $this->getServiceTypeFee();
|
||||||
|
|
||||||
|
// add the service fee to items
|
||||||
|
$qty = 1;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceTitle(),
|
||||||
|
'price' => $fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_fee = bcmul($qty, $fee, 2);
|
||||||
|
$total_price = $qty_fee;
|
||||||
|
|
||||||
|
if ($has_coolant)
|
||||||
|
{
|
||||||
|
$coolant_fee = $this->getCoolantFee();
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceCoolantTitle(),
|
||||||
|
'price' => $coolant_fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($coolant_fee, $qty, 2);
|
||||||
|
$total_price = bcadd($total_price, $qty_price, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$total['total_price'] = bcadd($total['total_price'], $total_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 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);
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getServiceCoolantTitle()
|
||||||
|
{
|
||||||
|
$title = '4L Coolant';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/InvoiceRule/PostRecharged.php
Normal file
64
src/InvoiceRule/PostRecharged.php
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
class PostRecharged implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'post_recharged';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($stype == $this->getID())
|
||||||
|
{
|
||||||
|
$fee = $this->getServiceTypeFee();
|
||||||
|
|
||||||
|
$qty = 1;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceTitle(),
|
||||||
|
'price' => $fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($fee, $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 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validatePromo($criteria, $promo_id)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validateInvoiceItems($criteria, $invoice_items)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getServiceTitle()
|
||||||
|
{
|
||||||
|
$title = 'Recharge fee';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/InvoiceRule/PostReplacement.php
Normal file
63
src/InvoiceRule/PostReplacement.php
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
class PostReplacement implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'post_replacement';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($stype == $this->getID())
|
||||||
|
{
|
||||||
|
$fee = $this->getServiceTypeFee();
|
||||||
|
|
||||||
|
$qty = 1;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceTitle(),
|
||||||
|
'price' => $fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($fee, $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)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getServiceTitle()
|
||||||
|
{
|
||||||
|
$title = 'Battery replacement';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
110
src/InvoiceRule/Tax.php
Normal file
110
src/InvoiceRule/Tax.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
69
src/InvoiceRule/TireRepair.php
Normal file
69
src/InvoiceRule/TireRepair.php
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
class TireRepair implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'tire';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
if ($stype == $this->getID())
|
||||||
|
{
|
||||||
|
// check if customer vehicle has a motolite battery
|
||||||
|
$cv = $criteria->getCustomerVehicle();
|
||||||
|
if ($cv->hasMotoliteBattery())
|
||||||
|
$fee = 0;
|
||||||
|
else
|
||||||
|
$fee = $this->getServiceTypeFee();
|
||||||
|
|
||||||
|
// add the service fee to items
|
||||||
|
$qty = 1;
|
||||||
|
$items[] = [
|
||||||
|
'service_type' => $this->getID(),
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getServiceTitle(),
|
||||||
|
'price' => $fee,
|
||||||
|
];
|
||||||
|
|
||||||
|
$qty_price = bcmul($fee, $qty, 2);
|
||||||
|
$total['total_price'] = bcadd($total['total_price'], $qty_price, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
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';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/InvoiceRule/TradeIn.php
Normal file
87
src/InvoiceRule/TradeIn.php
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\InvoiceRuleInterface;
|
||||||
|
|
||||||
|
use App\Ramcar\TradeInType;
|
||||||
|
|
||||||
|
class TradeIn implements InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return 'trade-in';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria, &$total)
|
||||||
|
{
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
// get the entries
|
||||||
|
$entries = $criteria->getEntries();
|
||||||
|
foreach($entries as $entry)
|
||||||
|
{
|
||||||
|
$batt = $entry['battery'];
|
||||||
|
$qty = $entry['qty'];
|
||||||
|
$trade_in_type = null;
|
||||||
|
|
||||||
|
if (isset($entry['trade_in']))
|
||||||
|
$trade_in_type = $entry['trade_in'];
|
||||||
|
|
||||||
|
if ($trade_in_type != null)
|
||||||
|
{
|
||||||
|
$ti_rate = $this->getTradeInRate($batt, $trade_in_type);
|
||||||
|
|
||||||
|
$qty_ti = bcmul($ti_rate, $qty, 2);
|
||||||
|
|
||||||
|
$total['ti_rate'] = bcadd($total['ti_rate'], $qty_ti, 2);
|
||||||
|
$total['total_price'] = bcsub($total['total_price'], $qty_ti, 2);
|
||||||
|
|
||||||
|
$price = bcmul($ti_rate, -1, 2);
|
||||||
|
|
||||||
|
$items[] = [
|
||||||
|
'qty' => $qty,
|
||||||
|
'title' => $this->getTitle($batt, $trade_in_type),
|
||||||
|
'price' => $price,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
switch ($trade_in_type)
|
||||||
|
{
|
||||||
|
case TradeInType::MOTOLITE:
|
||||||
|
return $size->getTIPriceMotolite();
|
||||||
|
case TradeInType::PREMIUM:
|
||||||
|
return $size->getTIPricePremium();
|
||||||
|
case TradeInType::OTHER:
|
||||||
|
return $size->getTIPriceOther();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTitle($battery, $trade_in_type)
|
||||||
|
{
|
||||||
|
$title = 'Trade-in ' . TradeInType::getName($trade_in_type) . ' ' . $battery->getSize()->getName() . ' battery';
|
||||||
|
|
||||||
|
return $title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
16
src/InvoiceRuleInterface.php
Normal file
16
src/InvoiceRuleInterface.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
interface InvoiceRuleInterface
|
||||||
|
{
|
||||||
|
// validate promo
|
||||||
|
public function validatePromo($criteria, $promo_id);
|
||||||
|
|
||||||
|
// validate invoice items
|
||||||
|
public function validateInvoiceItems($criteria, $invoice_items);
|
||||||
|
|
||||||
|
// compute
|
||||||
|
// this returns an array of items or empty array
|
||||||
|
public function compute($criteria, &$total);
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ class InvoiceCriteria
|
||||||
protected $flag_coolant;
|
protected $flag_coolant;
|
||||||
protected $discount;
|
protected $discount;
|
||||||
protected $service_charges;
|
protected $service_charges;
|
||||||
|
protected $flag_taxable;
|
||||||
|
|
||||||
// entries are battery and trade-in combos
|
// entries are battery and trade-in combos
|
||||||
protected $entries;
|
protected $entries;
|
||||||
|
|
@ -28,6 +29,7 @@ class InvoiceCriteria
|
||||||
$this->flag_coolant = false;
|
$this->flag_coolant = false;
|
||||||
$this->discount = 0;
|
$this->discount = 0;
|
||||||
$this->service_charges = [];
|
$this->service_charges = [];
|
||||||
|
$this->flag_taxable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setServiceType($stype)
|
public function setServiceType($stype)
|
||||||
|
|
@ -153,4 +155,15 @@ class InvoiceCriteria
|
||||||
return $this->service_charges;
|
return $this->service_charges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setIsTaxable($flag = true)
|
||||||
|
{
|
||||||
|
$this->flag_taxable = $flag;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isTaxable()
|
||||||
|
{
|
||||||
|
return $this->flag_taxable;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
285
src/Service/InvoiceManager.php
Normal file
285
src/Service/InvoiceManager.php
Normal file
|
|
@ -0,0 +1,285 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
use App\InvoiceRule;
|
||||||
|
|
||||||
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
|
|
||||||
|
use App\Ramcar\InvoiceCriteria;
|
||||||
|
use App\Ramcar\InvoiceStatus;
|
||||||
|
use App\Ramcar\ServiceType;
|
||||||
|
use App\Ramcar\TradeInType;
|
||||||
|
|
||||||
|
use App\Entity\Invoice;
|
||||||
|
use App\Entity\InvoiceItem;
|
||||||
|
use App\Entity\User;
|
||||||
|
use App\Entity\Battery;
|
||||||
|
use App\Entity\Promo;
|
||||||
|
|
||||||
|
class InvoiceManager implements InvoiceGeneratorInterface
|
||||||
|
{
|
||||||
|
private $security;
|
||||||
|
protected $em;
|
||||||
|
protected $validator;
|
||||||
|
protected $available_rules;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $em, Security $security, ValidatorInterface $validator)
|
||||||
|
{
|
||||||
|
$this->em = $em;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->validator = $validator;
|
||||||
|
|
||||||
|
$this->available_rules = $this->getAvailableRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAvailableRules()
|
||||||
|
{
|
||||||
|
// TODO: get list of invoice rules from .env or a json file?
|
||||||
|
return [
|
||||||
|
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(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is called when JO is submitted
|
||||||
|
public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, &$error_array)
|
||||||
|
{
|
||||||
|
// instantiate the invoice criteria
|
||||||
|
$criteria = new InvoiceCriteria();
|
||||||
|
$criteria->setServiceType($jo->getServiceType())
|
||||||
|
->setCustomerVehicle($jo->getCustomerVehicle());
|
||||||
|
|
||||||
|
// set if taxable
|
||||||
|
// NOTE: ideally, this should be a parameter when calling generateInvoiceCriteria. But that
|
||||||
|
// would mean adding it as a parameter to the call, impacting all calls
|
||||||
|
$criteria->setIsTaxable();
|
||||||
|
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
$error_array['invoice'] = $ierror;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// generate the invoice
|
||||||
|
$invoice = $this->generateInvoice($criteria);
|
||||||
|
|
||||||
|
// validate
|
||||||
|
$ierrors = $this->validator->validate($invoice);
|
||||||
|
|
||||||
|
// add errors to list
|
||||||
|
foreach ($ierrors as $error) {
|
||||||
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if invoice already exists for JO
|
||||||
|
$old_invoice = $jo->getInvoice();
|
||||||
|
if ($old_invoice != null)
|
||||||
|
{
|
||||||
|
// remove old invoice
|
||||||
|
$this->em->remove($old_invoice);
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add invoice to JO
|
||||||
|
$jo->setInvoice($invoice);
|
||||||
|
|
||||||
|
$this->em->persist($invoice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is called by JobOrderController when JS script generateInvoice is called
|
||||||
|
public function generateDraftInvoice($criteria, $promo_id, $service_charges, $items)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// called by the following:
|
||||||
|
// (1) JobOrderController when JS script generateInvoice is called
|
||||||
|
// (2) APIController from newRequestJobOrder
|
||||||
|
// (3) generateInvoiceCriteria
|
||||||
|
// (4) RiderAPIHandler's changeService
|
||||||
|
// (5) TAPI's JobOrderController
|
||||||
|
public function generateInvoice($criteria)
|
||||||
|
{
|
||||||
|
// no need to validate since generateDraftInvoice was called before this was called
|
||||||
|
// generate the invoice and from APIController, the fields were validated
|
||||||
|
$invoice_data = $this->compute($criteria);
|
||||||
|
|
||||||
|
$invoice = $this->createInvoice($invoice_data);
|
||||||
|
|
||||||
|
$invoice_items = $invoice->getItems();
|
||||||
|
|
||||||
|
return $invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compute($criteria)
|
||||||
|
{
|
||||||
|
// initialize
|
||||||
|
$total = [
|
||||||
|
'sell_price' => 0.0,
|
||||||
|
'vat' => 0.0,
|
||||||
|
'vat_ex_price' => 0.0,
|
||||||
|
'ti_rate' => 0.0,
|
||||||
|
'total_price' => 0.0,
|
||||||
|
'discount' => 0.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
// get what is in criteria
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
$entries = $criteria->getEntries();
|
||||||
|
$promos = $criteria->getPromos();
|
||||||
|
$is_taxable = $criteria->isTaxable();
|
||||||
|
|
||||||
|
$invoice_items = [];
|
||||||
|
$data = [];
|
||||||
|
foreach ($this->available_rules as $rule)
|
||||||
|
{
|
||||||
|
$items = $rule->compute($criteria, $total);
|
||||||
|
|
||||||
|
$promo = null;
|
||||||
|
|
||||||
|
if (count($items) > 0)
|
||||||
|
{
|
||||||
|
foreach ($items as $item)
|
||||||
|
{
|
||||||
|
$title = $item['title'];
|
||||||
|
$quantity = $item['qty'];
|
||||||
|
$price = $item['price'];
|
||||||
|
|
||||||
|
$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[] = [
|
||||||
|
'promo' => $promo,
|
||||||
|
'invoice_items' => $invoice_items,
|
||||||
|
'total' => $total,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createInvoice($invoice_data)
|
||||||
|
{
|
||||||
|
$invoice = new Invoice();
|
||||||
|
|
||||||
|
// get current user
|
||||||
|
$user = $this->security->getUser();
|
||||||
|
// check if user is User or APIUser
|
||||||
|
if ($user instanceof User)
|
||||||
|
{
|
||||||
|
$invoice->setCreatedBy($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($invoice_data as $data)
|
||||||
|
{
|
||||||
|
$invoice_items = $data['invoice_items'];
|
||||||
|
$total = $data['total'];
|
||||||
|
|
||||||
|
// check if promo is set
|
||||||
|
if (isset($data['promo']))
|
||||||
|
$promo = $data['promo'];
|
||||||
|
|
||||||
|
foreach ($invoice_items as $item)
|
||||||
|
{
|
||||||
|
$invoice_item = new InvoiceItem();
|
||||||
|
|
||||||
|
$invoice_item->setInvoice($invoice)
|
||||||
|
->setTitle($item['title'])
|
||||||
|
->setQuantity($item['quantity'])
|
||||||
|
->setPrice($item['price']);
|
||||||
|
|
||||||
|
if ($item['battery'] != null)
|
||||||
|
$invoice_item->setBattery($item['battery']);
|
||||||
|
|
||||||
|
$invoice->addItem($invoice_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->setTotalPrice($total['total_price'])
|
||||||
|
->setVATExclusivePrice($total['vat_ex_price'])
|
||||||
|
->setVAT($total['vat'])
|
||||||
|
->setDiscount($total['discount'])
|
||||||
|
->setTradeIn($total['ti_rate'])
|
||||||
|
->setStatus(InvoiceStatus::DRAFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,12 +29,13 @@ use App\Entity\CustomerTag;
|
||||||
use App\Entity\EmergencyType;
|
use App\Entity\EmergencyType;
|
||||||
use App\Entity\OwnershipType;
|
use App\Entity\OwnershipType;
|
||||||
use App\Entity\CustomerLocation;
|
use App\Entity\CustomerLocation;
|
||||||
|
use App\Entity\Battery;
|
||||||
|
|
||||||
use App\Ramcar\InvoiceCriteria;
|
|
||||||
use App\Ramcar\ServiceType;
|
use App\Ramcar\ServiceType;
|
||||||
use App\Ramcar\TradeInType;
|
use App\Ramcar\TradeInType;
|
||||||
use App\Ramcar\JOEventType;
|
use App\Ramcar\JOEventType;
|
||||||
use App\Ramcar\JOStatus;
|
use App\Ramcar\JOStatus;
|
||||||
|
use App\Ramcar\InvoiceCriteria;
|
||||||
use App\Ramcar\WarrantyClass;
|
use App\Ramcar\WarrantyClass;
|
||||||
use App\Ramcar\DiscountApply;
|
use App\Ramcar\DiscountApply;
|
||||||
use App\Ramcar\ModeOfPayment;
|
use App\Ramcar\ModeOfPayment;
|
||||||
|
|
@ -3487,8 +3488,19 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
||||||
|
|
||||||
// db loaded
|
// db loaded
|
||||||
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
|
$params['bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
|
||||||
|
$params['trade_in_bmfgs'] = $em->getRepository(BatteryManufacturer::class)->findAll();
|
||||||
$params['promos'] = $em->getRepository(Promo::class)->findAll();
|
$params['promos'] = $em->getRepository(Promo::class)->findAll();
|
||||||
|
|
||||||
|
// list of batteries for trade-in
|
||||||
|
$ti_batteries = $em->getRepository(Battery::class)->findAll();
|
||||||
|
$trade_in_batteries = [];
|
||||||
|
foreach ($ti_batteries as $ti_battery)
|
||||||
|
{
|
||||||
|
$battery_name = $ti_battery->getModel()->getName() . ' ' . $ti_battery->getSize()->getName();
|
||||||
|
$trade_in_batteries[$ti_battery->getID()] = $battery_name;
|
||||||
|
}
|
||||||
|
$params['trade_in_batteries'] = $trade_in_batteries;
|
||||||
|
|
||||||
// list of emergency types
|
// list of emergency types
|
||||||
$e_types = $em->getRepository(EmergencyType::class)->findBy([], ['name' => 'ASC']);
|
$e_types = $em->getRepository(EmergencyType::class)->findBy([], ['name' => 'ASC']);
|
||||||
$emergency_types = [];
|
$emergency_types = [];
|
||||||
|
|
|
||||||
|
|
@ -866,6 +866,9 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface
|
||||||
$crit->setCustomerVehicle($cv);
|
$crit->setCustomerVehicle($cv);
|
||||||
$crit->setHasCoolant($jo->hasCoolant());
|
$crit->setHasCoolant($jo->hasCoolant());
|
||||||
|
|
||||||
|
// set istaxable
|
||||||
|
$crit->setIsTaxable();
|
||||||
|
|
||||||
if ($promo != null)
|
if ($promo != null)
|
||||||
$crit->addPromo($promo);
|
$crit->addPromo($promo);
|
||||||
|
|
||||||
|
|
|
||||||
46
templates/invoice/trade_in.html.twig
Normal file
46
templates/invoice/trade_in.html.twig
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<div class="form-group m-form__group row">
|
||||||
|
<div class="col-lg-1 hide">
|
||||||
|
<label for="invoice-trade-in-bmfg">Manufacturer</label>
|
||||||
|
<select class="form-control m-input" id="invoice-trade-in-bmfg">
|
||||||
|
{% for manufacturer in trade_in_bmfgs %}
|
||||||
|
<option value="{{ manufacturer.getID() }}">{{ manufacturer.getName() }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<label for="invoice-trade-in-battery">Battery For Trade In</label>
|
||||||
|
<select class="form-control m-input" id="invoice-trade-in-battery" data-value="">
|
||||||
|
<option value=""></option>
|
||||||
|
{% for id, battery_name in trade_in_batteries %}
|
||||||
|
<option value="{{ id }}">{{ battery_name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-2">
|
||||||
|
<label for="invoice-trade-in-type">Trade In</label>
|
||||||
|
<select class="form-control m-input" name="invoice_trade_in_type" id="invoice-trade-in-type">
|
||||||
|
<option value="">None</option>
|
||||||
|
{% for key, type in trade_in_types %}
|
||||||
|
<option value="{{ key }}">{{ type }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-2">
|
||||||
|
<label data-field="no_trade_in_reason">No Trade In Reason</label>
|
||||||
|
<select class="form-control m-input" id="no-trade-in-reason" name="no_trade_in_reason">
|
||||||
|
<option value="">Select reason</option>
|
||||||
|
{% for key, class in no_trade_in_reasons %}
|
||||||
|
<option value="{{ key }}"{{ obj.getNoTradeInReason == key ? ' selected' }}>{{ class }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<div class="form-control-feedback hide" data-field="no_trade_in_reason"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1">
|
||||||
|
<label for="invoice-trade-in-quantity">Quantity</label>
|
||||||
|
<input type="text" id="invoice-trade-in-quantity" class="form-control m-input text-right" value="1">
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div><label> </label></div>
|
||||||
|
<button type="button" class="btn btn-primary" id="btn-add-trade-in-to-invoice">Add</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
17
templates/invoice/trade_in.js.twig
Normal file
17
templates/invoice/trade_in.js.twig
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
// add trade in battery to invoice
|
||||||
|
$('#btn-add-trade-in-to-invoice').click(function() {
|
||||||
|
var bmfg = $("#invoice-trade-in-bmfg").val();
|
||||||
|
var battery = $("#invoice-trade-in-battery").val();
|
||||||
|
var tradeIn = $("#invoice-trade-in-type").val();
|
||||||
|
var qty = $("#invoice-trade-in-quantity").val();
|
||||||
|
|
||||||
|
// add to invoice array
|
||||||
|
invoiceItems.push({
|
||||||
|
battery: battery,
|
||||||
|
quantity: qty,
|
||||||
|
trade_in: tradeIn,
|
||||||
|
});
|
||||||
|
|
||||||
|
// regenerate the invoice
|
||||||
|
generateInvoice();
|
||||||
|
});
|
||||||
|
|
@ -715,6 +715,7 @@
|
||||||
<option value="">Select a vehicle and manufacturer first</option>
|
<option value="">Select a vehicle and manufacturer first</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<!--
|
||||||
<div class="col-lg-2">
|
<div class="col-lg-2">
|
||||||
<label for="invoice-trade-in-type">Trade In</label>
|
<label for="invoice-trade-in-type">Trade In</label>
|
||||||
<select class="form-control m-input" name="invoice_trade_in_type" id="invoice-trade-in-type">
|
<select class="form-control m-input" name="invoice_trade_in_type" id="invoice-trade-in-type">
|
||||||
|
|
@ -734,6 +735,7 @@
|
||||||
</select>
|
</select>
|
||||||
<div class="form-control-feedback hide" data-field="no_trade_in_reason"></div>
|
<div class="form-control-feedback hide" data-field="no_trade_in_reason"></div>
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
<div class="col-lg-1">
|
<div class="col-lg-1">
|
||||||
<label for="invoice-quantity">Quantity</label>
|
<label for="invoice-quantity">Quantity</label>
|
||||||
|
|
@ -748,6 +750,7 @@
|
||||||
<button type="button" class="btn btn-danger" id="btn-reset-invoice">Reset</button>
|
<button type="button" class="btn btn-danger" id="btn-reset-invoice">Reset</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% include('invoice/trade_in.html.twig') %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -1190,7 +1193,6 @@
|
||||||
<script src="/assets/vendors/custom/gmaps/gmaps.js" type="text/javascript"></script>
|
<script src="/assets/vendors/custom/gmaps/gmaps.js" type="text/javascript"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
// location search autocomplete
|
// location search autocomplete
|
||||||
var input = document.getElementById('m_gmap_address');
|
var input = document.getElementById('m_gmap_address');
|
||||||
|
|
||||||
|
|
@ -1686,11 +1688,13 @@ $(function() {
|
||||||
|
|
||||||
var invoiceItems = [];
|
var invoiceItems = [];
|
||||||
|
|
||||||
|
{% include 'invoice/trade_in.js.twig' %}
|
||||||
|
|
||||||
// add to invoice
|
// add to invoice
|
||||||
$("#btn-add-to-invoice").click(function() {
|
$("#btn-add-to-invoice").click(function() {
|
||||||
var bmfg = $("#invoice-bmfg").val();
|
var bmfg = $("#invoice-bmfg").val();
|
||||||
var battery = $("#invoice-battery").val();
|
var battery = $("#invoice-battery").val();
|
||||||
var tradeIn = $("#invoice-trade-in-type").val();
|
// var tradeIn = $("#invoice-trade-in-type").val();
|
||||||
var qty = $("#invoice-quantity").val();
|
var qty = $("#invoice-quantity").val();
|
||||||
|
|
||||||
if (!bmfg || !battery || !qty) {
|
if (!bmfg || !battery || !qty) {
|
||||||
|
|
@ -1714,10 +1718,12 @@ $(function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to invoice array
|
// add to invoice array
|
||||||
|
// TODO: need to figure out how to push battery and tradein separately
|
||||||
|
// right now, battery and trade in is one entry. Need to separate that into two entries
|
||||||
invoiceItems.push({
|
invoiceItems.push({
|
||||||
battery: battery,
|
battery: battery,
|
||||||
quantity: qty,
|
quantity: qty,
|
||||||
trade_in: tradeIn,
|
trade_in: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
// regenerate the invoice
|
// regenerate the invoice
|
||||||
|
|
@ -1752,6 +1758,8 @@ $(function() {
|
||||||
var stype = $("#service_type").val();
|
var stype = $("#service_type").val();
|
||||||
var cvid = $("#customer-vehicle").val();
|
var cvid = $("#customer-vehicle").val();
|
||||||
|
|
||||||
|
console.log(JSON.stringify(invoiceItems));
|
||||||
|
|
||||||
// generate invoice values
|
// generate invoice values
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue