Add support for subscription related job orders #799

This commit is contained in:
Ramon Gutierrez 2024-10-26 08:28:17 +08:00
parent d1104b7416
commit e4e031f0a9
6 changed files with 121 additions and 6 deletions

View file

@ -17,6 +17,7 @@ use App\Entity\Battery;
use App\Entity\BatterySize; use App\Entity\BatterySize;
use App\Entity\Customer; use App\Entity\Customer;
use App\Entity\CustomerMetadata; use App\Entity\CustomerMetadata;
use App\Ramcar\ServiceType;
class InvoiceController extends ApiController class InvoiceController extends ApiController
{ {
@ -55,7 +56,16 @@ class InvoiceController extends ApiController
// make invoice criteria // make invoice criteria
$icrit = new InvoiceCriteria(); $icrit = new InvoiceCriteria();
$icrit->setServiceType($req->request->get('service_type'));
// if service type is subscription, set to battery replacement but add extra criteria
$stype = $req->request->get('service_type');
if ($stype === 'subscription') {
$stype = ServiceType::BATTERY_REPLACEMENT_NEW;
$icrit->setSubscription(true);
}
// set the service type
$icrit->setServiceType($stype);
// check promo // check promo
$promo_id = $req->request->get('promo_id'); $promo_id = $req->request->get('promo_id');

View file

@ -42,7 +42,7 @@ use App\Entity\JOEvent;
use App\Entity\Warranty; use App\Entity\Warranty;
use App\Entity\JobOrder; use App\Entity\JobOrder;
use App\Entity\CustomerVehicle; use App\Entity\CustomerVehicle;
use App\Ramcar\SubscriptionStatus;
use DateTime; use DateTime;
class JobOrderController extends ApiController class JobOrderController extends ApiController
@ -616,9 +616,16 @@ class JobOrderController extends ApiController
// validate service type // validate service type
$stype = $req->request->get('service_type'); $stype = $req->request->get('service_type');
// if this is a subscription, change to battery replacement so we follow invoice rules for this
if ($stype === 'subscription') {
$stype = ServiceType::BATTERY_REPLACEMENT_NEW;
}
if (!ServiceType::validate($stype)) { if (!ServiceType::validate($stype)) {
return new ApiResponse(false, 'Invalid service type.'); return new ApiResponse(false, 'Invalid service type.');
} }
$jo->setServiceType($stype); $jo->setServiceType($stype);
// validate warranty // validate warranty
@ -712,12 +719,24 @@ class JobOrderController extends ApiController
$pt_id = $pt_manager->getPriceTier($jo->getCoordinates()); $pt_id = $pt_manager->getPriceTier($jo->getCoordinates());
$icrit->setPriceTier($pt_id); $icrit->setPriceTier($pt_id);
// if subscription, set subscription on invoice criteria and find the subscription row to associate with the JO
if ($req->request->get('service_type') === 'subscription') {
$icrit->setSubscription(true);
// get subscription row and check state
$sub = $cv->getLatestSubscription();
if (empty($sub) || $sub->getStatus() !== SubscriptionStatus::ACTIVE) {
return new ApiResponse(false, 'Invalid subscription state for this vehicle.');
}
// associate subscription with JO
$jo->setSubscription($sub);
}
// send to invoice generator // send to invoice generator
$invoice = $ic->generateInvoice($icrit); $invoice = $ic->generateInvoice($icrit);
$jo->setInvoice($invoice); $jo->setInvoice($invoice);
//error_log("GENERATED INVOICE");
// save here first so we have a JO ID which is required for the hub selector // save here first so we have a JO ID which is required for the hub selector
$this->em->persist($invoice); $this->em->persist($invoice);
$this->em->persist($jo); $this->em->persist($jo);
@ -1406,6 +1425,8 @@ class JobOrderController extends ApiController
$dest = $jo->getCoordinates(); $dest = $jo->getCoordinates();
$sub = $jo->getSubscription();
$jo_data = [ $jo_data = [
'id' => $jo->getID(), 'id' => $jo->getID(),
'date_create' => $jo->getDateCreate()->format('M d, Y'), 'date_create' => $jo->getDateCreate()->format('M d, Y'),
@ -1420,6 +1441,7 @@ class JobOrderController extends ApiController
'landmark' => $jo->getLandmark(), 'landmark' => $jo->getLandmark(),
'jo_status' => $status, 'jo_status' => $status,
'status' => $this->generateAPIRiderStatus($status), 'status' => $this->generateAPIRiderStatus($status),
'subscription' => !empty($sub) ? $sub->getID() : null,
]; ];
// customer vehicle and warranty // customer vehicle and warranty

View file

@ -13,8 +13,8 @@ use Doctrine\Common\Collections\Criteria;
/** /**
* @ORM\Entity * @ORM\Entity
* @ORM\Table(name="customer_vehicle", indexes={@ORM\Index(columns={"plate_number"}, flags={"fulltext"}), * @ORM\Table(name="customer_vehicle", indexes={@ORM\Index(columns={"plate_number"}, flags={"fulltext"})
@ORM\Index(name="plate_number_idx", columns={"plate_number"})}) * @ORM\Index(name="plate_number_idx", columns={"plate_number"})})
*/ */
class CustomerVehicle class CustomerVehicle
{ {

View file

@ -0,0 +1,69 @@
<?php
namespace App\InvoiceRule;
use Doctrine\ORM\EntityManagerInterface;
use App\InvoiceRuleInterface;
use App\Ramcar\ServiceType;
class IsSubscription implements InvoiceRuleInterface
{
protected $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public function getID()
{
return 'discount';
}
public function compute($criteria, &$total)
{
$items = [];
// set the discount to the total selling price
$discount = $total['sell_price'];
$qty = 1;
$price = bcmul(-1, $discount, 2);
$items[] = [
'title' => $this->getTitle(),
'qty' => $qty,
'price' => $price,
];
$total['discount'] = $discount;
$total['total_price'] = bcsub($total['total_price'], $discount, 2);
return $items;
}
public function validatePromo($criteria, $promo_id)
{
// only applies to battery sales
if ($criteria->getServiceType() != ServiceType::BATTERY_REPLACEMENT_NEW)
return null;
// only applies if this is a subscription order
if ($criteria->isSubscription() === false)
return null;
return false;
}
public function validateInvoiceItems($criteria, $invoice_items)
{
return null;
}
protected function getTitle()
{
$title = 'Waived for subscription';
return $title;
}
}

View file

@ -18,6 +18,7 @@ class InvoiceCriteria
protected $flag_taxable; protected $flag_taxable;
protected $source; // use Ramcar's TransactionOrigin protected $source; // use Ramcar's TransactionOrigin
protected $price_tier; protected $price_tier;
protected $is_subscription;
// entries are battery and trade-in combos // entries are battery and trade-in combos
protected $entries; protected $entries;
@ -34,6 +35,7 @@ class InvoiceCriteria
$this->flag_taxable = false; $this->flag_taxable = false;
$this->source = ''; $this->source = '';
$this->price_tier = 0; // set to default $this->price_tier = 0; // set to default
$this->is_subscription = false;
} }
public function setServiceType($stype) public function setServiceType($stype)
@ -202,4 +204,15 @@ class InvoiceCriteria
{ {
return $this->price_tier; return $this->price_tier;
} }
public function setSubscription($is_subscription)
{
$this->is_subscription = $is_subscription;
return $this;
}
public function isSubscription()
{
return $this->is_subscription;
}
} }

View file

@ -55,6 +55,7 @@ class InvoiceManager implements InvoiceGeneratorInterface
new InvoiceRule\Fuel($this->em, $this->pt_manager), new InvoiceRule\Fuel($this->em, $this->pt_manager),
new InvoiceRule\TireRepair($this->em, $this->pt_manager), new InvoiceRule\TireRepair($this->em, $this->pt_manager),
new InvoiceRule\DiscountType($this->em), new InvoiceRule\DiscountType($this->em),
new InvoiceRule\IsSubscription($this->em),
new InvoiceRule\TradeIn($this->em), new InvoiceRule\TradeIn($this->em),
new InvoiceRule\Tax($this->em, $this->pt_manager), new InvoiceRule\Tax($this->em, $this->pt_manager),
]; ];