Add tax rule. #744

This commit is contained in:
Korina Cordero 2023-05-30 05:54:16 -04:00
parent 9bac6df2df
commit f598e4f426
6 changed files with 204 additions and 35 deletions

View file

@ -108,7 +108,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' NO TRADE IN NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -132,7 +132,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' QUANTITY NO TRADE IN NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -154,13 +154,13 @@ class TestInvoiceManagerCommand extends Command
$rules = $this->inv_manager->check($criteria);
error_log(print_r($rules, true));
// error_log(print_r($rules, true));
$invoice_items = $this->inv_manager->compute($criteria, $rules);
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' PREMIUM TRADE IN SAME BATTERY NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -188,7 +188,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' MOTOLITE TRADE IN SAME BATTERY NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -216,7 +216,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' OTHER TRADE IN SAME BATTERY NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -247,7 +247,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' PREMIUM TRADE IN DIFFERENT BATTERY NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -278,7 +278,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' MOTOLITE TRADE IN DIFFERENT BATTERY NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -309,12 +309,39 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_NEW . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' OTHER TRADE IN DIFFERENT BATTERY NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
protected function testBatterySalesTradeInQuantityNoDiscount()
{
$criteria = new InvoiceCriteria();
// TEST SCENARIO: new battery, trade-in different battery, premium, no discount
$criteria->setServiceType(ServiceType::BATTERY_REPLACEMENT_NEW);
$battery_id = 1038;
$battery = $this->em->getRepository(Battery::class)->find($battery_id);
// add battery
$criteria->addEntry($battery, null, 1);
$trade_battery_id = 1037;
$trade_battery = $this->em->getRepository(Battery::class)->find($trade_battery_id);
// add battery for trade in
$criteria->addEntry($trade_battery, 'other', 3);
$rules = $this->inv_manager->check($criteria);
// error_log(print_r($rules, true));
$invoice_items = $this->inv_manager->compute($criteria, $rules);
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_NEW) . ' QUANTITY NO DISCOUNT ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
protected function testBatteryReplacementWarranty()
@ -337,7 +364,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::BATTERY_REPLACEMENT_WARRANTY . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::BATTERY_REPLACEMENT_WARRANTY) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -362,7 +389,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::EMERGENCY_REFUEL . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::EMERGENCY_REFUEL) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -387,7 +414,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::EMERGENCY_REFUEL . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::EMERGENCY_REFUEL) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -412,7 +439,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::EMERGENCY_REFUEL . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::EMERGENCY_REFUEL) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -437,7 +464,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::EMERGENCY_REFUEL . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::EMERGENCY_REFUEL) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -456,7 +483,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::JUMPSTART_TROUBLESHOOT . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::JUMPSTART_TROUBLESHOOT) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -475,7 +502,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::JUMPSTART_WARRANTY . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::JUMPSTART_WARRANTY) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -501,7 +528,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::OVERHEAT_ASSISTANCE . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::OVERHEAT_ASSISTANCE) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -526,7 +553,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::OVERHEAT_ASSISTANCE . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::OVERHEAT_ASSISTANCE) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -545,7 +572,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::POST_RECHARGED . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::POST_RECHARGED) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -564,7 +591,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::POST_REPLACEMENT . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::POST_REPLACEMENT) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -589,7 +616,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::TIRE_REPAIR . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::TIRE_REPAIR) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}
@ -614,7 +641,7 @@ class TestInvoiceManagerCommand extends Command
foreach ($invoice_items as $invoice_item)
{
error_log('TEST: ' . ServiceType::TIRE_REPAIR . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
error_log('TEST: ' . strtoupper(ServiceType::TIRE_REPAIR) . ' ' . $invoice_item->getTitle() . ' ' . $invoice_item->getQuantity() . ' ' . $invoice_item->getPrice());
}
}

View file

@ -50,6 +50,7 @@ class BatterySales implements InvoiceInterface
$price = $batt->getSellingPrice();
$items[] = [
'service_type' => $this->getID(),
'battery' => $batt,
'qty' => $qty,
'title' => $this->getTitle($batt),

View file

@ -27,7 +27,28 @@ class DiscountType implements InvoiceInterface
public function compute($criteria, $stype_fees)
{
return [];
$items = [];
$promos = $criteria->getPromos();
// 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;
}
return $items;
}
}

