Move the invoice generation out of the job order service and into the invoice generator service. #270

This commit is contained in:
Korina Cordero 2019-10-02 01:47:57 +00:00
parent 08bd23fe30
commit f205f04b48
5 changed files with 290 additions and 271 deletions

View file

@ -3,6 +3,9 @@
namespace App\Service\InvoiceGenerator;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\InvoiceStatus;
@ -13,6 +16,8 @@ use App\Ramcar\FuelType;
use App\Entity\Invoice;
use App\Entity\InvoiceItem;
use App\Entity\Battery;
use App\Entity\Promo;
use App\Entity\User;
use App\Service\InvoiceGeneratorInterface;
@ -33,11 +38,16 @@ class CMBInvoiceGenerator implements InvoiceGeneratorInterface
const REFUEL_FEE_DIESEL = 220;
private $security;
protected $em;
protected $validator;
// creates invoice based on the criteria sent
public function __construct(Security $security)
public function __construct(Security $security, EntityManagerInterface $em,
ValidatorInterface $validator)
{
$this->security = $security;
$this->em = $em;
$this->validator = $validator;
}
public function generateInvoice(InvoiceCriteria $criteria)
@ -121,6 +131,69 @@ class CMBInvoiceGenerator implements InvoiceGeneratorInterface
return $invoice;
}
// generate invoice criteria
public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, &$error_array)
{
$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->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
$em->remove($old_invoice);
$em->flush();
}
// add invoice to JO
$jo->setInvoice($iobj);
$em->persist($iobj);
}
}
protected function getTaxAmount($price)
{
$vat_ex_price = $this->getTaxExclusivePrice($price);
@ -154,6 +227,75 @@ class CMBInvoiceGenerator implements InvoiceGeneratorInterface
return 0;
}
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;
}
protected function processEntries(&$total, InvoiceCriteria $criteria, Invoice $invoice)
{
// error_log('processing entries...');

View file

@ -3,6 +3,9 @@
namespace App\Service\InvoiceGenerator;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\ORM\EntityManagerInterface;
use App\Ramcar\InvoiceCriteria;
use App\Ramcar\InvoiceStatus;
@ -33,11 +36,16 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface
const REFUEL_FEE_DIESEL = 220;
private $security;
protected $em;
protected $validator;
// creates invoice based on the criteria sent
public function __construct(Security $security)
public function __construct(Security $security, EntityManagerInterface $em,
ValidatorInterface $validator)
{
$this->security = $security;
$this->em = $em;
$this->validator = $validator;
}
public function generateInvoice(InvoiceCriteria $criteria)
@ -108,9 +116,6 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface
$invoice->setCreatedBy($user);
}
// NOTE: we compute and save VAT up to the 2nd decimal place.
// it's only in the display when viewing a job order, where
// VAT is seen as a whole number.
$invoice->setTotalPrice($total['total_price'])
->setVATExclusivePrice($total['vat_ex_price'])
->setVAT($total['vat'])
@ -124,6 +129,69 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface
return $invoice;
}
// generate invoice criteria
public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, &$error_array)
{
$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->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
$em->remove($old_invoice);
$em->flush();
}
// add invoice to JO
$jo->setInvoice($iobj);
$em->persist($iobj);
}
}
protected function getTaxAmount($price)
{
$vat_ex_price = $this->getTaxExclusivePrice($price);
@ -157,6 +225,75 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface
return 0;
}
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;
}
protected function processEntries(&$total, InvoiceCriteria $criteria, Invoice $invoice)
{
// error_log('processing entries...');

View file

@ -3,6 +3,7 @@
namespace App\Service;
use App\Entity\Invoice;
use App\Entity\JobOrder;
use App\Ramcar\InvoiceCriteria;
@ -11,4 +12,7 @@ interface InvoiceGeneratorInterface
// generate invoice using a criteria
public function generateInvoice(InvoiceCriteria $criteria);
// generate invoice criteria
public function generateInvoiceCriteria(JobOrder $jo, int $promo_id, array $invoice_items, array &$error_array);
}

View file

@ -16,7 +16,6 @@ use Doctrine\DBAL\LockMode;
use Doctrine\ORM\PessimisticLockException;
use App\Entity\JobOrder;
use App\Entity\Battery;
use App\Entity\BatteryManufacturer;
use App\Entity\JOEvent;
use App\Entity\CustomerVehicle;
@ -338,8 +337,7 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
// check if invoice changed
if ($invoice_change)
{
// TODO: move invoice processing to InvoiceGenerator
$this->processInvoice($jo, $promo_id, $invoice_items, $error_array);
$this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $error_array);
}
// validate
@ -2154,134 +2152,4 @@ class CMBJobOrderHandler implements JobOrderHandlerInterface
->setParameter('status', $status);
}
}
// TODO: move this to InvoiceGenerator
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);
}
}
//TODO: move this to InvoiceGenerator
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;
}
// TODO: move this to InvoiceGenerator
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;
}
}

View file

@ -16,7 +16,6 @@ use Doctrine\DBAL\LockMode;
use Doctrine\ORM\PessimisticLockException;
use App\Entity\JobOrder;
use App\Entity\Battery;
use App\Entity\BatteryManufacturer;
use App\Entity\JOEvent;
use App\Entity\CustomerVehicle;
@ -338,8 +337,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
// check if invoice changed
if ($invoice_change)
{
// TODO: move invoice processing to InvoiceGenerator
$this->processInvoice($jo, $promo_id, $invoice_items, $error_array);
$this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $error_array);
}
// validate
@ -2154,134 +2152,4 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
->setParameter('status', $status);
}
}
// TODO: move this to InvoiceGenerator
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);
}
}
//TODO: move this to InvoiceGenerator
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;
}
// TODO: move this to InvoiceGenerator
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;
}
}