resq/src/Service/InvoiceManager.php
2023-06-01 04:39:38 -04:00

204 lines
5.8 KiB
PHP

<?php
namespace App\Service;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Invoice;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\InvoiceStatus;
use App\Entity\InvoiceItem;
use App\Entity\User;
use App\Entity\Battery;
class InvoiceManager
{
protected $em;
protected $available_rules;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
$this->available_rules = $this->getAvailableRules();
}
public function getAvailableRules()
{
// TODO: get list of invoice rules from .env
return [
new Invoice\ServiceType(),
new Invoice\BatterySales(),
new Invoice\BatteryReplacementWarranty(),
new Invoice\Jumpstart(),
new Invoice\JumpstartWarranty(),
new Invoice\PostRecharged(),
new Invoice\PostReplacement(),
new Invoice\Overheat(),
new Invoice\Fuel(),
new Invoice\TireRepair(),
new Invoice\DiscountType(),
new Invoice\TradeIn(),
new Invoice\Tax(),
];
}
public function getServiceTypeFees()
{
return [
'service_fee' => 300,
'coolant_fee' => 1600,
'post_recharged_fee' => 300,
'jumpstart_troubleshoot_fee' => 150,
'jumpstart_warranty_fee' => 0,
'battery_replacement_fee' => 0,
'battery_warranty_fee' => 0,
'other_services_fee' => 200,
'fuel_fee_gas' => 320,
'fuel_fee_diesel' => 340,
];
}
public function getTaxRate()
{
return 0.12;
}
// check what rules to use given the criteria
public function check($criteria)
{
$active_rules = [];
foreach ($this->available_rules as $rule)
{
$is_active = $rule->check($criteria);
if ($is_active)
$active_rules[$rule->getID()] = $rule;
}
return $active_rules;
}
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();
$flag_trade_in = false;
foreach ($entries as $entry)
{
if ($entry['trade_in'] != null)
{
$flag_trade_in = true;
}
}
$invoice_items = [];
$data = [];
foreach ($active_rules as $id => $active_rule)
{
// each criteria can only have one service type
// find the rule for the service type
if ($id == $stype)
{
$items = [];
$computed_items = $active_rule->compute($criteria, $stype_fees, $total);
foreach ($computed_items as $computed_item)
{
if (!empty($computed_item))
{
$items[] = $computed_item;
}
}
// check if tax is needed
if ($is_taxable)
{
$tax_rate = $this->getTaxRate();
if (isset($active_rules['tax']))
{
$active_rules['tax']->compute($tax_rate, $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, $total);
foreach ($tradein_items as $tradein_item)
{
$items[] = $tradein_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, $total);
foreach ($discount_items as $discount_item)
{
$items[] = $discount_item;
}
}
}
$promo = null;
foreach ($items as $item)
{
$invoice_item = new InvoiceItem();
$invoice_item->setTitle($item['title'])
->setQuantity($item['qty'])
->setPrice($item['price']);
if (isset($item['battery']))
$invoice_item->setBattery($item['battery']);
if (isset($item['promo']))
$promo = $item['promo'];
$invoice_items[] = $invoice_item;
}
// also need to return the total and the promo
$data[] = [
'promo' => $promo,
'invoice_items' => $invoice_items,
'total' => $total,
];
}
}
return $data;
}
}