Merge branch 'origin/265-cmb-project' into '270-final-cmb-fixes'
Move origin/265 to 270 See merge request jankstudio/resq!317
This commit is contained in:
commit
6c3bc652fa
10 changed files with 1111 additions and 269 deletions
|
|
@ -130,3 +130,15 @@ services:
|
||||||
$menu_name: "main_menu"
|
$menu_name: "main_menu"
|
||||||
tags:
|
tags:
|
||||||
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
|
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
|
||||||
|
|
||||||
|
# invoice generator
|
||||||
|
App\Service\InvoiceGenerator\CMBInvoiceGenerator: ~
|
||||||
|
|
||||||
|
# invoice generator interface
|
||||||
|
App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\CMBInvoiceGenerator"
|
||||||
|
|
||||||
|
# job order generator
|
||||||
|
App\Service\JobOrderGenerator\CMBJobOrderGenerator: ~
|
||||||
|
|
||||||
|
#job order generator interface
|
||||||
|
App\Service\JobOrderGeneratorInterface: "@App\\Service\\JobOrderGenerator\\CMBJobOrderGenerator"
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ use App\Ramcar\TransactionOrigin;
|
||||||
use App\Ramcar\TradeInType;
|
use App\Ramcar\TradeInType;
|
||||||
use App\Ramcar\JOEventType;
|
use App\Ramcar\JOEventType;
|
||||||
|
|
||||||
use App\Service\InvoiceCreator;
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
use App\Service\RisingTideGateway;
|
use App\Service\RisingTideGateway;
|
||||||
use App\Service\MQTTClient;
|
use App\Service\MQTTClient;
|
||||||
use App\Service\GeofenceTracker;
|
use App\Service\GeofenceTracker;
|
||||||
|
|
@ -808,7 +808,7 @@ class APIController extends Controller
|
||||||
return $res->getReturnResponse();
|
return $res->getReturnResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function requestJobOrder(Request $req, InvoiceCreator $ic, GeofenceTracker $geo)
|
public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo)
|
||||||
{
|
{
|
||||||
// check required parameters and api key
|
// check required parameters and api key
|
||||||
$required_params = [
|
$required_params = [
|
||||||
|
|
@ -973,7 +973,7 @@ class APIController extends Controller
|
||||||
$icrit->addEntry($batt, $trade_in, 1);
|
$icrit->addEntry($batt, $trade_in, 1);
|
||||||
|
|
||||||
// send to invoice generator
|
// send to invoice generator
|
||||||
$invoice = $ic->processCriteria($icrit);
|
$invoice = $ic->generateInvoice($icrit);
|
||||||
$jo->setInvoice($invoice);
|
$jo->setInvoice($invoice);
|
||||||
|
|
||||||
$em->persist($jo);
|
$em->persist($jo);
|
||||||
|
|
@ -1020,7 +1020,7 @@ class APIController extends Controller
|
||||||
return $res->getReturnResponse();
|
return $res->getReturnResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEstimate(Request $req, InvoiceCreator $ic)
|
public function getEstimate(Request $req, InvoiceGeneratorInterface $ic)
|
||||||
{
|
{
|
||||||
// $this->debugRequest($req);
|
// $this->debugRequest($req);
|
||||||
|
|
||||||
|
|
@ -1120,7 +1120,7 @@ class APIController extends Controller
|
||||||
$icrit->addEntry($batt, $trade_in, 1);
|
$icrit->addEntry($batt, $trade_in, 1);
|
||||||
|
|
||||||
// send to invoice generator
|
// send to invoice generator
|
||||||
$invoice = $ic->processCriteria($icrit);
|
$invoice = $ic->generateInvoice($icrit);
|
||||||
|
|
||||||
// make invoice json data
|
// make invoice json data
|
||||||
$data = [
|
$data = [
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ use App\Ramcar\WarrantyClass;
|
||||||
use App\Ramcar\DiscountApply;
|
use App\Ramcar\DiscountApply;
|
||||||
use App\Ramcar\TradeInType;
|
use App\Ramcar\TradeInType;
|
||||||
use App\Ramcar\InvoiceCriteria;
|
use App\Ramcar\InvoiceCriteria;
|
||||||
use App\Ramcar\InvoiceStatus;
|
|
||||||
use App\Ramcar\ModeOfPayment;
|
use App\Ramcar\ModeOfPayment;
|
||||||
use App\Ramcar\TransactionOrigin;
|
use App\Ramcar\TransactionOrigin;
|
||||||
use App\Ramcar\JOEventType;
|
use App\Ramcar\JOEventType;
|
||||||
|
|
@ -27,7 +26,8 @@ use App\Entity\Battery;
|
||||||
use App\Entity\JOEvent;
|
use App\Entity\JOEvent;
|
||||||
use App\Entity\JORejection;
|
use App\Entity\JORejection;
|
||||||
|
|
||||||
use App\Service\InvoiceCreator;
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
|
use App\Service\JobOrderGeneratorInterface;
|
||||||
use App\Service\MapTools;
|
use App\Service\MapTools;
|
||||||
use App\Service\HubCounter;
|
use App\Service\HubCounter;
|
||||||
use App\Service\MQTTClient;
|
use App\Service\MQTTClient;
|
||||||
|
|
@ -251,7 +251,7 @@ class JobOrderController extends Controller
|
||||||
return $this->render('job-order/form.html.twig', $params);
|
return $this->render('job-order/form.html.twig', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function openEditSubmit(Request $req, ValidatorInterface $validator, InvoiceCreator $ic, $id)
|
public function openEditSubmit(Request $req, ValidatorInterface $validator, JobOrderGeneratorInterface $joc, $id)
|
||||||
{
|
{
|
||||||
$this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.');
|
$this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.');
|
||||||
|
|
||||||
|
|
@ -297,69 +297,11 @@ class JobOrderController extends Controller
|
||||||
// did they change invoice?
|
// did they change invoice?
|
||||||
$invoice_items = $req->request->get('invoice_items', []);
|
$invoice_items = $req->request->get('invoice_items', []);
|
||||||
$invoice_change = $req->request->get('invoice_change', 0);
|
$invoice_change = $req->request->get('invoice_change', 0);
|
||||||
if ($invoice_change)
|
$promo_id = $req->request->get('invoice_promo');
|
||||||
{
|
|
||||||
// instantiate invoice criteria
|
|
||||||
$criteria = new InvoiceCriteria();
|
|
||||||
$criteria->setServiceType($stype)
|
|
||||||
->setCustomerVehicle($obj->getCustomerVehicle());
|
|
||||||
|
|
||||||
$ierror = $this->invoicePromo($em, $criteria, $req->request->get('invoice_promo'));
|
// call service to generate job order and invoice
|
||||||
|
$joc->generateJobOrder($obj, $promo_id, $invoice_change, $invoice_items, $error_array);
|
||||||
|
|
||||||
// check for trade in so we can mark it for mobile app
|
|
||||||
foreach ($invoice_items as $item)
|
|
||||||
{
|
|
||||||
// get first trade-in
|
|
||||||
if (!empty($item['trade_in']))
|
|
||||||
{
|
|
||||||
$obj->setTradeInType($item['trade_in']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$ierror)
|
|
||||||
$ierror = $this->invoiceBatteries($em, $criteria, $invoice_items);
|
|
||||||
|
|
||||||
if ($ierror)
|
|
||||||
{
|
|
||||||
$error_array['invoice'] = $ierror;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// generate the invoice
|
|
||||||
$iobj = $ic->processCriteria($criteria);
|
|
||||||
$iobj->setStatus(InvoiceStatus::DRAFT)
|
|
||||||
->setCreatedBy($this->getUser());
|
|
||||||
|
|
||||||
// validate
|
|
||||||
$ierrors = $validator->validate($iobj);
|
|
||||||
|
|
||||||
// add errors to list
|
|
||||||
foreach ($ierrors as $error) {
|
|
||||||
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove previous invoice
|
|
||||||
$old_invoice = $obj->getInvoice();
|
|
||||||
$em->remove($old_invoice);
|
|
||||||
$em->flush();
|
|
||||||
|
|
||||||
// add invoice to JO
|
|
||||||
$obj->setInvoice($iobj);
|
|
||||||
|
|
||||||
// persist invoice
|
|
||||||
$em->persist($iobj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// validate
|
|
||||||
$errors = $validator->validate($obj);
|
|
||||||
|
|
||||||
// add errors to list
|
|
||||||
foreach ($errors as $error) {
|
|
||||||
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if any errors were found
|
// check if any errors were found
|
||||||
|
|
@ -371,17 +313,6 @@ class JobOrderController extends Controller
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the event
|
|
||||||
$event = new JOEvent();
|
|
||||||
$event->setDateHappen(new DateTime())
|
|
||||||
->setTypeID(JOEventType::OPEN_EDIT)
|
|
||||||
->setUser($this->getUser())
|
|
||||||
->setJobOrder($obj);
|
|
||||||
$em->persist($event);
|
|
||||||
|
|
||||||
// validated! save the entity
|
|
||||||
$em->flush();
|
|
||||||
|
|
||||||
// return successful response
|
// return successful response
|
||||||
return $this->json([
|
return $this->json([
|
||||||
'success' => 'Changes have been saved!'
|
'success' => 'Changes have been saved!'
|
||||||
|
|
@ -425,7 +356,8 @@ class JobOrderController extends Controller
|
||||||
return $this->render('job-order/form.html.twig', $params);
|
return $this->render('job-order/form.html.twig', $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function incomingSubmit(Request $req, ValidatorInterface $validator, InvoiceCreator $ic)
|
public function incomingSubmit(Request $req, ValidatorInterface $validator,
|
||||||
|
JobOrderGeneratorInterface $joc)
|
||||||
{
|
{
|
||||||
$this->denyAccessUnlessGranted('jo_in.list', null, 'No access.');
|
$this->denyAccessUnlessGranted('jo_in.list', null, 'No access.');
|
||||||
|
|
||||||
|
|
@ -491,63 +423,12 @@ class JobOrderController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// instantiate invoice criteria
|
// call service to generate job order and invoice
|
||||||
$criteria = new InvoiceCriteria();
|
$invoice_items = $req->request->get('invoice_items', []);
|
||||||
$criteria->setServiceType($stype)
|
$promo_id = $req->request->get('invoice_promo');
|
||||||
->setCustomerVehicle($cust_vehicle);
|
$invoice_change = true;
|
||||||
|
|
||||||
$ierror = $this->invoicePromo($em, $criteria, $req->request->get('invoice_promo'));
|
$joc->generateJobOrder($obj, $promo_id, $invoice_change, $invoice_items, $error_array);
|
||||||
$invoice_items = $req->request->get('invoice_items');
|
|
||||||
|
|
||||||
if (!$ierror && !empty($invoice_items))
|
|
||||||
{
|
|
||||||
// check for trade in so we can mark it for mobile app
|
|
||||||
foreach ($invoice_items as $item)
|
|
||||||
{
|
|
||||||
// get first trade-in
|
|
||||||
if (!empty($item['trade_in']))
|
|
||||||
{
|
|
||||||
$obj->setTradeInType($item['trade_in']);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$ierror = $this->invoiceBatteries($em, $criteria, $invoice_items);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ierror)
|
|
||||||
{
|
|
||||||
$error_array['invoice'] = $ierror;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// generate the invoice
|
|
||||||
$iobj = $ic->processCriteria($criteria);
|
|
||||||
$iobj->setStatus(InvoiceStatus::DRAFT)
|
|
||||||
->setCreatedBy($this->getUser());
|
|
||||||
|
|
||||||
// validate
|
|
||||||
$ierrors = $validator->validate($iobj);
|
|
||||||
|
|
||||||
// add errors to list
|
|
||||||
foreach ($ierrors as $error) {
|
|
||||||
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// add invoice to JO
|
|
||||||
$obj->setInvoice($iobj);
|
|
||||||
|
|
||||||
// save
|
|
||||||
$em->persist($iobj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate
|
|
||||||
$errors = $validator->validate($obj);
|
|
||||||
|
|
||||||
// add errors to list
|
|
||||||
foreach ($errors as $error) {
|
|
||||||
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if any errors were found
|
// check if any errors were found
|
||||||
|
|
@ -559,19 +440,6 @@ class JobOrderController extends Controller
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
// validated! save the entity
|
|
||||||
$em->persist($obj);
|
|
||||||
|
|
||||||
// the event
|
|
||||||
$event = new JOEvent();
|
|
||||||
$event->setDateHappen(new DateTime())
|
|
||||||
->setTypeID(JOEventType::CREATE)
|
|
||||||
->setUser($this->getUser())
|
|
||||||
->setJobOrder($obj);
|
|
||||||
$em->persist($event);
|
|
||||||
|
|
||||||
$em->flush();
|
|
||||||
|
|
||||||
// return successful response
|
// return successful response
|
||||||
return $this->json([
|
return $this->json([
|
||||||
'success' => 'Changes have been saved!'
|
'success' => 'Changes have been saved!'
|
||||||
|
|
@ -2482,7 +2350,7 @@ class JobOrderController extends Controller
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateInvoice(Request $req, InvoiceCreator $ic)
|
public function generateInvoice(Request $req, InvoiceGeneratorInterface $ic)
|
||||||
{
|
{
|
||||||
// error_log('generating invoice...');
|
// error_log('generating invoice...');
|
||||||
$error = false;
|
$error = false;
|
||||||
|
|
@ -2548,7 +2416,7 @@ class JobOrderController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate the invoice
|
// generate the invoice
|
||||||
$iobj = $ic->processCriteria($criteria);
|
$iobj = $ic->generateInvoice($criteria);
|
||||||
|
|
||||||
// use invoice object values in a json friendly array
|
// use invoice object values in a json friendly array
|
||||||
$invoice = [
|
$invoice = [
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ use App\Ramcar\InvoiceStatus;
|
||||||
use App\Ramcar\ModeOfPayment;
|
use App\Ramcar\ModeOfPayment;
|
||||||
use App\Ramcar\JOEventType;
|
use App\Ramcar\JOEventType;
|
||||||
|
|
||||||
use App\Service\InvoiceCreator;
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
use App\Service\MQTTClient;
|
use App\Service\MQTTClient;
|
||||||
|
|
||||||
use App\Entity\RiderSession;
|
use App\Entity\RiderSession;
|
||||||
|
|
@ -739,7 +739,7 @@ class RAPIController extends Controller
|
||||||
error_log(print_r($all, true));
|
error_log(print_r($all, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function changeService(Request $req, InvoiceCreator $ic)
|
public function changeService(Request $req, InvoiceGeneratorInterface $ic)
|
||||||
{
|
{
|
||||||
$this->debugRequest($req);
|
$this->debugRequest($req);
|
||||||
|
|
||||||
|
|
@ -839,8 +839,7 @@ class RAPIController extends Controller
|
||||||
error_log('adding entry for battery - ' . $battery->getID());
|
error_log('adding entry for battery - ' . $battery->getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoice = $ic->processCriteria($crit);
|
$invoice = $ic->generateInvoice($crit);
|
||||||
$invoice->setStatus(InvoiceStatus::DRAFT);
|
|
||||||
|
|
||||||
// remove previous invoice
|
// remove previous invoice
|
||||||
$old_invoice = $jo->getInvoice();
|
$old_invoice = $jo->getInvoice();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service\InvoiceGenerator;
|
||||||
|
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
use App\Ramcar\InvoiceCriteria;
|
use App\Ramcar\InvoiceCriteria;
|
||||||
|
use App\Ramcar\InvoiceStatus;
|
||||||
use App\Ramcar\TradeInType;
|
use App\Ramcar\TradeInType;
|
||||||
use App\Ramcar\DiscountApply;
|
use App\Ramcar\DiscountApply;
|
||||||
use App\Ramcar\ServiceType;
|
use App\Ramcar\ServiceType;
|
||||||
|
|
@ -12,31 +15,125 @@ use App\Entity\Invoice;
|
||||||
use App\Entity\InvoiceItem;
|
use App\Entity\InvoiceItem;
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
|
|
||||||
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
|
|
||||||
use Doctrine\Common\Util\Debug;
|
use Doctrine\Common\Util\Debug;
|
||||||
|
|
||||||
class InvoiceCreator
|
class CMBInvoiceGenerator implements InvoiceGeneratorInterface
|
||||||
{
|
{
|
||||||
const VAT_RATE = 0.12;
|
const TAX_RATE = 0.00;
|
||||||
const SERVICE_FEE = 300;
|
const SERVICE_FEE = 300;
|
||||||
|
const RECHARGE_FEE = 300;
|
||||||
|
const TROUBLESHOOTING_FEE = 150;
|
||||||
|
const BATT_REPLACEMENT_FEE = 0;
|
||||||
|
const WARRANTY_FEE = 0;
|
||||||
|
const OTHER_SERVICES_FEE = 200;
|
||||||
|
const COOLANT_FEE = 1600;
|
||||||
|
const REFUEL_FEE_GAS = 260;
|
||||||
|
const REFUEL_FEE_DIESEL = 220;
|
||||||
|
|
||||||
|
private $security;
|
||||||
|
|
||||||
// creates invoice based on the criteria sent
|
// creates invoice based on the criteria sent
|
||||||
public function __construct()
|
public function __construct(Security $security)
|
||||||
{
|
{
|
||||||
|
$this->security = $security;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVATAmount($price)
|
public function generateInvoice(InvoiceCriteria $criteria)
|
||||||
{
|
{
|
||||||
$vat_ex_price = $this->getVATExclusivePrice($price);
|
// initialize
|
||||||
|
$invoice = new Invoice();
|
||||||
|
$total = [
|
||||||
|
'sell_price' => 0.0,
|
||||||
|
'vat' => 0.0,
|
||||||
|
'vat_ex_price' => 0.0,
|
||||||
|
'ti_rate' => 0.0,
|
||||||
|
'total_price' => 0.0,
|
||||||
|
'discount' => 0.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
$cv = $criteria->getCustomerVehicle();
|
||||||
|
$has_coolant = $criteria->hasCoolant();
|
||||||
|
// error_log($stype);
|
||||||
|
switch ($stype)
|
||||||
|
{
|
||||||
|
case ServiceType::JUMPSTART_TROUBLESHOOT:
|
||||||
|
$this->processJumpstart($total, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::JUMPSTART_WARRANTY:
|
||||||
|
$this->processJumpstartWarranty($total, $invoice);
|
||||||
|
|
||||||
|
case ServiceType::BATTERY_REPLACEMENT_NEW:
|
||||||
|
$this->processEntries($total, $criteria, $invoice);
|
||||||
|
/*
|
||||||
|
$this->processBatteries($total, $criteria, $invoice);
|
||||||
|
$this->processTradeIns($total, $criteria, $invoice);
|
||||||
|
*/
|
||||||
|
$this->processDiscount($total, $criteria, $invoice);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ServiceType::BATTERY_REPLACEMENT_WARRANTY:
|
||||||
|
$this->processWarranty($total, $criteria, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::POST_RECHARGED:
|
||||||
|
$this->processRecharge($total, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::POST_REPLACEMENT:
|
||||||
|
$this->processReplacement($total, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::TIRE_REPAIR:
|
||||||
|
$this->processTireRepair($total, $invoice, $cv);
|
||||||
|
// $this->processOtherServices($total, $invoice, $stype);
|
||||||
|
break;
|
||||||
|
case ServiceType::OVERHEAT_ASSISTANCE:
|
||||||
|
$this->processOverheat($total, $invoice, $cv, $has_coolant);
|
||||||
|
break;
|
||||||
|
case ServiceType::EMERGENCY_REFUEL:
|
||||||
|
error_log('processing refuel');
|
||||||
|
$ftype = $criteria->getCustomerVehicle()->getFuelType();
|
||||||
|
$this->processRefuel($total, $invoice, $cv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check if any promo is applied
|
||||||
|
// apply discounts
|
||||||
|
$promos = $criteria->getPromos();
|
||||||
|
|
||||||
|
// get current user
|
||||||
|
$user = $this->security->getUser();
|
||||||
|
if ($user != null)
|
||||||
|
{
|
||||||
|
$invoice->setCreatedBy($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->setTotalPrice($total['total_price'])
|
||||||
|
->setVATExclusivePrice($total['vat_ex_price'])
|
||||||
|
->setVAT($total['vat'])
|
||||||
|
->setDiscount($total['discount'])
|
||||||
|
->setTradeIn($total['ti_rate'])
|
||||||
|
->setStatus(InvoiceStatus::DRAFT);
|
||||||
|
|
||||||
|
// dump
|
||||||
|
//Debug::dump($invoice, 1);
|
||||||
|
|
||||||
|
return $invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTaxAmount($price)
|
||||||
|
{
|
||||||
|
$vat_ex_price = $this->getTaxExclusivePrice($price);
|
||||||
return $price - $vat_ex_price;
|
return $price - $vat_ex_price;
|
||||||
// return round($vat_ex_price * self::VAT_RATE, 2);
|
// return round($vat_ex_price * self::TAX_RATE, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVATExclusivePrice($price)
|
protected function getTaxExclusivePrice($price)
|
||||||
{
|
{
|
||||||
return round($price / (1 + self::VAT_RATE), 2);
|
return round($price / (1 + self::TAX_RATE), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTradeInRate($ti)
|
protected function getTradeInRate($ti)
|
||||||
{
|
{
|
||||||
$size = $ti['size'];
|
$size = $ti['size'];
|
||||||
$trade_in = $ti['trade_in'];
|
$trade_in = $ti['trade_in'];
|
||||||
|
|
@ -109,8 +206,8 @@ class InvoiceCreator
|
||||||
$qty = $con_data['qty'];
|
$qty = $con_data['qty'];
|
||||||
|
|
||||||
$sell_price = $batt->getSellingPrice();
|
$sell_price = $batt->getSellingPrice();
|
||||||
$vat = $this->getVATAmount($sell_price);
|
$vat = $this->getTaxAmount($sell_price);
|
||||||
// $vat_ex_price = $this->getVATExclusivePrice($sell_price);
|
// $vat_ex_price = $this->getTaxExclusivePrice($sell_price);
|
||||||
|
|
||||||
$total['sell_price'] += $sell_price * $qty;
|
$total['sell_price'] += $sell_price * $qty;
|
||||||
$total['vat'] += $vat * $qty;
|
$total['vat'] += $vat * $qty;
|
||||||
|
|
@ -192,22 +289,22 @@ class InvoiceCreator
|
||||||
$invoice->setPromo($promo);
|
$invoice->setPromo($promo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processJumpstart(&$total, $invoice)
|
protected function processJumpstart(&$total, $invoice)
|
||||||
{
|
{
|
||||||
// add troubleshooting fee
|
// add troubleshooting fee
|
||||||
$item = new InvoiceItem();
|
$item = new InvoiceItem();
|
||||||
$item->setInvoice($invoice)
|
$item->setInvoice($invoice)
|
||||||
->setTitle('Troubleshooting fee')
|
->setTitle('Troubleshooting fee')
|
||||||
->setQuantity(1)
|
->setQuantity(1)
|
||||||
->setPrice(150.00);
|
->setPrice(self::TROUBLESHOOTING_FEE);
|
||||||
$invoice->addItem($item);
|
$invoice->addItem($item);
|
||||||
|
|
||||||
$total['sell_price'] = 150.00;
|
$total['sell_price'] = self::TROUBLESHOOTING_FEE;
|
||||||
$total['vat_ex_price'] = 150.00;
|
$total['vat_ex_price'] = self::TROUBLESHOOTING_FEE;
|
||||||
$total['total_price'] = 150.00;
|
$total['total_price'] = self::TROUBLESHOOTING_FEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processJumpstartWarranty(&$total, $invoice)
|
protected function processJumpstartWarranty(&$total, $invoice)
|
||||||
{
|
{
|
||||||
$item = new InvoiceItem();
|
$item = new InvoiceItem();
|
||||||
$item->setInvoice($invoice)
|
$item->setInvoice($invoice)
|
||||||
|
|
@ -217,33 +314,33 @@ class InvoiceCreator
|
||||||
$invoice->addItem($item);
|
$invoice->addItem($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRecharge(&$total, $invoice)
|
protected function processRecharge(&$total, $invoice)
|
||||||
{
|
{
|
||||||
// add recharge fee
|
// add recharge fee
|
||||||
$item = new InvoiceItem();
|
$item = new InvoiceItem();
|
||||||
$item->setInvoice($invoice)
|
$item->setInvoice($invoice)
|
||||||
->setTitle('Recharge fee')
|
->setTitle('Recharge fee')
|
||||||
->setQuantity(1)
|
->setQuantity(1)
|
||||||
->setPrice(300.00);
|
->setPrice(self::RECHARGE_FEE);
|
||||||
$invoice->addItem($item);
|
$invoice->addItem($item);
|
||||||
|
|
||||||
$total['sell_price'] = 300.00;
|
$total['sell_price'] = self::RECHARGE_FEE;
|
||||||
$total['vat_ex_price'] = 300.00;
|
$total['vat_ex_price'] = self::RECHARGE_FEE;
|
||||||
$total['total_price'] = 300.00;
|
$total['total_price'] = self::RECHARGE_FEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processReplacement(&$total, $invoice)
|
protected function processReplacement(&$total, $invoice)
|
||||||
{
|
{
|
||||||
// add recharge fee
|
// add recharge fee
|
||||||
$item = new InvoiceItem();
|
$item = new InvoiceItem();
|
||||||
$item->setInvoice($invoice)
|
$item->setInvoice($invoice)
|
||||||
->setTitle('Battery replacement')
|
->setTitle('Battery replacement')
|
||||||
->setQuantity(1)
|
->setQuantity(1)
|
||||||
->setPrice(0.00);
|
->setPrice(self::BATT_REPLACEMENT_FEE);
|
||||||
$invoice->addItem($item);
|
$invoice->addItem($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processWarranty(&$total, InvoiceCriteria $criteria, $invoice)
|
protected function processWarranty(&$total, InvoiceCriteria $criteria, $invoice)
|
||||||
{
|
{
|
||||||
// error_log('processing warranty');
|
// error_log('processing warranty');
|
||||||
$entries = $criteria->getEntries();
|
$entries = $criteria->getEntries();
|
||||||
|
|
@ -254,25 +351,25 @@ class InvoiceCreator
|
||||||
$item->setInvoice($invoice)
|
$item->setInvoice($invoice)
|
||||||
->setTitle($batt->getModel()->getName() . ' ' . $batt->getSize()->getName() . ' - Service Unit')
|
->setTitle($batt->getModel()->getName() . ' ' . $batt->getSize()->getName() . ' - Service Unit')
|
||||||
->setQuantity(1)
|
->setQuantity(1)
|
||||||
->setPrice(0.00)
|
->setPrice(self::WARRANTY_FEE)
|
||||||
->setBattery($batt);
|
->setBattery($batt);
|
||||||
$invoice->addItem($item);
|
$invoice->addItem($item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processOtherServices(&$total, $invoice, $stype)
|
protected function processOtherServices(&$total, $invoice, $stype)
|
||||||
{
|
{
|
||||||
$item = new InvoiceItem();
|
$item = new InvoiceItem();
|
||||||
$item->setInvoice($invoice)
|
$item->setInvoice($invoice)
|
||||||
->setTitle('Service - ' . ServiceType::getName($stype))
|
->setTitle('Service - ' . ServiceType::getName($stype))
|
||||||
->setQuantity(1)
|
->setQuantity(1)
|
||||||
->setPrice(200.00);
|
->setPrice(self::OTHER_SERVICES_FEE);
|
||||||
$invoice->addItem($item);
|
$invoice->addItem($item);
|
||||||
|
|
||||||
$total['total_price'] = 200.00;
|
$total['total_price'] = 200.00;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processOverheat(&$total, $invoice, $cv, $has_coolant)
|
protected function processOverheat(&$total, $invoice, $cv, $has_coolant)
|
||||||
{
|
{
|
||||||
// free if they have a motolite battery
|
// free if they have a motolite battery
|
||||||
if ($cv->hasMotoliteBattery())
|
if ($cv->hasMotoliteBattery())
|
||||||
|
|
@ -295,20 +392,21 @@ class InvoiceCreator
|
||||||
$coolant->setInvoice($invoice)
|
$coolant->setInvoice($invoice)
|
||||||
->setTitle('4L Coolant')
|
->setTitle('4L Coolant')
|
||||||
->setQuantity(1)
|
->setQuantity(1)
|
||||||
->setPrice(1600);
|
->setPrice(self::COOLANT_FEE);
|
||||||
$invoice->addItem($coolant);
|
$invoice->addItem($coolant);
|
||||||
|
|
||||||
$total_price += 1600;
|
$total_price += self::COOLANT_FEE;
|
||||||
|
//$total_price += 1600;
|
||||||
}
|
}
|
||||||
|
|
||||||
$vat_ex_price = $this->getVATExclusivePrice($total_price);
|
$vat_ex_price = $this->getTaxExclusivePrice($total_price);
|
||||||
$vat = $total_price - $vat_ex_price;
|
$vat = $total_price - $vat_ex_price;
|
||||||
$total['total_price'] = $total_price;
|
$total['total_price'] = $total_price;
|
||||||
$total['vat_ex_price'] = $vat_ex_price;
|
$total['vat_ex_price'] = $vat_ex_price;
|
||||||
$total['vat'] = $vat;
|
$total['vat'] = $vat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processTireRepair(&$total, $invoice, $cv)
|
protected function processTireRepair(&$total, $invoice, $cv)
|
||||||
{
|
{
|
||||||
// free if they have a motolite battery
|
// free if they have a motolite battery
|
||||||
if ($cv->hasMotoliteBattery())
|
if ($cv->hasMotoliteBattery())
|
||||||
|
|
@ -324,14 +422,14 @@ class InvoiceCreator
|
||||||
$invoice->addItem($item);
|
$invoice->addItem($item);
|
||||||
$total_price = $fee;
|
$total_price = $fee;
|
||||||
|
|
||||||
$vat_ex_price = $this->getVATExclusivePrice($total_price);
|
$vat_ex_price = $this->getTaxExclusivePrice($total_price);
|
||||||
$vat = $total_price - $vat_ex_price;
|
$vat = $total_price - $vat_ex_price;
|
||||||
$total['total_price'] = $total_price;
|
$total['total_price'] = $total_price;
|
||||||
$total['vat_ex_price'] = $vat_ex_price;
|
$total['vat_ex_price'] = $vat_ex_price;
|
||||||
$total['vat'] = $vat;
|
$total['vat'] = $vat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRefuel(&$total, $invoice, $cv)
|
protected function processRefuel(&$total, $invoice, $cv)
|
||||||
{
|
{
|
||||||
// free if they have a motolite battery
|
// free if they have a motolite battery
|
||||||
if ($cv->hasMotoliteBattery())
|
if ($cv->hasMotoliteBattery())
|
||||||
|
|
@ -351,8 +449,8 @@ class InvoiceCreator
|
||||||
$total_price = $fee;
|
$total_price = $fee;
|
||||||
// $total['total_price'] = 200.00;
|
// $total['total_price'] = 200.00;
|
||||||
|
|
||||||
$gas_price = 260;
|
$gas_price = self::REFUEL_FEE_GAS;
|
||||||
$diesel_price = 220;
|
$diesel_price = self::REFUEL_FEE_DIESEL;
|
||||||
|
|
||||||
$fuel = new InvoiceItem();
|
$fuel = new InvoiceItem();
|
||||||
error_log('fuel type - ' . $ftype);
|
error_log('fuel type - ' . $ftype);
|
||||||
|
|
@ -385,84 +483,11 @@ class InvoiceCreator
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$vat_ex_price = $this->getVATExclusivePrice($total_price);
|
$vat_ex_price = $this->getTaxExclusivePrice($total_price);
|
||||||
$vat = $total_price - $vat_ex_price;
|
$vat = $total_price - $vat_ex_price;
|
||||||
$total['total_price'] = $total_price;
|
$total['total_price'] = $total_price;
|
||||||
$total['vat_ex_price'] = $vat_ex_price;
|
$total['vat_ex_price'] = $vat_ex_price;
|
||||||
$total['vat'] = $vat;
|
$total['vat'] = $vat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processCriteria(InvoiceCriteria $criteria)
|
|
||||||
{
|
|
||||||
// initialize
|
|
||||||
$invoice = new Invoice();
|
|
||||||
$total = [
|
|
||||||
'sell_price' => 0.0,
|
|
||||||
'vat' => 0.0,
|
|
||||||
'vat_ex_price' => 0.0,
|
|
||||||
'ti_rate' => 0.0,
|
|
||||||
'total_price' => 0.0,
|
|
||||||
'discount' => 0.0,
|
|
||||||
];
|
|
||||||
|
|
||||||
$stype = $criteria->getServiceType();
|
|
||||||
$cv = $criteria->getCustomerVehicle();
|
|
||||||
$has_coolant = $criteria->hasCoolant();
|
|
||||||
// error_log($stype);
|
|
||||||
switch ($stype)
|
|
||||||
{
|
|
||||||
case ServiceType::JUMPSTART_TROUBLESHOOT:
|
|
||||||
$this->processJumpstart($total, $invoice);
|
|
||||||
break;
|
|
||||||
case ServiceType::JUMPSTART_WARRANTY:
|
|
||||||
$this->processJumpstartWarranty($total, $invoice);
|
|
||||||
|
|
||||||
case ServiceType::BATTERY_REPLACEMENT_NEW:
|
|
||||||
$this->processEntries($total, $criteria, $invoice);
|
|
||||||
/*
|
|
||||||
$this->processBatteries($total, $criteria, $invoice);
|
|
||||||
$this->processTradeIns($total, $criteria, $invoice);
|
|
||||||
*/
|
|
||||||
$this->processDiscount($total, $criteria, $invoice);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ServiceType::BATTERY_REPLACEMENT_WARRANTY:
|
|
||||||
$this->processWarranty($total, $criteria, $invoice);
|
|
||||||
break;
|
|
||||||
case ServiceType::POST_RECHARGED:
|
|
||||||
$this->processRecharge($total, $invoice);
|
|
||||||
break;
|
|
||||||
case ServiceType::POST_REPLACEMENT:
|
|
||||||
$this->processReplacement($total, $invoice);
|
|
||||||
break;
|
|
||||||
case ServiceType::TIRE_REPAIR:
|
|
||||||
$this->processTireRepair($total, $invoice, $cv);
|
|
||||||
// $this->processOtherServices($total, $invoice, $stype);
|
|
||||||
break;
|
|
||||||
case ServiceType::OVERHEAT_ASSISTANCE:
|
|
||||||
$this->processOverheat($total, $invoice, $cv, $has_coolant);
|
|
||||||
break;
|
|
||||||
case ServiceType::EMERGENCY_REFUEL:
|
|
||||||
error_log('processing refuel');
|
|
||||||
$ftype = $criteria->getCustomerVehicle()->getFuelType();
|
|
||||||
$this->processRefuel($total, $invoice, $cv);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check if any promo is applied
|
|
||||||
// apply discounts
|
|
||||||
$promos = $criteria->getPromos();
|
|
||||||
|
|
||||||
$invoice->setTotalPrice($total['total_price'])
|
|
||||||
->setVATExclusivePrice($total['vat_ex_price'])
|
|
||||||
->setVAT($total['vat'])
|
|
||||||
->setDiscount($total['discount'])
|
|
||||||
->setTradeIn($total['ti_rate']);
|
|
||||||
|
|
||||||
|
|
||||||
// dump
|
|
||||||
//Debug::dump($invoice, 1);
|
|
||||||
|
|
||||||
return $invoice;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
493
src/Service/InvoiceGenerator/ResqInvoiceGenerator.php
Normal file
493
src/Service/InvoiceGenerator/ResqInvoiceGenerator.php
Normal file
|
|
@ -0,0 +1,493 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\InvoiceGenerator;
|
||||||
|
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
use App\Ramcar\InvoiceCriteria;
|
||||||
|
use App\Ramcar\InvoiceStatus;
|
||||||
|
use App\Ramcar\TradeInType;
|
||||||
|
use App\Ramcar\DiscountApply;
|
||||||
|
use App\Ramcar\ServiceType;
|
||||||
|
use App\Ramcar\FuelType;
|
||||||
|
|
||||||
|
use App\Entity\Invoice;
|
||||||
|
use App\Entity\InvoiceItem;
|
||||||
|
use App\Entity\User;
|
||||||
|
|
||||||
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
|
|
||||||
|
use Doctrine\Common\Util\Debug;
|
||||||
|
|
||||||
|
class ResqInvoiceGenerator implements InvoiceGeneratorInterface
|
||||||
|
{
|
||||||
|
const TAX_RATE = 0.12;
|
||||||
|
const SERVICE_FEE = 300;
|
||||||
|
const RECHARGE_FEE = 300;
|
||||||
|
const TROUBLESHOOTING_FEE = 150;
|
||||||
|
const BATT_REPLACEMENT_FEE = 0;
|
||||||
|
const WARRANTY_FEE = 0;
|
||||||
|
const OTHER_SERVICES_FEE = 200;
|
||||||
|
const COOLANT_FEE = 1600;
|
||||||
|
const REFUEL_FEE_GAS = 260;
|
||||||
|
const REFUEL_FEE_DIESEL = 220;
|
||||||
|
|
||||||
|
private $security;
|
||||||
|
|
||||||
|
// creates invoice based on the criteria sent
|
||||||
|
public function __construct(Security $security)
|
||||||
|
{
|
||||||
|
$this->security = $security;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateInvoice(InvoiceCriteria $criteria)
|
||||||
|
{
|
||||||
|
// initialize
|
||||||
|
$invoice = new Invoice();
|
||||||
|
$total = [
|
||||||
|
'sell_price' => 0.0,
|
||||||
|
'vat' => 0.0,
|
||||||
|
'vat_ex_price' => 0.0,
|
||||||
|
'ti_rate' => 0.0,
|
||||||
|
'total_price' => 0.0,
|
||||||
|
'discount' => 0.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
$cv = $criteria->getCustomerVehicle();
|
||||||
|
$has_coolant = $criteria->hasCoolant();
|
||||||
|
// error_log($stype);
|
||||||
|
switch ($stype)
|
||||||
|
{
|
||||||
|
case ServiceType::JUMPSTART_TROUBLESHOOT:
|
||||||
|
$this->processJumpstart($total, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::JUMPSTART_WARRANTY:
|
||||||
|
$this->processJumpstartWarranty($total, $invoice);
|
||||||
|
|
||||||
|
case ServiceType::BATTERY_REPLACEMENT_NEW:
|
||||||
|
$this->processEntries($total, $criteria, $invoice);
|
||||||
|
/*
|
||||||
|
$this->processBatteries($total, $criteria, $invoice);
|
||||||
|
$this->processTradeIns($total, $criteria, $invoice);
|
||||||
|
*/
|
||||||
|
$this->processDiscount($total, $criteria, $invoice);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ServiceType::BATTERY_REPLACEMENT_WARRANTY:
|
||||||
|
$this->processWarranty($total, $criteria, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::POST_RECHARGED:
|
||||||
|
$this->processRecharge($total, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::POST_REPLACEMENT:
|
||||||
|
$this->processReplacement($total, $invoice);
|
||||||
|
break;
|
||||||
|
case ServiceType::TIRE_REPAIR:
|
||||||
|
$this->processTireRepair($total, $invoice, $cv);
|
||||||
|
// $this->processOtherServices($total, $invoice, $stype);
|
||||||
|
break;
|
||||||
|
case ServiceType::OVERHEAT_ASSISTANCE:
|
||||||
|
$this->processOverheat($total, $invoice, $cv, $has_coolant);
|
||||||
|
break;
|
||||||
|
case ServiceType::EMERGENCY_REFUEL:
|
||||||
|
error_log('processing refuel');
|
||||||
|
$ftype = $criteria->getCustomerVehicle()->getFuelType();
|
||||||
|
$this->processRefuel($total, $invoice, $cv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check if any promo is applied
|
||||||
|
// apply discounts
|
||||||
|
$promos = $criteria->getPromos();
|
||||||
|
|
||||||
|
// get current user
|
||||||
|
$user = $this->security->getUser();
|
||||||
|
if ($user != null)
|
||||||
|
{
|
||||||
|
$invoice->setCreatedBy($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice->setTotalPrice($total['total_price'])
|
||||||
|
->setVATExclusivePrice($total['vat_ex_price'])
|
||||||
|
->setVAT($total['vat'])
|
||||||
|
->setDiscount($total['discount'])
|
||||||
|
->setTradeIn($total['ti_rate'])
|
||||||
|
->setStatus(InvoiceStatus::DRAFT);
|
||||||
|
|
||||||
|
// dump
|
||||||
|
//Debug::dump($invoice, 1);
|
||||||
|
|
||||||
|
return $invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTaxAmount($price)
|
||||||
|
{
|
||||||
|
$vat_ex_price = $this->getTaxExclusivePrice($price);
|
||||||
|
return $price - $vat_ex_price;
|
||||||
|
// return round($vat_ex_price * self::TAX_RATE, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTaxExclusivePrice($price)
|
||||||
|
{
|
||||||
|
return round($price / (1 + self::TAX_RATE), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTradeInRate($ti)
|
||||||
|
{
|
||||||
|
$size = $ti['size'];
|
||||||
|
$trade_in = $ti['trade_in'];
|
||||||
|
|
||||||
|
if ($trade_in == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch ($trade_in)
|
||||||
|
{
|
||||||
|
case TradeInType::MOTOLITE:
|
||||||
|
return $size->getTIPriceMotolite();
|
||||||
|
case TradeInType::PREMIUM:
|
||||||
|
return $size->getTIPricePremium();
|
||||||
|
case TradeInType::OTHER:
|
||||||
|
return $size->getTIPriceOther();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processEntries(&$total, InvoiceCriteria $criteria, Invoice $invoice)
|
||||||
|
{
|
||||||
|
// error_log('processing entries...');
|
||||||
|
$entries = $criteria->getEntries();
|
||||||
|
|
||||||
|
$con_batts = [];
|
||||||
|
$con_tis = [];
|
||||||
|
foreach ($entries as $entry)
|
||||||
|
{
|
||||||
|
$batt = $entry['battery'];
|
||||||
|
$qty = $entry['qty'];
|
||||||
|
$trade_in = $entry['trade_in'];
|
||||||
|
$size = $batt->getSize();
|
||||||
|
|
||||||
|
// consolidate batteries
|
||||||
|
$batt_id = $batt->getID();
|
||||||
|
if (!isset($con_batts[$batt_id]))
|
||||||
|
$con_batts[$batt->getID()] = [
|
||||||
|
'batt' => $batt,
|
||||||
|
'qty' => 0
|
||||||
|
];
|
||||||
|
$con_batts[$batt_id]['qty']++;
|
||||||
|
|
||||||
|
|
||||||
|
// no trade-in
|
||||||
|
if ($trade_in == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// consolidate trade-ins
|
||||||
|
$ti_key = $size->getID() . '|' . $trade_in;
|
||||||
|
if (!isset($con_tis[$ti_key]))
|
||||||
|
$con_tis[$ti_key] = [
|
||||||
|
'size' => $size,
|
||||||
|
'trade_in' => $trade_in,
|
||||||
|
'qty' => 0
|
||||||
|
];
|
||||||
|
$con_tis[$ti_key]['qty']++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->processBatteries($total, $con_batts, $invoice);
|
||||||
|
$this->processTradeIns($total, $con_tis, $invoice);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processBatteries(&$total, $con_batts, Invoice $invoice)
|
||||||
|
{
|
||||||
|
// process batteries
|
||||||
|
foreach ($con_batts as $con_data)
|
||||||
|
{
|
||||||
|
$batt = $con_data['batt'];
|
||||||
|
$qty = $con_data['qty'];
|
||||||
|
|
||||||
|
$sell_price = $batt->getSellingPrice();
|
||||||
|
$vat = $this->getTaxAmount($sell_price);
|
||||||
|
// $vat_ex_price = $this->getTaxExclusivePrice($sell_price);
|
||||||
|
|
||||||
|
$total['sell_price'] += $sell_price * $qty;
|
||||||
|
$total['vat'] += $vat * $qty;
|
||||||
|
$total['vat_ex_price'] += ($sell_price - $vat) * $qty;
|
||||||
|
|
||||||
|
$total['total_price'] += $sell_price * $qty;
|
||||||
|
|
||||||
|
// add item
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle($batt->getModel()->getName() . ' ' . $batt->getSize()->getName())
|
||||||
|
->setQuantity($qty)
|
||||||
|
->setPrice($sell_price)
|
||||||
|
->setBattery($batt);
|
||||||
|
|
||||||
|
$invoice->addItem($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processTradeIns(&$total, $con_tis, Invoice $invoice)
|
||||||
|
{
|
||||||
|
foreach ($con_tis as $ti)
|
||||||
|
{
|
||||||
|
$qty = $ti['qty'];
|
||||||
|
$ti_rate = $this->getTradeInRate($ti);
|
||||||
|
|
||||||
|
$total['ti_rate'] += $ti_rate * $qty;
|
||||||
|
$total['total_price'] -= $ti_rate * $qty;
|
||||||
|
|
||||||
|
// add item
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Trade-in ' . TradeInType::getName($ti['trade_in']) . ' ' . $ti['size']->getName() . ' battery')
|
||||||
|
->setQuantity($qty)
|
||||||
|
->setPrice($ti_rate * -1);
|
||||||
|
|
||||||
|
$invoice->addItem($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processDiscount(&$total, InvoiceCriteria $criteria, Invoice $invoice)
|
||||||
|
{
|
||||||
|
$promos = $criteria->getPromos();
|
||||||
|
if (count($promos) < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 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 = round($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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if discount is higher than 0, display in invoice
|
||||||
|
if ($discount > 0)
|
||||||
|
{
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Promo discount')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(-1 * $discount);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
$total['discount'] = $discount;
|
||||||
|
$total['total_price'] -= $discount;
|
||||||
|
|
||||||
|
// process
|
||||||
|
$invoice->setPromo($promo);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processJumpstart(&$total, $invoice)
|
||||||
|
{
|
||||||
|
// add troubleshooting fee
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Troubleshooting fee')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(self::TROUBLESHOOTING_FEE);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
|
||||||
|
$total['sell_price'] = self::TROUBLESHOOTING_FEE;
|
||||||
|
$total['vat_ex_price'] = self::TROUBLESHOOTING_FEE;
|
||||||
|
$total['total_price'] = self::TROUBLESHOOTING_FEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processJumpstartWarranty(&$total, $invoice)
|
||||||
|
{
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Troubleshooting fee')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(0.00);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processRecharge(&$total, $invoice)
|
||||||
|
{
|
||||||
|
// add recharge fee
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Recharge fee')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(self::RECHARGE_FEE);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
|
||||||
|
$total['sell_price'] = self::RECHARGE_FEE;
|
||||||
|
$total['vat_ex_price'] = self::RECHARGE_FEE;
|
||||||
|
$total['total_price'] = self::RECHARGE_FEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processReplacement(&$total, $invoice)
|
||||||
|
{
|
||||||
|
// add recharge fee
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Battery replacement')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(self::BATT_REPLACEMENT_FEE);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processWarranty(&$total, InvoiceCriteria $criteria, $invoice)
|
||||||
|
{
|
||||||
|
// error_log('processing warranty');
|
||||||
|
$entries = $criteria->getEntries();
|
||||||
|
foreach ($entries as $entry)
|
||||||
|
{
|
||||||
|
$batt = $entry['battery'];
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle($batt->getModel()->getName() . ' ' . $batt->getSize()->getName() . ' - Service Unit')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(self::WARRANTY_FEE)
|
||||||
|
->setBattery($batt);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processOtherServices(&$total, $invoice, $stype)
|
||||||
|
{
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Service - ' . ServiceType::getName($stype))
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(self::OTHER_SERVICES_FEE);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
|
||||||
|
$total['total_price'] = 200.00;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processOverheat(&$total, $invoice, $cv, $has_coolant)
|
||||||
|
{
|
||||||
|
// free if they have a motolite battery
|
||||||
|
if ($cv->hasMotoliteBattery())
|
||||||
|
$fee = 0;
|
||||||
|
else
|
||||||
|
$fee = self::SERVICE_FEE;
|
||||||
|
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Service - Overheat Assistance')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice($fee);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
|
||||||
|
$total_price = $fee;
|
||||||
|
|
||||||
|
if ($has_coolant)
|
||||||
|
{
|
||||||
|
$coolant = new InvoiceItem();
|
||||||
|
$coolant->setInvoice($invoice)
|
||||||
|
->setTitle('4L Coolant')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(self::COOLANT_FEE);
|
||||||
|
$invoice->addItem($coolant);
|
||||||
|
|
||||||
|
$total_price += self::COOLANT_FEE;
|
||||||
|
//$total_price += 1600;
|
||||||
|
}
|
||||||
|
|
||||||
|
$vat_ex_price = $this->getTaxExclusivePrice($total_price);
|
||||||
|
$vat = $total_price - $vat_ex_price;
|
||||||
|
$total['total_price'] = $total_price;
|
||||||
|
$total['vat_ex_price'] = $vat_ex_price;
|
||||||
|
$total['vat'] = $vat;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processTireRepair(&$total, $invoice, $cv)
|
||||||
|
{
|
||||||
|
// free if they have a motolite battery
|
||||||
|
if ($cv->hasMotoliteBattery())
|
||||||
|
$fee = 0;
|
||||||
|
else
|
||||||
|
$fee = self::SERVICE_FEE;
|
||||||
|
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Service - Flat Tire')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice($fee);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
$total_price = $fee;
|
||||||
|
|
||||||
|
$vat_ex_price = $this->getTaxExclusivePrice($total_price);
|
||||||
|
$vat = $total_price - $vat_ex_price;
|
||||||
|
$total['total_price'] = $total_price;
|
||||||
|
$total['vat_ex_price'] = $vat_ex_price;
|
||||||
|
$total['vat'] = $vat;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processRefuel(&$total, $invoice, $cv)
|
||||||
|
{
|
||||||
|
// free if they have a motolite battery
|
||||||
|
if ($cv->hasMotoliteBattery())
|
||||||
|
$fee = 0;
|
||||||
|
else
|
||||||
|
$fee = self::SERVICE_FEE;
|
||||||
|
|
||||||
|
$ftype = $cv->getFuelType();
|
||||||
|
$item = new InvoiceItem();
|
||||||
|
|
||||||
|
// service charge
|
||||||
|
$item->setInvoice($invoice)
|
||||||
|
->setTitle('Service - ' . ServiceType::getName(ServiceType::EMERGENCY_REFUEL))
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice($fee);
|
||||||
|
$invoice->addItem($item);
|
||||||
|
$total_price = $fee;
|
||||||
|
// $total['total_price'] = 200.00;
|
||||||
|
|
||||||
|
$gas_price = self::REFUEL_FEE_GAS;
|
||||||
|
$diesel_price = self::REFUEL_FEE_DIESEL;
|
||||||
|
|
||||||
|
$fuel = new InvoiceItem();
|
||||||
|
error_log('fuel type - ' . $ftype);
|
||||||
|
switch ($ftype)
|
||||||
|
{
|
||||||
|
case FuelType::GAS:
|
||||||
|
$fuel->setInvoice($invoice)
|
||||||
|
->setTitle('4L Fuel - Gas')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice($gas_price);
|
||||||
|
$invoice->addItem($fuel);
|
||||||
|
$total_price += $gas_price;
|
||||||
|
break;
|
||||||
|
case FuelType::DIESEL:
|
||||||
|
$fuel->setInvoice($invoice)
|
||||||
|
->setTitle('4L Fuel - Diesel')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice($diesel_price);
|
||||||
|
$total_price += $diesel_price;
|
||||||
|
$invoice->addItem($fuel);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// NOTE: should never get to this point
|
||||||
|
$fuel->setInvoice($invoice)
|
||||||
|
->setTitle('Fuel - Unknown')
|
||||||
|
->setQuantity(1)
|
||||||
|
->setPrice(0);
|
||||||
|
$total_price += 0.00;
|
||||||
|
$invoice->addItem($fuel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$vat_ex_price = $this->getTaxExclusivePrice($total_price);
|
||||||
|
$vat = $total_price - $vat_ex_price;
|
||||||
|
$total['total_price'] = $total_price;
|
||||||
|
$total['vat_ex_price'] = $vat_ex_price;
|
||||||
|
$total['vat'] = $vat;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
src/Service/InvoiceGeneratorInterface.php
Normal file
14
src/Service/InvoiceGeneratorInterface.php
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use App\Entity\Invoice;
|
||||||
|
|
||||||
|
use App\Ramcar\InvoiceCriteria;
|
||||||
|
|
||||||
|
interface InvoiceGeneratorInterface
|
||||||
|
{
|
||||||
|
// generate invoice using a criteria
|
||||||
|
public function generateInvoice(InvoiceCriteria $criteria);
|
||||||
|
|
||||||
|
}
|
||||||
209
src/Service/JobOrderGenerator/CMBJobOrderGenerator.php
Normal file
209
src/Service/JobOrderGenerator/CMBJobOrderGenerator.php
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\JobOrderGenerator;
|
||||||
|
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
use App\Entity\JobOrder;
|
||||||
|
use App\Entity\Battery;
|
||||||
|
use App\Entity\JOEvent;
|
||||||
|
|
||||||
|
use App\Ramcar\InvoiceCriteria;
|
||||||
|
use App\Ramcar\ServiceType;
|
||||||
|
use App\Ramcar\TradeInType;
|
||||||
|
use App\Ramcar\JOEventType;
|
||||||
|
|
||||||
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
|
use App\Service\JobOrderGeneratorInterface;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
class CMBJobOrderGenerator implements JobOrderGeneratorInterface
|
||||||
|
{
|
||||||
|
protected $em;
|
||||||
|
protected $ic;
|
||||||
|
|
||||||
|
public function __construct(Security $security, EntityManagerInterface $em,
|
||||||
|
InvoiceGeneratorInterface $ic, ValidatorInterface $validator)
|
||||||
|
{
|
||||||
|
$this->em = $em;
|
||||||
|
$this->ic = $ic;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->validator = $validator;
|
||||||
|
}
|
||||||
|
public function generateJobOrder(JobOrder $jo, $promo_id, $invoice_change, $invoice_items, &$error_array)
|
||||||
|
{
|
||||||
|
// TODO: data validation to be moved here
|
||||||
|
|
||||||
|
// check if invoice changed
|
||||||
|
if ($invoice_change)
|
||||||
|
{
|
||||||
|
$this->processInvoice($jo, $promo_id, $invoice_items, $error_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate
|
||||||
|
$errors = $this->validator->validate($jo);
|
||||||
|
|
||||||
|
// add errors to list
|
||||||
|
foreach ($errors as $error) {
|
||||||
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if errors are found
|
||||||
|
if (empty($error_array))
|
||||||
|
{
|
||||||
|
// validated, no error. save the job order
|
||||||
|
$this->em->persist($jo);
|
||||||
|
|
||||||
|
// get current user
|
||||||
|
$user = $this->security->getUser();
|
||||||
|
|
||||||
|
// the event
|
||||||
|
$event = new JOEvent();
|
||||||
|
$event->setDateHappen(new DateTime())
|
||||||
|
->setTypeID(JOEventType::CREATE)
|
||||||
|
->setJobOrder($jo);
|
||||||
|
|
||||||
|
if ($user != null)
|
||||||
|
{
|
||||||
|
$event->setUser($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->em->persist($event);
|
||||||
|
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $error_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processInvoice($jo, $promo_id, $invoice_items, &$error_array)
|
||||||
|
{
|
||||||
|
// instantiate the invoice criteria
|
||||||
|
$criteria = new InvoiceCriteria();
|
||||||
|
$criteria->setServiceType($jo->getServiceType())
|
||||||
|
->setCustomerVehicle($jo->getCustomerVehicle());
|
||||||
|
|
||||||
|
$ierror = $this->invoicePromo($criteria, $promo_id);
|
||||||
|
|
||||||
|
if (!$ierror && !empty($invoice_items))
|
||||||
|
{
|
||||||
|
// check for trade-in so we can mark it for mobile app
|
||||||
|
foreach ($invoice_items as $item)
|
||||||
|
{
|
||||||
|
// get first trade-in
|
||||||
|
if (!empty($item['trade_in']))
|
||||||
|
{
|
||||||
|
$jo->getTradeInType($item['trade_in']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ierror = $this->invoiceBatteries($criteria, $invoice_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ierror)
|
||||||
|
{
|
||||||
|
$error_array['invoice'] = $ierror;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// generate the invoice
|
||||||
|
$iobj = $this->ic->generateInvoice($criteria);
|
||||||
|
|
||||||
|
// validate
|
||||||
|
$ierrors = $this->validator->validate($iobj);
|
||||||
|
|
||||||
|
// 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($iobj);
|
||||||
|
|
||||||
|
$this->em->persist($iobj);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function invoicePromo(InvoiceCriteria $criteria, $promo_id)
|
||||||
|
{
|
||||||
|
// return error if there's a problem, false otherwise
|
||||||
|
// check service type
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
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 invoiceBatteries(InvoiceCriteria $criteria, $items)
|
||||||
|
{
|
||||||
|
// check service type
|
||||||
|
$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($items))
|
||||||
|
{
|
||||||
|
foreach ($items as $item)
|
||||||
|
{
|
||||||
|
// check if this is a valid battery
|
||||||
|
$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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// add to criteria
|
||||||
|
$criteria->addBattery($battery, $qty);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
209
src/Service/JobOrderGenerator/ResqJobOrderGenerator.php
Normal file
209
src/Service/JobOrderGenerator/ResqJobOrderGenerator.php
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\JobOrderGenerator;
|
||||||
|
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
|
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
use App\Entity\JobOrder;
|
||||||
|
use App\Entity\Battery;
|
||||||
|
use App\Entity\JOEvent;
|
||||||
|
|
||||||
|
use App\Ramcar\InvoiceCriteria;
|
||||||
|
use App\Ramcar\ServiceType;
|
||||||
|
use App\Ramcar\TradeInType;
|
||||||
|
use App\Ramcar\JOEventType;
|
||||||
|
|
||||||
|
use App\Service\InvoiceGeneratorInterface;
|
||||||
|
use App\Service\JobOrderGeneratorInterface;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
class ResqJobOrderGenerator implements JobOrderGeneratorInterface
|
||||||
|
{
|
||||||
|
protected $em;
|
||||||
|
protected $ic;
|
||||||
|
|
||||||
|
public function __construct(Security $security, EntityManagerInterface $em,
|
||||||
|
InvoiceGeneratorInterface $ic, ValidatorInterface $validator)
|
||||||
|
{
|
||||||
|
$this->em = $em;
|
||||||
|
$this->ic = $ic;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->validator = $validator;
|
||||||
|
}
|
||||||
|
public function generateJobOrder(JobOrder $jo, $promo_id, $invoice_change, $invoice_items, &$error_array)
|
||||||
|
{
|
||||||
|
// TODO: data validation to be moved here
|
||||||
|
|
||||||
|
// check if invoice changed
|
||||||
|
if ($invoice_change)
|
||||||
|
{
|
||||||
|
$this->processInvoice($jo, $promo_id, $invoice_items, $error_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate
|
||||||
|
$errors = $this->validator->validate($jo);
|
||||||
|
|
||||||
|
// add errors to list
|
||||||
|
foreach ($errors as $error) {
|
||||||
|
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if errors are found
|
||||||
|
if (empty($error_array))
|
||||||
|
{
|
||||||
|
// validated, no error. save the job order
|
||||||
|
$this->em->persist($jo);
|
||||||
|
|
||||||
|
// get current user
|
||||||
|
$user = $this->security->getUser();
|
||||||
|
|
||||||
|
// the event
|
||||||
|
$event = new JOEvent();
|
||||||
|
$event->setDateHappen(new DateTime())
|
||||||
|
->setTypeID(JOEventType::CREATE)
|
||||||
|
->setJobOrder($jo);
|
||||||
|
|
||||||
|
if ($user != null)
|
||||||
|
{
|
||||||
|
$event->setUser($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->em->persist($event);
|
||||||
|
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $error_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processInvoice($jo, $promo_id, $invoice_items, &$error_array)
|
||||||
|
{
|
||||||
|
// instantiate the invoice criteria
|
||||||
|
$criteria = new InvoiceCriteria();
|
||||||
|
$criteria->setServiceType($jo->getServiceType())
|
||||||
|
->setCustomerVehicle($jo->getCustomerVehicle());
|
||||||
|
|
||||||
|
$ierror = $this->invoicePromo($criteria, $promo_id);
|
||||||
|
|
||||||
|
if (!$ierror && !empty($invoice_items))
|
||||||
|
{
|
||||||
|
// check for trade-in so we can mark it for mobile app
|
||||||
|
foreach ($invoice_items as $item)
|
||||||
|
{
|
||||||
|
// get first trade-in
|
||||||
|
if (!empty($item['trade_in']))
|
||||||
|
{
|
||||||
|
$jo->getTradeInType($item['trade_in']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ierror = $this->invoiceBatteries($criteria, $invoice_items);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ierror)
|
||||||
|
{
|
||||||
|
$error_array['invoice'] = $ierror;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// generate the invoice
|
||||||
|
$iobj = $this->ic->generateInvoice($criteria);
|
||||||
|
|
||||||
|
// validate
|
||||||
|
$ierrors = $this->validator->validate($iobj);
|
||||||
|
|
||||||
|
// 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($iobj);
|
||||||
|
|
||||||
|
$this->em->persist($iobj);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function invoicePromo(InvoiceCriteria $criteria, $promo_id)
|
||||||
|
{
|
||||||
|
// return error if there's a problem, false otherwise
|
||||||
|
// check service type
|
||||||
|
$stype = $criteria->getServiceType();
|
||||||
|
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 invoiceBatteries(InvoiceCriteria $criteria, $items)
|
||||||
|
{
|
||||||
|
// check service type
|
||||||
|
$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($items))
|
||||||
|
{
|
||||||
|
foreach ($items as $item)
|
||||||
|
{
|
||||||
|
// check if this is a valid battery
|
||||||
|
$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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// add to criteria
|
||||||
|
$criteria->addBattery($battery, $qty);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/Service/JobOrderGeneratorInterface.php
Normal file
13
src/Service/JobOrderGeneratorInterface.php
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use App\Entity\JobOrder;
|
||||||
|
use App\Entity\InvoiceItem;
|
||||||
|
|
||||||
|
interface JobOrderGeneratorInterface
|
||||||
|
{
|
||||||
|
// generate job order
|
||||||
|
public function generateJobOrder(JobOrder $jo, int $promo_id, bool $invoice_change,
|
||||||
|
array $invoice_items, array &$error_array);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue