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); }