From 1c02138f52766b417a03ee1c22bd3226258b8115 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 22 May 2023 06:06:12 -0400 Subject: [PATCH] Add services for the new invoice generator. #744 --- src/Ramcar/InvoiceCriteria.php | 13 +++ src/Service/InvoiceBatteryManager.php | 40 +++++++ src/Service/InvoiceManager.php | 159 ++++++++++++++++++++++++++ src/Service/InvoiceTaxManager.php | 29 +++++ src/Service/InvoiceTradeInManager.php | 53 +++++++++ 5 files changed, 294 insertions(+) create mode 100644 src/Service/InvoiceBatteryManager.php create mode 100644 src/Service/InvoiceManager.php create mode 100644 src/Service/InvoiceTaxManager.php create mode 100644 src/Service/InvoiceTradeInManager.php diff --git a/src/Ramcar/InvoiceCriteria.php b/src/Ramcar/InvoiceCriteria.php index 6665226d..886d6024 100644 --- a/src/Ramcar/InvoiceCriteria.php +++ b/src/Ramcar/InvoiceCriteria.php @@ -15,6 +15,7 @@ class InvoiceCriteria protected $flag_coolant; protected $discount; protected $service_charges; + protected $flag_taxable; // entries are battery and trade-in combos protected $entries; @@ -28,6 +29,7 @@ class InvoiceCriteria $this->flag_coolant = false; $this->discount = 0; $this->service_charges = []; + $this->flag_taxable = false; } public function setServiceType($stype) @@ -153,4 +155,15 @@ class InvoiceCriteria return $this->service_charges; } + public function setIsTaxable($flag = true) + { + $this->flag_taxable = $flag; + return $this; + } + + public function isTaxable() + { + return $this->flag_taxable; + } + } diff --git a/src/Service/InvoiceBatteryManager.php b/src/Service/InvoiceBatteryManager.php new file mode 100644 index 00000000..c9af27e5 --- /dev/null +++ b/src/Service/InvoiceBatteryManager.php @@ -0,0 +1,40 @@ +getSellingPrice(); + + $computed_price = bcmul($sell_price, $qty, 2); + $invoice_batteries = [ + 'title' => $battery->getModel()->getName() . ' ' . $battery->getSize()->getName(), + 'battery' => $battery, + 'qty' => $qty, + 'sell_price' => $computed_price, + 'vat' => 0.0, + 'vat_ex_price' => 0.0, + ]; + + $total['sell_price'] = bcadd($total['sell_price'], $computed_price, 2); + $total['vat'] += 0.00; + $total['vat_ex_price'] += 0.00; + + $total['total_price'] = bcadd($total['total_price'], $computed_price, 2); + } + + return $invoice_batteries; + } +} diff --git a/src/Service/InvoiceManager.php b/src/Service/InvoiceManager.php new file mode 100644 index 00000000..ddb108e2 --- /dev/null +++ b/src/Service/InvoiceManager.php @@ -0,0 +1,159 @@ +security = $security; + $this->em = $em; + $this->validator = $validator; + $this->inv_batt = $inv_batt; + $this->inv_trade = $inv_trade; + $this->inv_tax = $inv_tax; + } + + 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(); + + switch($stype) + { + case ServiceType::JUMPSTART_TROUBLESHOOT: + $this->processJumpstart($total, $invoice); + break; + case ServiceType::JUMPSTART_WARRANTY: + $this->processJumpstartWarranty($total, $invoice); + break; + case ServiceType::BATTERY_REPLACEMENT_NEW: + $this->processEntries($total, $criteria, $invoice); + $this->processDiscount($total, $criteria, $invoice, $cust_tag_info); + 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); + break; + case ServiceType::OVERHEAT_ASSISTANCE: + $this->processOverheat($total, $invoice, $cv, $has_coolant); + break; + case ServiceType::EMERGENCY_REFUEL: + $ftype = $criteria->getCustomerVehicle()->getFuelType(); + $this->processRefuel($total, $invoice, $cv); + break; + } + + // process promos here? + + // get current user + $user = $this->security->getUser(); + // check if user is User or APIUser + if ($user instanceof User) + { + $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); + + return $invoice; + } + + // process battery sales and trade-ins + protected function processEntries(&$total, InvoiceCriteria $criteria, Invoice $invoice) + { + $entries = $criteria->getEntries(); + + $con_batts = []; + $con_tis = []; + foreach($entries as $entry) + { + // batteries purchased should have trade_in set to null + $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 + // need to set battery for trade in so we know what battery is for trade in + // possible that battery purchased is not the same battery for trade in + $ti_key = $size->getID() . '|' . $trade_in; + if (!isset($con_tis[$ti_key])) + $con_tis[$ti_key] = [ + 'batt' => $batt, + 'size' => $size, + 'trade_in' => $trade_in, + 'qty' => 0 + ]; + $con_tis[$ti_key]['qty']++; + } + + $inv_batt_entries = $this->inv_batt->processBatteries($con_batts, $total); + $inv_trade_in_entries = $this->inv_trade->processTradeIns($con_tis, $total); + + // check if we need to compute tax + if ($criteria->isTaxable()) + { + $this->inv_tax->computeTax($inv_batt_entries, $total); + } + } +} diff --git a/src/Service/InvoiceTaxManager.php b/src/Service/InvoiceTaxManager.php new file mode 100644 index 00000000..1535c68e --- /dev/null +++ b/src/Service/InvoiceTaxManager.php @@ -0,0 +1,29 @@ +getTaxAmount($sell_price); + $vat_ex_price = $this->getTaxExclusivePrice($sell_price); + + // TODO: add to the total array the computed vat prices + } + } + + // TODO: use bc functions for these + protected function getTaxAmount($price) + { + $vat_ex_price = $this->getTaxExclusivePrice($price); + return $price - $vat_ex_price; + } + + protected function getTaxExclusivePrice($price) + { + return round($price / (1 + self::TAX_RATE), 2); + } +} diff --git a/src/Service/InvoiceTradeInManager.php b/src/Service/InvoiceTradeInManager.php new file mode 100644 index 00000000..e0e04308 --- /dev/null +++ b/src/Service/InvoiceTradeInManager.php @@ -0,0 +1,53 @@ +getTradeInRate($ti); + + $ti_price = bcmul($ti_rate, -1, 2); + $invoice_trade_ins = [ + 'title' => 'Trade-in ' . TradeInType::getName($ti['trade_in']) . ' ' . $ti['size']->getName() . ' battery'), + 'qty' => $qty, + 'price' => $ti_price, + ]; + + $tti_price = bcmul($ti_rate, $qty, 2); + + $total['ti_rate'] = bcadd($total['ti_rate'], $tti_price, 2); + $total['total_price'] = bcsub($total['total_price'], $tti_price, 2); + } + + return $invoice_trade_ins; + } + + 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; + } +}