Add trade-in support to invoice generation and JO creation for app #778
This commit is contained in:
parent
fd0c9ede26
commit
4773d6c08c
3 changed files with 115 additions and 69 deletions
|
|
@ -24,7 +24,6 @@ class InvoiceController extends ApiController
|
|||
'service_type',
|
||||
'cv_id',
|
||||
// 'batt_id',
|
||||
'trade_in',
|
||||
]);
|
||||
|
||||
if (!$validity['is_valid']) {
|
||||
|
|
@ -82,22 +81,31 @@ class InvoiceController extends ApiController
|
|||
|
||||
// check trade-in
|
||||
// only allow motolite, other, none
|
||||
$trade_in = $req->request->get('trade_in');
|
||||
switch ($trade_in) {
|
||||
$trade_in_batt = $req->request->get('trade_in_batt');
|
||||
$trade_in_type = $req->request->get('trade_in_type');
|
||||
|
||||
switch ($trade_in_type) {
|
||||
case TradeInType::MOTOLITE:
|
||||
case TradeInType::OTHER:
|
||||
break;
|
||||
|
||||
default:
|
||||
$trade_in = '';
|
||||
$trade_in_type = '';
|
||||
break;
|
||||
}
|
||||
|
||||
// right now, the app does not include trade-ins but this might change in the future
|
||||
if (empty($trade_in))
|
||||
// add the actual battery item first
|
||||
$icrit->addEntry($batt, null, 1);
|
||||
else
|
||||
$icrit->addEntry($batt, $trade_in, 1);
|
||||
|
||||
// DEBUG
|
||||
|
||||
// if we have a trade in, add it as well
|
||||
if (!empty($trade_in_type) && !empty($trade_in_batt)) {
|
||||
$ti_batt_obj = $this->em->getRepository(Battery::class)->find($trade_in_batt);
|
||||
if (!empty($ti_batt_obj)) {
|
||||
$icrit->addEntry($ti_batt_obj, $trade_in_type, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// set if taxable
|
||||
$icrit->setIsTaxable();
|
||||
|
|
|
|||
|
|
@ -490,7 +490,6 @@ class JobOrderController extends ApiController
|
|||
$validity = $this->validateRequest($req, [
|
||||
'service_type',
|
||||
'cv_id',
|
||||
'trade_in',
|
||||
'long',
|
||||
'lat',
|
||||
'warranty',
|
||||
|
|
@ -502,7 +501,8 @@ class JobOrderController extends ApiController
|
|||
}
|
||||
|
||||
// trade in type
|
||||
$trade_in = $req->request->get('trade_in');
|
||||
$trade_in_batt = $req->request->get('trade_in_batt');
|
||||
$trade_in_type = $req->request->get('trade_in_type', '');
|
||||
|
||||
// address
|
||||
$address = $req->request->get('delivery_address', 'Set by mobile application');
|
||||
|
|
@ -580,7 +580,7 @@ class JobOrderController extends ApiController
|
|||
->setTier1Notes('')
|
||||
->setTier2Notes('')
|
||||
->setDeliveryAddress($address)
|
||||
->setTradeInType($trade_in)
|
||||
->setTradeInType($trade_in_type)
|
||||
->setDeliveryInstructions($instructions)
|
||||
// TODO: error check for valid mode of payment
|
||||
->setModeOfPayment($req->request->get('mode_of_payment'))
|
||||
|
|
@ -669,26 +669,28 @@ class JobOrderController extends ApiController
|
|||
$icrit->addBattery($batt);
|
||||
*/
|
||||
|
||||
// NOTE: trade in is currently not supported. Would it be better
|
||||
// if we remove trade-in as a required parameter? Or just leave it be
|
||||
// and simply not process it?
|
||||
// check trade-in
|
||||
// only allow motolite, other, none
|
||||
switch ($trade_in) {
|
||||
switch ($trade_in_type) {
|
||||
case TradeInType::MOTOLITE:
|
||||
case TradeInType::OTHER:
|
||||
break;
|
||||
|
||||
default:
|
||||
$trade_in = '';
|
||||
$trade_in_type = '';
|
||||
break;
|
||||
}
|
||||
|
||||
// right now, the app does not include trade-ins but this might change in the future
|
||||
if (empty($trade_in))
|
||||
// add the actual battery item first
|
||||
$icrit->addEntry($batt, null, 1);
|
||||
else
|
||||
$icrit->addEntry($batt, $trade_in, 1);
|
||||
|
||||
// if we have a trade in, add it as well
|
||||
if (!empty($trade_in_type) && !empty($trade_in_batt)) {
|
||||
$ti_batt_obj = $this->em->getRepository(Battery::class)->find($trade_in_batt);
|
||||
if (!empty($ti_batt_obj)) {
|
||||
$icrit->addEntry($ti_batt_obj, $trade_in_type, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// set taxable
|
||||
$icrit->setIsTaxable();
|
||||
|
|
@ -975,7 +977,6 @@ class JobOrderController extends ApiController
|
|||
'service_type',
|
||||
'cv_id',
|
||||
// 'batt_id',
|
||||
'trade_in',
|
||||
'long',
|
||||
'lat',
|
||||
'warranty',
|
||||
|
|
@ -987,7 +988,8 @@ class JobOrderController extends ApiController
|
|||
}
|
||||
|
||||
// trade in type
|
||||
$trade_in = $req->request->get('trade_in');
|
||||
$trade_in_batt = $req->request->get('trade_in_batt');
|
||||
$trade_in_type = $req->request->get('trade_in_type', '');
|
||||
|
||||
// address
|
||||
$address = $req->request->get('delivery_address', 'Set by mobile application');
|
||||
|
|
@ -1013,7 +1015,7 @@ class JobOrderController extends ApiController
|
|||
->setTier1Notes('')
|
||||
->setTier2Notes('')
|
||||
->setDeliveryAddress($address)
|
||||
->setTradeInType($trade_in)
|
||||
->setTradeInType($trade_in_type)
|
||||
->setDeliveryInstructions($instructions)
|
||||
// TODO: error check for valid mode of payment
|
||||
->setModeOfPayment($req->request->get('mode_of_payment'));
|
||||
|
|
@ -1098,24 +1100,33 @@ class JobOrderController extends ApiController
|
|||
|
||||
// check trade-in
|
||||
// only allow motolite, other, none
|
||||
switch ($trade_in) {
|
||||
switch ($trade_in_type) {
|
||||
case TradeInType::MOTOLITE:
|
||||
case TradeInType::OTHER:
|
||||
break;
|
||||
|
||||
default:
|
||||
$trade_in = '';
|
||||
$trade_in_type = '';
|
||||
break;
|
||||
}
|
||||
|
||||
// add the actual battery item first
|
||||
$icrit->addEntry($batt, null, 1);
|
||||
|
||||
// if we have a trade in, add it as well
|
||||
if (!empty($trade_in_type) && !empty($trade_in_batt)) {
|
||||
$ti_batt_obj = $this->em->getRepository(Battery::class)->find($trade_in_batt);
|
||||
if (!empty($ti_batt_obj)) {
|
||||
$icrit->addEntry($ti_batt_obj, $trade_in_type, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// set taxable
|
||||
$icrit->setIsTaxable();
|
||||
|
||||
// set JO source
|
||||
$icrit->setSource(TransactionOrigin::MOBILE_APP);
|
||||
|
||||
$icrit->addEntry($batt, $trade_in, 1);
|
||||
|
||||
// send to invoice generator
|
||||
$invoice = $ic->generateInvoice($icrit);
|
||||
$jo->setInvoice($invoice);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use App\Entity\VehicleManufacturer;
|
|||
use App\Entity\Vehicle;
|
||||
use App\Ramcar\JOStatus;
|
||||
use App\Ramcar\ServiceType;
|
||||
use App\Ramcar\TradeInType;
|
||||
use DateTime;
|
||||
|
||||
class VehicleController extends ApiController
|
||||
|
|
@ -165,49 +166,14 @@ class VehicleController extends ApiController
|
|||
return new ApiResponse(false, 'Invalid vehicle.');
|
||||
}
|
||||
|
||||
// compute for trade in value
|
||||
$trade_in_value = 0;
|
||||
$previous_jo_found = false;
|
||||
|
||||
// check for last battery replacement JO
|
||||
$last_jo = $this->em->getRepository(JobOrder::class)->findOneBy([
|
||||
'service_type' => [
|
||||
ServiceType::BATTERY_REPLACEMENT_NEW, ServiceType::BATTERY_REPLACEMENT_WARRANTY
|
||||
],
|
||||
'status' => JOStatus::FULFILLED,
|
||||
'cus_vehicle' => $cv,
|
||||
], ['date_create' => 'desc']);
|
||||
|
||||
if (!empty($last_jo)) {
|
||||
$items = $last_jo->getInvoice()->getItems();
|
||||
|
||||
foreach ($items as $item) {
|
||||
// find the first battery item and get its trade-in value
|
||||
$item_battery = $item->getBattery();
|
||||
if (!empty($item_battery)) {
|
||||
$previous_jo_found = true;
|
||||
$trade_in_value = $item_battery->getSize()->getTIPriceMotolite();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: possibly refactor this bit
|
||||
// if no valid previous JO is found, use lowest value we can find based on battery compatibility
|
||||
if (!$previous_jo_found) {
|
||||
$comp_batteries = $cv->getVehicle()->getBatteries();
|
||||
|
||||
// default order of association is price desc, so we get the last row for the cheapest value possible. this is due to the assumption that we can have multiple battery sizes compatible with a vehicle
|
||||
if (!empty($comp_batteries)) {
|
||||
$lp_battery = array_reverse($comp_batteries->toArray())[0];
|
||||
$trade_in_value = $lp_battery->getSize()->getTIPriceOther();
|
||||
}
|
||||
}
|
||||
// check trade in value
|
||||
$result = $this->getTIEstimateByCV($cv);
|
||||
|
||||
// response
|
||||
return new ApiResponse(true, '', [
|
||||
'previous_jo_found' => $previous_jo_found,
|
||||
'trade_in_value' => $trade_in_value,
|
||||
'trade_in_batt' => $result['trade_in_batt'],
|
||||
'trade_in_type' => $result['trade_in_type'],
|
||||
'trade_in_value' => $result['trade_in_value'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -355,6 +321,67 @@ class VehicleController extends ApiController
|
|||
return new ApiResponse();
|
||||
}
|
||||
|
||||
protected function getTIEstimateByCV($cv)
|
||||
{
|
||||
// compute for trade in value
|
||||
$trade_in_batt = null;
|
||||
$trade_in_value = 0;
|
||||
$trade_in_type = TradeInType::OTHER;
|
||||
$previous_jo_found = false;
|
||||
|
||||
// check for last battery replacement JO
|
||||
$last_jo = $this->em->getRepository(JobOrder::class)->findOneBy([
|
||||
'service_type' => [
|
||||
ServiceType::BATTERY_REPLACEMENT_NEW, ServiceType::BATTERY_REPLACEMENT_WARRANTY
|
||||
],
|
||||
'status' => JOStatus::FULFILLED,
|
||||
'cus_vehicle' => $cv,
|
||||
], ['date_create' => 'desc']);
|
||||
|
||||
if (!empty($last_jo)) {
|
||||
$items = $last_jo->getInvoice()->getItems();
|
||||
|
||||
foreach ($items as $item) {
|
||||
// find the first battery item and get its trade-in value
|
||||
$item_battery = $item->getBattery();
|
||||
if (!empty($item_battery)) {
|
||||
$trade_in_type = TradeInType::MOTOLITE;
|
||||
$trade_in_batt = $item_battery->getID();
|
||||
$previous_jo_found = true;
|
||||
$size = $item_battery->getSize();
|
||||
$trade_in_value = $size->getTIPriceMotolite();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: possibly refactor this bit
|
||||
// if no valid previous JO is found, base the trade-in value on recommended batteries
|
||||
if (!$previous_jo_found) {
|
||||
$comp_batteries = $cv->getVehicle()->getBatteries();
|
||||
|
||||
// get the lowest trade-in value from the list of batteries
|
||||
if (!empty($comp_batteries)) {
|
||||
foreach ($comp_batteries as $battery) {
|
||||
$size = $battery->getSize();
|
||||
$size_ti = $size->getTIPriceOther();
|
||||
|
||||
// get the lowest value or set if not set yet
|
||||
if ($size_ti < $trade_in_value || $trade_in_value == 0) {
|
||||
$trade_in_value = $size_ti;
|
||||
$trade_in_batt = $battery->getID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'trade_in_batt' => $trade_in_batt,
|
||||
'trade_in_type' => $trade_in_type,
|
||||
'trade_in_value' => $trade_in_value,
|
||||
];
|
||||
}
|
||||
|
||||
protected function checkVehicleRequirements(Request $req)
|
||||
{
|
||||
// validate params
|
||||
|
|
|
|||
Loading…
Reference in a new issue