82
src/Invoice/Tax.php Normal file
View file

@ -0,0 +1,82 @@
<?php
namespace App\Invoice;
use App\InvoiceInterface;
class Tax implements InvoiceInterface
{
const TAX_RATE = 0.12;
public function check($criteria)
{
if (!empty($criteria->isTaxable()))
return true;
return false;
}
public function getTemplate()
{
return 'invoice/tax.html.twig';
}
public function getID()
{
return 'tax';
}
public function compute($items, &$total)
{
foreach ($items as $item)
{
$price = $item['price'];
$qty = $item['qty'];
if (isset($items['service_type']))
{
if ($items['service_type'] == 'battery_new')
{
// battery purchase
if (isset($item['battery']))
{
// battery purchase
$vat = $this->getTaxAmount($price);
$qty_price = bcmul($price, $qty, 2);
$price_minus_vat = bcsub($price, $vat, 2);
$qty_price_minus_vat = bcmul($price_minus_vat, $qty, 2);
$total['sell_price'] = bcadd($total['sell_price'], $qty_price, 2);
$total['vat'] = bcadd($total['vat'], $qty_price, 2);
$total['vat_ex_price'] = bcadd($total['vat_ex_price'], $qty_price_minus_vat, 2);
$total['total_price'] = bcadd($total['total_price'], $qty_price, 2);
}
}
}
else
{
// everything else
}
}
}
protected function getTaxAmount($price)
{
$vat_ex_price = $this->getTaxExclusivePrice($price);
$tax_amount = bcsub($price, $vat_ex_price, 2);
return $tax_amount;
}
protected function getTaxExclusivePrice($price)
{
$tax_ex_price = bcdiv($price, bcadd(1, self::TAX_RATE, 2), 2);
return $tax_ex_price;
}
}

View file

@ -35,7 +35,7 @@ class TradeIn implements InvoiceInterface
return 'trade_in';
}
public function compute($criteria)
public function compute($criteria, $stype_fees)
{
$items = [];

View file

@ -44,6 +44,7 @@ class InvoiceManager
new Invoice\TireRepair(),
new Invoice\DiscountType(),
new Invoice\TradeIn(),
new Invoice\Tax,
];
}
@ -80,9 +81,21 @@ class InvoiceManager
public function compute($criteria, $active_rules)
{
// initialize
$total = [
'sell_price' => 0.0,
'vat' => 0.0,
'vat_ex_price' => 0.0,
'ti_rate' => 0.0,
'total_price' => 0.0,
'discount' => 0.0,
];
// get what is in criteria
$stype = $criteria->getServiceType();
$entries = $criteria->getEntries();
$promos = $criteria->getPromos();
$is_taxable = $criteria->isTaxable();
// get the service type fees
$stype_fees = $this->getServiceTypeFees();
@ -102,23 +115,37 @@ class InvoiceManager
if ($id == $stype)
{
$items = [];
// process trade-ins by calling the trade-in rule if there are trade-ins
// since it's lumped with only the battery_new service type
if ($flag_trade_in)
{
$tradein_items = $active_rules['trade_in']->compute($criteria);
foreach ($tradein_items as $tradein_item)
{
$items[] = $tradein_item;
}
}
$computed_items = $active_rule->compute($criteria, $stype_fees);
foreach ($computed_items as $computed_item)
{
if (!empty($computed_item))
{
$items[] = $computed_item;
}
}
// check if tax is needed
if ($is_taxable)
{
if (isset($active_rules['tax']))
{
$active_rule['tax']->compute($items, $total);
}
}
// process trade-ins by calling the trade-in rule if there are trade-ins among the entries
if ($flag_trade_in)
{
if (isset($active_rules['trade_in']))
{
$tradein_items = $active_rules['trade_in']->compute($criteria, $stype_fees);
foreach ($tradein_items as $tradein_item)
{
$items[] = $tradein_item;
}
}
}
foreach ($items as $item)
{
@ -133,9 +160,20 @@ class InvoiceManager
$invoice_items[] = $invoice_item;
}
// process promos, if any
if (count($promos) > 0)
{
if (isset($active_rules['discount_type']))
{
$discount_items = $active_rules['discount_type']->compute($criteria, $stype_fees);
}
}
}
}
return $invoice_items;
}
}