From f1cc1dfae1a43d15fa8aed2c5c643aadd0e60bdc Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 19 Sep 2019 07:28:48 +0000 Subject: [PATCH 01/10] Create interface for invoice creator. #265 --- config/services.yaml | 6 ++ src/Controller/APIController.php | 6 +- src/Controller/JobOrderController.php | 8 +-- src/Controller/RAPIController.php | 4 +- .../CMBInvoiceCreator.php} | 45 +++++++------- src/Service/InvoiceCreatorInterface.php | 58 +++++++++++++++++++ 6 files changed, 97 insertions(+), 30 deletions(-) rename src/Service/{InvoiceCreator.php => InvoiceCreator/CMBInvoiceCreator.php} (91%) create mode 100644 src/Service/InvoiceCreatorInterface.php diff --git a/config/services.yaml b/config/services.yaml index 8c8024f5..65abbe59 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -130,3 +130,9 @@ services: $menu_name: "main_menu" tags: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController } + + # invoice creator + App\Service\InvoiceCreator\CMBInvoiceCreator: ~ + + # invoice creator interface + App\Service\InvoiceCreatorInterface: "@App\\Service\\InvoiceCreator\\CMBInvoiceCreator" diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 075879bb..92146e1b 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -24,7 +24,7 @@ use App\Ramcar\TransactionOrigin; use App\Ramcar\TradeInType; use App\Ramcar\JOEventType; -use App\Service\InvoiceCreator; +use App\Service\InvoiceCreatorInterface; use App\Service\RisingTideGateway; use App\Service\MQTTClient; use App\Service\GeofenceTracker; @@ -808,7 +808,7 @@ class APIController extends Controller return $res->getReturnResponse(); } - public function requestJobOrder(Request $req, InvoiceCreator $ic, GeofenceTracker $geo) + public function requestJobOrder(Request $req, InvoiceCreatorInterface $ic, GeofenceTracker $geo) { // check required parameters and api key $required_params = [ @@ -1020,7 +1020,7 @@ class APIController extends Controller return $res->getReturnResponse(); } - public function getEstimate(Request $req, InvoiceCreator $ic) + public function getEstimate(Request $req, InvoiceCreatorInterface $ic) { // $this->debugRequest($req); diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 8e9c7d46..d746a59b 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -27,7 +27,7 @@ use App\Entity\Battery; use App\Entity\JOEvent; use App\Entity\JORejection; -use App\Service\InvoiceCreator; +use App\Service\InvoiceCreatorInterface; use App\Service\MapTools; use App\Service\HubCounter; use App\Service\MQTTClient; @@ -251,7 +251,7 @@ class JobOrderController extends Controller 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, InvoiceCreatorInterface $ic, $id) { $this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.'); @@ -425,7 +425,7 @@ class JobOrderController extends Controller 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, InvoiceCreatorInterface $ic) { $this->denyAccessUnlessGranted('jo_in.list', null, 'No access.'); @@ -2482,7 +2482,7 @@ class JobOrderController extends Controller return null; } - public function generateInvoice(Request $req, InvoiceCreator $ic) + public function generateInvoice(Request $req, InvoiceCreatorInterface $ic) { // error_log('generating invoice...'); $error = false; diff --git a/src/Controller/RAPIController.php b/src/Controller/RAPIController.php index ddd66d5e..a613a150 100644 --- a/src/Controller/RAPIController.php +++ b/src/Controller/RAPIController.php @@ -25,7 +25,7 @@ use App\Ramcar\InvoiceStatus; use App\Ramcar\ModeOfPayment; use App\Ramcar\JOEventType; -use App\Service\InvoiceCreator; +use App\Service\InvoiceCreatorInterface; use App\Service\MQTTClient; use App\Entity\RiderSession; @@ -739,7 +739,7 @@ class RAPIController extends Controller error_log(print_r($all, true)); } - public function changeService(Request $req, InvoiceCreator $ic) + public function changeService(Request $req, InvoiceCreatorInterface $ic) { $this->debugRequest($req); diff --git a/src/Service/InvoiceCreator.php b/src/Service/InvoiceCreator/CMBInvoiceCreator.php similarity index 91% rename from src/Service/InvoiceCreator.php rename to src/Service/InvoiceCreator/CMBInvoiceCreator.php index 1c6a74a7..aa96399e 100644 --- a/src/Service/InvoiceCreator.php +++ b/src/Service/InvoiceCreator/CMBInvoiceCreator.php @@ -1,6 +1,6 @@ getVATExclusivePrice($price); + $vat_ex_price = $this->getTaxExclusivePrice($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) + public function getTaxExclusivePrice($price) { - return round($price / (1 + self::VAT_RATE), 2); + return round($price / (1 + self::TAX_RATE), 2); } public function getTradeInRate($ti) @@ -57,7 +60,7 @@ class InvoiceCreator return 0; } - protected function processEntries(&$total, InvoiceCriteria $criteria, Invoice $invoice) + public function processEntries(&$total, InvoiceCriteria $criteria, Invoice $invoice) { // error_log('processing entries...'); $entries = $criteria->getEntries(); @@ -100,7 +103,7 @@ class InvoiceCreator $this->processTradeIns($total, $con_tis, $invoice); } - protected function processBatteries(&$total, $con_batts, Invoice $invoice) + public function processBatteries(&$total, $con_batts, Invoice $invoice) { // process batteries foreach ($con_batts as $con_data) @@ -109,8 +112,8 @@ class InvoiceCreator $qty = $con_data['qty']; $sell_price = $batt->getSellingPrice(); - $vat = $this->getVATAmount($sell_price); - // $vat_ex_price = $this->getVATExclusivePrice($sell_price); + $vat = $this->getTaxAmount($sell_price); + // $vat_ex_price = $this->getTaxExclusivePrice($sell_price); $total['sell_price'] += $sell_price * $qty; $total['vat'] += $vat * $qty; @@ -130,7 +133,7 @@ class InvoiceCreator } } - protected function processTradeIns(&$total, $con_tis, Invoice $invoice) + public function processTradeIns(&$total, $con_tis, Invoice $invoice) { foreach ($con_tis as $ti) { @@ -151,7 +154,7 @@ class InvoiceCreator } } - protected function processDiscount(&$total, InvoiceCriteria $criteria, Invoice $invoice) + public function processDiscount(&$total, InvoiceCriteria $criteria, Invoice $invoice) { $promos = $criteria->getPromos(); if (count($promos) < 1) @@ -224,12 +227,12 @@ class InvoiceCreator $item->setInvoice($invoice) ->setTitle('Recharge fee') ->setQuantity(1) - ->setPrice(300.00); + ->setPrice(self::RECHARGE_FEE); $invoice->addItem($item); - $total['sell_price'] = 300.00; - $total['vat_ex_price'] = 300.00; - $total['total_price'] = 300.00; + $total['sell_price'] = self::RECHARGE_FEE; + $total['vat_ex_price'] = self::RECHARGE_FEE; + $total['total_price'] = self::RECHARGE_FEE; } public function processReplacement(&$total, $invoice) @@ -301,7 +304,7 @@ class InvoiceCreator $total_price += 1600; } - $vat_ex_price = $this->getVATExclusivePrice($total_price); + $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; @@ -324,7 +327,7 @@ class InvoiceCreator $invoice->addItem($item); $total_price = $fee; - $vat_ex_price = $this->getVATExclusivePrice($total_price); + $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; @@ -385,7 +388,7 @@ class InvoiceCreator break; } - $vat_ex_price = $this->getVATExclusivePrice($total_price); + $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; diff --git a/src/Service/InvoiceCreatorInterface.php b/src/Service/InvoiceCreatorInterface.php new file mode 100644 index 00000000..f91f48c2 --- /dev/null +++ b/src/Service/InvoiceCreatorInterface.php @@ -0,0 +1,58 @@ + Date: Fri, 20 Sep 2019 06:09:17 +0000 Subject: [PATCH 02/10] Rename invoice creator for resq. Make most public methods in invoice creator protected. #265 --- ...oiceCreator.php => ResqInvoiceCreator.php} | 739 +++++++++--------- src/Service/InvoiceCreatorInterface.php | 44 -- 2 files changed, 370 insertions(+), 413 deletions(-) rename src/Service/InvoiceCreator/{CMBInvoiceCreator.php => ResqInvoiceCreator.php} (92%) diff --git a/src/Service/InvoiceCreator/CMBInvoiceCreator.php b/src/Service/InvoiceCreator/ResqInvoiceCreator.php similarity index 92% rename from src/Service/InvoiceCreator/CMBInvoiceCreator.php rename to src/Service/InvoiceCreator/ResqInvoiceCreator.php index aa96399e..42f6a517 100644 --- a/src/Service/InvoiceCreator/CMBInvoiceCreator.php +++ b/src/Service/InvoiceCreator/ResqInvoiceCreator.php @@ -16,7 +16,7 @@ use App\Service\InvoiceCreatorInterface; use Doctrine\Common\Util\Debug; -class CMBInvoiceCreator implements InvoiceCreatorInterface +class ResqInvoiceCreator implements InvoiceCreatorInterface { const TAX_RATE = 0.12; const SERVICE_FEE = 300; @@ -27,374 +27,6 @@ class CMBInvoiceCreator implements InvoiceCreatorInterface { } - public function getTaxAmount($price) - { - $vat_ex_price = $this->getTaxExclusivePrice($price); - return $price - $vat_ex_price; - // return round($vat_ex_price * self::TAX_RATE, 2); - } - - public function getTaxExclusivePrice($price) - { - return round($price / (1 + self::TAX_RATE), 2); - } - - public 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; - } - - public 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); - } - - public 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); - } - } - - public 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); - } - } - - public 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); - } - - public function processJumpstart(&$total, $invoice) - { - // add troubleshooting fee - $item = new InvoiceItem(); - $item->setInvoice($invoice) - ->setTitle('Troubleshooting fee') - ->setQuantity(1) - ->setPrice(150.00); - $invoice->addItem($item); - - $total['sell_price'] = 150.00; - $total['vat_ex_price'] = 150.00; - $total['total_price'] = 150.00; - } - - public function processJumpstartWarranty(&$total, $invoice) - { - $item = new InvoiceItem(); - $item->setInvoice($invoice) - ->setTitle('Troubleshooting fee') - ->setQuantity(1) - ->setPrice(0.00); - $invoice->addItem($item); - } - - public 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; - } - - public function processReplacement(&$total, $invoice) - { - // add recharge fee - $item = new InvoiceItem(); - $item->setInvoice($invoice) - ->setTitle('Battery replacement') - ->setQuantity(1) - ->setPrice(0.00); - $invoice->addItem($item); - } - - public 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(0.00) - ->setBattery($batt); - $invoice->addItem($item); - } - } - - public function processOtherServices(&$total, $invoice, $stype) - { - $item = new InvoiceItem(); - $item->setInvoice($invoice) - ->setTitle('Service - ' . ServiceType::getName($stype)) - ->setQuantity(1) - ->setPrice(200.00); - $invoice->addItem($item); - - $total['total_price'] = 200.00; - } - - public 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(1600); - $invoice->addItem($coolant); - - $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; - } - - public 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; - } - - public 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 = 260; - $diesel_price = 220; - - $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; - } - public function processCriteria(InvoiceCriteria $criteria) { // initialize @@ -468,4 +100,373 @@ class CMBInvoiceCreator implements InvoiceCreatorInterface 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(150.00); + $invoice->addItem($item); + + $total['sell_price'] = 150.00; + $total['vat_ex_price'] = 150.00; + $total['total_price'] = 150.00; + } + + 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(0.00); + $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(0.00) + ->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(200.00); + $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(1600); + $invoice->addItem($coolant); + + $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 = 260; + $diesel_price = 220; + + $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; + } + } diff --git a/src/Service/InvoiceCreatorInterface.php b/src/Service/InvoiceCreatorInterface.php index f91f48c2..3d13b5f6 100644 --- a/src/Service/InvoiceCreatorInterface.php +++ b/src/Service/InvoiceCreatorInterface.php @@ -11,48 +11,4 @@ interface InvoiceCreatorInterface // process invoice criteria public function processCriteria(InvoiceCriteria $criteria); - // process entries for invoice - public function processEntries(&$total, InvoiceCriteria $criteria, Invoice $invoice); - - // process batteries - public function processBatteries(&$total, $con_batts, Invoice $invoice); - - // get tradein rates - public function getTradeInRate($ti); - - // process discounts - public function processDiscount(&$total, InvoiceCriteria $criteria, Invoice $invoice); - - // process jumpstart service charges - public function processJumpstart(&$total, $invoice); - - // process jumpstart service charges with warranty - public function processJumpstartWarranty(&$total, $invoice); - - // process recharge costs - public function processRecharge(&$total, $invoice); - - // process replacement charges - public function processReplacement(&$total, $invoice); - - // process warranty charges - public function processWarranty(&$total, InvoiceCriteria $criteria, $invoice); - - // process other charges - public function processOtherServices(&$total, $invoice, $stype); - - // process overheat charges - public function processOverheat(&$total, $invoice, $cv, $has_coolant); - - // process tire repair charges - public function processTireRepair(&$total, $invoice, $cv); - - // process refuel charges - public function processRefuel(&$total, $invoice, $cv); - - // compute tax - public function getTaxAmount($price); - - // compute price without tax - public function getTaxExclusivePrice($price); } From dc2eecbe0cd9f5314842f5ca8bc5b837dd5c24b8 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 20 Sep 2019 06:38:52 +0000 Subject: [PATCH 03/10] Rename InvoiceCreator to InvoiceGenerator. #265 --- config/services.yaml | 4 ++-- src/Controller/APIController.php | 6 +++--- src/Controller/JobOrderController.php | 8 ++++---- src/Controller/RAPIController.php | 4 ++-- src/Service/InvoiceCreatorInterface.php | 14 -------------- .../ResqInvoiceGenerator.php} | 8 ++++---- src/Service/InvoiceGeneratorInterface.php | 14 ++++++++++++++ 7 files changed, 29 insertions(+), 29 deletions(-) delete mode 100644 src/Service/InvoiceCreatorInterface.php rename src/Service/{InvoiceCreator/ResqInvoiceCreator.php => InvoiceGenerator/ResqInvoiceGenerator.php} (98%) create mode 100644 src/Service/InvoiceGeneratorInterface.php diff --git a/config/services.yaml b/config/services.yaml index 65abbe59..958e8133 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -132,7 +132,7 @@ services: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController } # invoice creator - App\Service\InvoiceCreator\CMBInvoiceCreator: ~ + App\Service\InvoiceGenerator\ResqInvoiceGenerator: ~ # invoice creator interface - App\Service\InvoiceCreatorInterface: "@App\\Service\\InvoiceCreator\\CMBInvoiceCreator" + App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\ResqInvoiceGenerator" diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 92146e1b..99456ed6 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -24,7 +24,7 @@ use App\Ramcar\TransactionOrigin; use App\Ramcar\TradeInType; use App\Ramcar\JOEventType; -use App\Service\InvoiceCreatorInterface; +use App\Service\InvoiceGeneratorInterface; use App\Service\RisingTideGateway; use App\Service\MQTTClient; use App\Service\GeofenceTracker; @@ -808,7 +808,7 @@ class APIController extends Controller return $res->getReturnResponse(); } - public function requestJobOrder(Request $req, InvoiceCreatorInterface $ic, GeofenceTracker $geo) + public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo) { // check required parameters and api key $required_params = [ @@ -1020,7 +1020,7 @@ class APIController extends Controller return $res->getReturnResponse(); } - public function getEstimate(Request $req, InvoiceCreatorInterface $ic) + public function getEstimate(Request $req, InvoiceGeneratorInterface $ic) { // $this->debugRequest($req); diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index d746a59b..c81a8694 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -27,7 +27,7 @@ use App\Entity\Battery; use App\Entity\JOEvent; use App\Entity\JORejection; -use App\Service\InvoiceCreatorInterface; +use App\Service\InvoiceGeneratorInterface; use App\Service\MapTools; use App\Service\HubCounter; use App\Service\MQTTClient; @@ -251,7 +251,7 @@ class JobOrderController extends Controller return $this->render('job-order/form.html.twig', $params); } - public function openEditSubmit(Request $req, ValidatorInterface $validator, InvoiceCreatorInterface $ic, $id) + public function openEditSubmit(Request $req, ValidatorInterface $validator, InvoiceGeneratorInterface $ic, $id) { $this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.'); @@ -425,7 +425,7 @@ class JobOrderController extends Controller return $this->render('job-order/form.html.twig', $params); } - public function incomingSubmit(Request $req, ValidatorInterface $validator, InvoiceCreatorInterface $ic) + public function incomingSubmit(Request $req, ValidatorInterface $validator, InvoiceGeneratorInterface $ic) { $this->denyAccessUnlessGranted('jo_in.list', null, 'No access.'); @@ -2482,7 +2482,7 @@ class JobOrderController extends Controller return null; } - public function generateInvoice(Request $req, InvoiceCreatorInterface $ic) + public function generateInvoice(Request $req, InvoiceGeneratorInterface $ic) { // error_log('generating invoice...'); $error = false; diff --git a/src/Controller/RAPIController.php b/src/Controller/RAPIController.php index a613a150..bc20fd4c 100644 --- a/src/Controller/RAPIController.php +++ b/src/Controller/RAPIController.php @@ -25,7 +25,7 @@ use App\Ramcar\InvoiceStatus; use App\Ramcar\ModeOfPayment; use App\Ramcar\JOEventType; -use App\Service\InvoiceCreatorInterface; +use App\Service\InvoiceGeneratorInterface; use App\Service\MQTTClient; use App\Entity\RiderSession; @@ -739,7 +739,7 @@ class RAPIController extends Controller error_log(print_r($all, true)); } - public function changeService(Request $req, InvoiceCreatorInterface $ic) + public function changeService(Request $req, InvoiceGeneratorInterface $ic) { $this->debugRequest($req); diff --git a/src/Service/InvoiceCreatorInterface.php b/src/Service/InvoiceCreatorInterface.php deleted file mode 100644 index 3d13b5f6..00000000 --- a/src/Service/InvoiceCreatorInterface.php +++ /dev/null @@ -1,14 +0,0 @@ - Date: Fri, 20 Sep 2019 09:30:08 +0000 Subject: [PATCH 04/10] Rename processCriteria to generateInvoice. Added constants to invoice generator. #265 --- src/Controller/APIController.php | 4 +-- src/Controller/JobOrderController.php | 6 ++-- src/Controller/RAPIController.php | 2 +- .../InvoiceGenerator/ResqInvoiceGenerator.php | 30 ++++++++++++------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 99456ed6..5642dad7 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -973,7 +973,7 @@ class APIController extends Controller $icrit->addEntry($batt, $trade_in, 1); // send to invoice generator - $invoice = $ic->processCriteria($icrit); + $invoice = $ic->generateInvoice($icrit); $jo->setInvoice($invoice); $em->persist($jo); @@ -1120,7 +1120,7 @@ class APIController extends Controller $icrit->addEntry($batt, $trade_in, 1); // send to invoice generator - $invoice = $ic->processCriteria($icrit); + $invoice = $ic->generateInvoice($icrit); // make invoice json data $data = [ diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index c81a8694..3563b6b9 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -327,7 +327,7 @@ class JobOrderController extends Controller else { // generate the invoice - $iobj = $ic->processCriteria($criteria); + $iobj = $ic->generateInvoice($criteria); $iobj->setStatus(InvoiceStatus::DRAFT) ->setCreatedBy($this->getUser()); @@ -522,7 +522,7 @@ class JobOrderController extends Controller else { // generate the invoice - $iobj = $ic->processCriteria($criteria); + $iobj = $ic->generateInvoice($criteria); $iobj->setStatus(InvoiceStatus::DRAFT) ->setCreatedBy($this->getUser()); @@ -2548,7 +2548,7 @@ class JobOrderController extends Controller } // generate the invoice - $iobj = $ic->processCriteria($criteria); + $iobj = $ic->generateInvoice($criteria); // use invoice object values in a json friendly array $invoice = [ diff --git a/src/Controller/RAPIController.php b/src/Controller/RAPIController.php index bc20fd4c..0c997435 100644 --- a/src/Controller/RAPIController.php +++ b/src/Controller/RAPIController.php @@ -839,7 +839,7 @@ class RAPIController extends Controller error_log('adding entry for battery - ' . $battery->getID()); } - $invoice = $ic->processCriteria($crit); + $invoice = $ic->generateInvoice($crit); $invoice->setStatus(InvoiceStatus::DRAFT); // remove previous invoice diff --git a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php index 9f66d5d3..456b0021 100644 --- a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php @@ -21,6 +21,13 @@ 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; // creates invoice based on the criteria sent public function __construct() @@ -276,12 +283,12 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface $item->setInvoice($invoice) ->setTitle('Troubleshooting fee') ->setQuantity(1) - ->setPrice(150.00); + ->setPrice(self::TROUBLESHOOTING_FEE); $invoice->addItem($item); - $total['sell_price'] = 150.00; - $total['vat_ex_price'] = 150.00; - $total['total_price'] = 150.00; + $total['sell_price'] = self::TROUBLESHOOTING_FEE; + $total['vat_ex_price'] = self::TROUBLESHOOTING_FEE; + $total['total_price'] = self::TROUBLESHOOTING_FEE; } protected function processJumpstartWarranty(&$total, $invoice) @@ -316,7 +323,7 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface $item->setInvoice($invoice) ->setTitle('Battery replacement') ->setQuantity(1) - ->setPrice(0.00); + ->setPrice(self::BATT_REPLACEMENT_FEE); $invoice->addItem($item); } @@ -331,7 +338,7 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface $item->setInvoice($invoice) ->setTitle($batt->getModel()->getName() . ' ' . $batt->getSize()->getName() . ' - Service Unit') ->setQuantity(1) - ->setPrice(0.00) + ->setPrice(self::WARRANTY_FEE) ->setBattery($batt); $invoice->addItem($item); } @@ -343,7 +350,7 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface $item->setInvoice($invoice) ->setTitle('Service - ' . ServiceType::getName($stype)) ->setQuantity(1) - ->setPrice(200.00); + ->setPrice(self::OTHER_SERVICES_FEE); $invoice->addItem($item); $total['total_price'] = 200.00; @@ -372,10 +379,11 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface $coolant->setInvoice($invoice) ->setTitle('4L Coolant') ->setQuantity(1) - ->setPrice(1600); + ->setPrice(self::COOLANT_FEE); $invoice->addItem($coolant); - $total_price += 1600; + $total_price += self::COOLANT_FEE; + //$total_price += 1600; } $vat_ex_price = $this->getTaxExclusivePrice($total_price); @@ -428,8 +436,8 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface $total_price = $fee; // $total['total_price'] = 200.00; - $gas_price = 260; - $diesel_price = 220; + $gas_price = self::REFUEL_FEE_GAS; + $diesel_price = self::REFUEL_FEE_DIESEL; $fuel = new InvoiceItem(); error_log('fuel type - ' . $ftype); From cf8c3bb8e1c8f2b0a95e7f4991395f497e392c4f Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 20 Sep 2019 09:53:49 +0000 Subject: [PATCH 05/10] Move setting of invoice status and createdby inside the invoice generator. #265 --- src/Controller/JobOrderController.php | 5 ----- src/Controller/RAPIController.php | 1 - .../InvoiceGenerator/ResqInvoiceGenerator.php | 21 +++++++++++++++---- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 3563b6b9..7d9993d7 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -8,7 +8,6 @@ use App\Ramcar\WarrantyClass; use App\Ramcar\DiscountApply; use App\Ramcar\TradeInType; use App\Ramcar\InvoiceCriteria; -use App\Ramcar\InvoiceStatus; use App\Ramcar\ModeOfPayment; use App\Ramcar\TransactionOrigin; use App\Ramcar\JOEventType; @@ -328,8 +327,6 @@ class JobOrderController extends Controller { // generate the invoice $iobj = $ic->generateInvoice($criteria); - $iobj->setStatus(InvoiceStatus::DRAFT) - ->setCreatedBy($this->getUser()); // validate $ierrors = $validator->validate($iobj); @@ -523,8 +520,6 @@ class JobOrderController extends Controller { // generate the invoice $iobj = $ic->generateInvoice($criteria); - $iobj->setStatus(InvoiceStatus::DRAFT) - ->setCreatedBy($this->getUser()); // validate $ierrors = $validator->validate($iobj); diff --git a/src/Controller/RAPIController.php b/src/Controller/RAPIController.php index 0c997435..67a598a6 100644 --- a/src/Controller/RAPIController.php +++ b/src/Controller/RAPIController.php @@ -840,7 +840,6 @@ class RAPIController extends Controller } $invoice = $ic->generateInvoice($crit); - $invoice->setStatus(InvoiceStatus::DRAFT); // remove previous invoice $old_invoice = $jo->getInvoice(); diff --git a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php index 456b0021..ed936c8a 100644 --- a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php @@ -2,7 +2,10 @@ 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; @@ -27,11 +30,14 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface const OTHER_SERVICES_FEE = 200; const COOLANT_FEE = 1600; const REFUEL_FEE_GAS = 260; - const REFUEL_FEE_DIESEL = 220; + const REFUEL_FEE_DIESEL = 220; + + private $security; // creates invoice based on the criteria sent - public function __construct() + public function __construct(Security $security) { + $this->security = $security; } public function generateInvoice(InvoiceCriteria $criteria) @@ -95,12 +101,19 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface // 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']); - + ->setTradeIn($total['ti_rate']) + ->setStatus(InvoiceStatus::DRAFT); // dump //Debug::dump($invoice, 1); From ca97897a2a3ba504189e0b690fde6a666be46d92 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 24 Sep 2019 06:58:55 +0000 Subject: [PATCH 06/10] Move the saving of new job order to a job order generator service. #265 --- config/services.yaml | 10 +- src/Controller/JobOrderController.php | 76 +------ .../ResqJobOrderGenerator.php | 193 ++++++++++++++++++ src/Service/JobOrderGeneratorInterface.php | 12 ++ 4 files changed, 221 insertions(+), 70 deletions(-) create mode 100644 src/Service/JobOrderGenerator/ResqJobOrderGenerator.php create mode 100644 src/Service/JobOrderGeneratorInterface.php diff --git a/config/services.yaml b/config/services.yaml index 958e8133..466fd4a8 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -131,8 +131,14 @@ services: tags: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController } - # invoice creator + # invoice generator App\Service\InvoiceGenerator\ResqInvoiceGenerator: ~ - # invoice creator interface + # invoice generator interface App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\ResqInvoiceGenerator" + + # job order generator + App\Service\JobOrderGenerator\ResqJobOrderGenerator: ~ + + #job order generator interface + App\Service\JobOrderGeneratorInterface: "@App\\Service\\JobOrderGenerator\\ResqJobOrderGenerator" diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 7d9993d7..d77d7ece 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -27,6 +27,7 @@ use App\Entity\JOEvent; use App\Entity\JORejection; use App\Service\InvoiceGeneratorInterface; +use App\Service\JobOrderGeneratorInterface; use App\Service\MapTools; use App\Service\HubCounter; use App\Service\MQTTClient; @@ -422,7 +423,8 @@ class JobOrderController extends Controller return $this->render('job-order/form.html.twig', $params); } - public function incomingSubmit(Request $req, ValidatorInterface $validator, InvoiceGeneratorInterface $ic) + public function incomingSubmit(Request $req, ValidatorInterface $validator, + JobOrderGeneratorInterface $joc) { $this->denyAccessUnlessGranted('jo_in.list', null, 'No access.'); @@ -488,61 +490,12 @@ class JobOrderController extends Controller } } - // instantiate invoice criteria - $criteria = new InvoiceCriteria(); - $criteria->setServiceType($stype) - ->setCustomerVehicle($cust_vehicle); + // call service to generate job order and invoice + $invoice_items = $req->request->get('invoice_items', []); + $promo_id = $req->request->get('invoice_promo'); - $ierror = $this->invoicePromo($em, $criteria, $req->request->get('invoice_promo')); - $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->generateInvoice($criteria); - - // 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(); - } + error_log('number of invoice items ' . count($invoice_items)); + $joc->generateJobOrder($obj, $promo_id, $invoice_items, $error_array); } // check if any errors were found @@ -554,19 +507,6 @@ class JobOrderController extends Controller ], 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 $this->json([ 'success' => 'Changes have been saved!' diff --git a/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php b/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php new file mode 100644 index 00000000..949a4a62 --- /dev/null +++ b/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php @@ -0,0 +1,193 @@ +em = $em; + $this->ic = $ic; + $this->security = $security; + $this->validator = $validator; + } + public function generateJobOrder(JobOrder $jo, $promo_id, $invoice_items, &$error_array) + { + // TODO: data validation to be moved here + $validator = $this->validator; + $em = $this->em; + + // 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 = $validator->validate($iobj); + + // add errors to list + foreach ($ierrors as $error) { + $error_array[$error->getPropertyPath()] = $error->getMessage(); + } + + // add invoice to JO + $jo->setInvoice($iobj); + + $em->persist($iobj); + + } + + // validate + $errors = $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 + $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); + } + + $em->persist($event); + + $em->flush(); + } + + return $error_array; + } + + 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; + } +} diff --git a/src/Service/JobOrderGeneratorInterface.php b/src/Service/JobOrderGeneratorInterface.php new file mode 100644 index 00000000..fb4d641b --- /dev/null +++ b/src/Service/JobOrderGeneratorInterface.php @@ -0,0 +1,12 @@ + Date: Wed, 25 Sep 2019 02:20:16 +0000 Subject: [PATCH 07/10] Refactor submission of updated job order. #265 --- src/Controller/JobOrderController.php | 79 ++-------------- .../ResqJobOrderGenerator.php | 90 +++++++++++-------- 2 files changed, 56 insertions(+), 113 deletions(-) diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index d77d7ece..fe02416d 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -251,7 +251,7 @@ class JobOrderController extends Controller return $this->render('job-order/form.html.twig', $params); } - public function openEditSubmit(Request $req, ValidatorInterface $validator, InvoiceGeneratorInterface $ic, $id) + public function openEditSubmit(Request $req, ValidatorInterface $validator, JobOrderGeneratorInterface $joc, $id) { $this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.'); @@ -296,68 +296,11 @@ class JobOrderController extends Controller // did they change invoice? $invoice_items = $req->request->get('invoice_items', []); - $invoice_change = $req->request->get('invoice_change', 0); - if ($invoice_change) - { - // instantiate invoice criteria - $criteria = new InvoiceCriteria(); - $criteria->setServiceType($stype) - ->setCustomerVehicle($obj->getCustomerVehicle()); + $promo_id = $req->request->get('invoice_promo'); + + // call service to generate job order and invoice + $joc->generateJobOrder($obj, $promo_id, $invoice_items, $error_array); - $ierror = $this->invoicePromo($em, $criteria, $req->request->get('invoice_promo')); - - // 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->generateInvoice($criteria); - - // 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 @@ -369,17 +312,6 @@ class JobOrderController extends Controller ], 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 $this->json([ 'success' => 'Changes have been saved!' @@ -494,7 +426,6 @@ class JobOrderController extends Controller $invoice_items = $req->request->get('invoice_items', []); $promo_id = $req->request->get('invoice_promo'); - error_log('number of invoice items ' . count($invoice_items)); $joc->generateJobOrder($obj, $promo_id, $invoice_items, $error_array); } diff --git a/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php b/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php index 949a4a62..38e347bc 100644 --- a/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php +++ b/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php @@ -37,9 +37,47 @@ class ResqJobOrderGenerator implements JobOrderGeneratorInterface public function generateJobOrder(JobOrder $jo, $promo_id, $invoice_items, &$error_array) { // TODO: data validation to be moved here - $validator = $this->validator; - $em = $this->em; + + $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()) @@ -73,54 +111,28 @@ class ResqJobOrderGenerator implements JobOrderGeneratorInterface $iobj = $this->ic->generateInvoice($criteria); // validate - $ierrors = $validator->validate($iobj); + $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); - $em->persist($iobj); + $this->em->persist($iobj); } - - // validate - $errors = $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 - $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); - } - - $em->persist($event); - - $em->flush(); - } - - return $error_array; } protected function invoicePromo(InvoiceCriteria $criteria, $promo_id) From f766965f8130810489a6aea8308ddefde6997012 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 25 Sep 2019 03:52:14 +0000 Subject: [PATCH 08/10] Add checking for invoice change. #265 --- src/Controller/JobOrderController.php | 6 ++++-- src/Service/JobOrderGenerator/ResqJobOrderGenerator.php | 8 ++++++-- src/Service/JobOrderGeneratorInterface.php | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index fe02416d..4f5bfd76 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -296,10 +296,11 @@ class JobOrderController extends Controller // did they change invoice? $invoice_items = $req->request->get('invoice_items', []); + $invoice_change = $req->request->get('invoice_change', 0); $promo_id = $req->request->get('invoice_promo'); // call service to generate job order and invoice - $joc->generateJobOrder($obj, $promo_id, $invoice_items, $error_array); + $joc->generateJobOrder($obj, $promo_id, $invoice_change, $invoice_items, $error_array); } @@ -425,8 +426,9 @@ class JobOrderController extends Controller // call service to generate job order and invoice $invoice_items = $req->request->get('invoice_items', []); $promo_id = $req->request->get('invoice_promo'); + $invoice_change = true; - $joc->generateJobOrder($obj, $promo_id, $invoice_items, $error_array); + $joc->generateJobOrder($obj, $promo_id, $invoice_change, $invoice_items, $error_array); } // check if any errors were found diff --git a/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php b/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php index 38e347bc..118dbe97 100644 --- a/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php +++ b/src/Service/JobOrderGenerator/ResqJobOrderGenerator.php @@ -34,11 +34,15 @@ class ResqJobOrderGenerator implements JobOrderGeneratorInterface $this->security = $security; $this->validator = $validator; } - public function generateJobOrder(JobOrder $jo, $promo_id, $invoice_items, &$error_array) + public function generateJobOrder(JobOrder $jo, $promo_id, $invoice_change, $invoice_items, &$error_array) { // TODO: data validation to be moved here - $this->processInvoice($jo, $promo_id, $invoice_items, $error_array); + // check if invoice changed + if ($invoice_change) + { + $this->processInvoice($jo, $promo_id, $invoice_items, $error_array); + } // validate $errors = $this->validator->validate($jo); diff --git a/src/Service/JobOrderGeneratorInterface.php b/src/Service/JobOrderGeneratorInterface.php index fb4d641b..da4090cb 100644 --- a/src/Service/JobOrderGeneratorInterface.php +++ b/src/Service/JobOrderGeneratorInterface.php @@ -8,5 +8,6 @@ use App\Entity\InvoiceItem; interface JobOrderGeneratorInterface { // generate job order - public function generateJobOrder(JobOrder $jo, int $promo_id, array $invoice_items, array &$error_array); + public function generateJobOrder(JobOrder $jo, int $promo_id, bool $invoice_change, + array $invoice_items, array &$error_array); } From 98a6bfc8aecd487ab40ddf03cab1d783ea41f095 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 25 Sep 2019 05:45:40 +0000 Subject: [PATCH 09/10] Create invoice and job generator for cmb. Modify services.yaml for cmb. #265 --- config/services.yaml | 8 +- .../InvoiceGenerator/CmbInvoiceGenerator.php | 493 ++++++++++++++++++ .../CmbJobOrderGenerator.php | 209 ++++++++ 3 files changed, 706 insertions(+), 4 deletions(-) create mode 100644 src/Service/InvoiceGenerator/CmbInvoiceGenerator.php create mode 100644 src/Service/JobOrderGenerator/CmbJobOrderGenerator.php diff --git a/config/services.yaml b/config/services.yaml index 466fd4a8..9b9231d3 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -132,13 +132,13 @@ services: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController } # invoice generator - App\Service\InvoiceGenerator\ResqInvoiceGenerator: ~ + App\Service\InvoiceGenerator\CmbInvoiceGenerator: ~ # invoice generator interface - App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\ResqInvoiceGenerator" + App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\CmbInvoiceGenerator" # job order generator - App\Service\JobOrderGenerator\ResqJobOrderGenerator: ~ + App\Service\JobOrderGenerator\CmbJobOrderGenerator: ~ #job order generator interface - App\Service\JobOrderGeneratorInterface: "@App\\Service\\JobOrderGenerator\\ResqJobOrderGenerator" + App\Service\JobOrderGeneratorInterface: "@App\\Service\\JobOrderGenerator\\CmbJobOrderGenerator" diff --git a/src/Service/InvoiceGenerator/CmbInvoiceGenerator.php b/src/Service/InvoiceGenerator/CmbInvoiceGenerator.php new file mode 100644 index 00000000..8ea9c74b --- /dev/null +++ b/src/Service/InvoiceGenerator/CmbInvoiceGenerator.php @@ -0,0 +1,493 @@ +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; + } + +} diff --git a/src/Service/JobOrderGenerator/CmbJobOrderGenerator.php b/src/Service/JobOrderGenerator/CmbJobOrderGenerator.php new file mode 100644 index 00000000..15c8506d --- /dev/null +++ b/src/Service/JobOrderGenerator/CmbJobOrderGenerator.php @@ -0,0 +1,209 @@ +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; + } +} From 6e3be9edc8dec0c6e97defde3c6f9c99a76ae1f2 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 26 Sep 2019 06:57:01 +0000 Subject: [PATCH 10/10] Rename from Cmb to CMB. #265 --- config/services.yaml | 8 ++++---- .../{CmbInvoiceGenerator.php => CMBInvoiceGenerator.php} | 2 +- ...{CmbJobOrderGenerator.php => CMBJobOrderGenerator.php} | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/Service/InvoiceGenerator/{CmbInvoiceGenerator.php => CMBInvoiceGenerator.php} (99%) rename src/Service/JobOrderGenerator/{CmbJobOrderGenerator.php => CMBJobOrderGenerator.php} (98%) diff --git a/config/services.yaml b/config/services.yaml index 9b9231d3..71d13a98 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -132,13 +132,13 @@ services: - { name: kernel.event_listener, event: kernel.controller, method: onKernelController } # invoice generator - App\Service\InvoiceGenerator\CmbInvoiceGenerator: ~ + App\Service\InvoiceGenerator\CMBInvoiceGenerator: ~ # invoice generator interface - App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\CmbInvoiceGenerator" + App\Service\InvoiceGeneratorInterface: "@App\\Service\\InvoiceGenerator\\CMBInvoiceGenerator" # job order generator - App\Service\JobOrderGenerator\CmbJobOrderGenerator: ~ + App\Service\JobOrderGenerator\CMBJobOrderGenerator: ~ #job order generator interface - App\Service\JobOrderGeneratorInterface: "@App\\Service\\JobOrderGenerator\\CmbJobOrderGenerator" + App\Service\JobOrderGeneratorInterface: "@App\\Service\\JobOrderGenerator\\CMBJobOrderGenerator" diff --git a/src/Service/InvoiceGenerator/CmbInvoiceGenerator.php b/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php similarity index 99% rename from src/Service/InvoiceGenerator/CmbInvoiceGenerator.php rename to src/Service/InvoiceGenerator/CMBInvoiceGenerator.php index 8ea9c74b..00f4cac3 100644 --- a/src/Service/InvoiceGenerator/CmbInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php @@ -19,7 +19,7 @@ use App\Service\InvoiceGeneratorInterface; use Doctrine\Common\Util\Debug; -class CmbInvoiceGenerator implements InvoiceGeneratorInterface +class CMBInvoiceGenerator implements InvoiceGeneratorInterface { const TAX_RATE = 0.00; const SERVICE_FEE = 300; diff --git a/src/Service/JobOrderGenerator/CmbJobOrderGenerator.php b/src/Service/JobOrderGenerator/CMBJobOrderGenerator.php similarity index 98% rename from src/Service/JobOrderGenerator/CmbJobOrderGenerator.php rename to src/Service/JobOrderGenerator/CMBJobOrderGenerator.php index 15c8506d..3d01983c 100644 --- a/src/Service/JobOrderGenerator/CmbJobOrderGenerator.php +++ b/src/Service/JobOrderGenerator/CMBJobOrderGenerator.php @@ -21,7 +21,7 @@ use App\Service\JobOrderGeneratorInterface; use DateTime; -class CmbJobOrderGenerator implements JobOrderGeneratorInterface +class CMBJobOrderGenerator implements JobOrderGeneratorInterface { protected $em; protected $ic;