diff --git a/config/services.yaml b/config/services.yaml index b19ecabc..d20db360 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -310,3 +310,8 @@ services: arguments: $server_key: "%env(FCM_SERVER_KEY)%" $sender_id: "%env(FCM_SENDER_ID)%" + + # price tier manager + App\Service\PriceTierManager: + arguments: + $em: "@doctrine.orm.entity_manager" diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 16a9cdf5..0eb148c5 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -50,6 +50,7 @@ use App\Service\HubFilterLogger; use App\Service\HubFilteringGeoChecker; use App\Service\HashGenerator; use App\Service\JobOrderManager; +use App\Service\PriceTierManager; use App\Entity\MobileSession; use App\Entity\Customer; @@ -2911,6 +2912,10 @@ class APIController extends Controller implements LoggedController // old app doesn't have separate jumpstart $icrit->setSource(TransactionOrigin::CALL); + // set price tier + $pt_id = $this->pt_manager->getPriceTier($jo->getCoordinates()); + $icrit->setPriceTier($pt_id); + // check promo $promo_id = $req->request->get('promo_id'); if (!empty($promo_id)) diff --git a/src/Controller/CAPI/RiderAppController.php b/src/Controller/CAPI/RiderAppController.php index d29f6a04..6cce3745 100644 --- a/src/Controller/CAPI/RiderAppController.php +++ b/src/Controller/CAPI/RiderAppController.php @@ -34,6 +34,7 @@ use App\Service\JobOrderHandlerInterface; use App\Service\InvoiceGeneratorInterface; use App\Service\RisingTideGateway; use App\Service\RiderTracker; +use App\Service\PriceTierManager; use App\Ramcar\ServiceType; use App\Ramcar\TradeInType; @@ -1099,7 +1100,7 @@ class RiderAppController extends ApiController return new APIResponse(true, 'Batteries found.', $data); } - public function changeService(Request $req, EntityManagerInterface $em, InvoiceGeneratorInterface $ic) + public function changeService(Request $req, EntityManagerInterface $em, InvoiceGeneratorInterface $ic, PriceTierManager $pt_manager) { // $this->debugRequest($req); @@ -1203,6 +1204,10 @@ class RiderAppController extends ApiController $crit->setHasCoolant($jo->hasCoolant()); $crit->setIsTaxable(); + // set price tier + $pt_id = $pt_manager->getPriceTier($jo->getCoordinates()); + $icrit->setPriceTier($pt_id); + if ($promo != null) $crit->addPromo($promo); diff --git a/src/Controller/CustomerAppAPI/ApiController.php b/src/Controller/CustomerAppAPI/ApiController.php index 6a25eb80..fdc0ec59 100644 --- a/src/Controller/CustomerAppAPI/ApiController.php +++ b/src/Controller/CustomerAppAPI/ApiController.php @@ -162,6 +162,6 @@ class ApiController extends BaseApiController protected function getGeoErrorMessage() { - return 'Oops! Our service is limited to some areas in Metro Manila, Laguna, Cavite, Pampanga and Baguio only. We will update you as soon as we are able to cover your area'; + return 'Our services are currently limited to some areas in Metro Manila, Baguio, Batangas, Laguna, Cavite, Pampanga, and Palawan. We will update you as soon as we are available in your area. Thank you for understanding. Keep safe!'; } } diff --git a/src/Controller/CustomerAppAPI/InvoiceController.php b/src/Controller/CustomerAppAPI/InvoiceController.php index a5c3a8b8..2e9779eb 100644 --- a/src/Controller/CustomerAppAPI/InvoiceController.php +++ b/src/Controller/CustomerAppAPI/InvoiceController.php @@ -4,18 +4,22 @@ namespace App\Controller\CustomerAppAPI; use Symfony\Component\HttpFoundation\Request; use Catalyst\ApiBundle\Component\Response as ApiResponse; +use CrEOF\Spatial\PHP\Types\Geometry\Point; use App\Service\InvoiceGeneratorInterface; +use App\Service\PriceTierManager; use App\Ramcar\InvoiceCriteria; use App\Ramcar\TradeInType; use App\Ramcar\TransactionOrigin; use App\Entity\CustomerVehicle; use App\Entity\Promo; use App\Entity\Battery; +use App\Entity\Customer; +use App\Entity\CustomerMetadata; class InvoiceController extends ApiController { - public function getEstimate(Request $req, InvoiceGeneratorInterface $ic) + public function getEstimate(Request $req, InvoiceGeneratorInterface $ic, PriceTierManager $pt_manager) { // $this->debugRequest($req); @@ -36,6 +40,18 @@ class InvoiceController extends ApiController return new ApiResponse(false, 'No customer information found.'); } + // get customer location from customer_metadata using customer id + $lng = $req->request->get('longitude'); + $lat = $req->request->get('latitude'); + + if ((empty($lng)) || (empty($lat))) + { + // use customer metadata location as basis + $coordinates = $this->getCustomerMetadata($cust); + } + else + $coordinates = new Point($lng, $lat); + // make invoice criteria $icrit = new InvoiceCriteria(); $icrit->setServiceType($req->request->get('service_type')); @@ -113,6 +129,18 @@ class InvoiceController extends ApiController // set JO source $icrit->setSource(TransactionOrigin::MOBILE_APP); + // set price tier + $pt_id = 0; + if ($coordinates != null) + { + error_log('coordinates are not null'); + $pt_id = $pt_manager->getPriceTier($coordinates); + } + else + error_log('null?'); + + $icrit->setPriceTier($pt_id); + // send to invoice generator $invoice = $ic->generateInvoice($icrit); @@ -148,4 +176,28 @@ class InvoiceController extends ApiController // response return new ApiResponse(true, '', $data); } + + protected function getCustomerMetadata(Customer $cust) + { + $coordinates = null; + + // check if customer already has existing metadata + $c_meta = $this->em->getRepository(CustomerMetadata::class)->findOneBy(['customer' => $cust]); + if ($c_meta != null) + { + $meta_data = $c_meta->getAllMetaInfo(); + foreach ($meta_data as $m_info) + { + if ((isset($m_info['longitude'])) && (isset($m_info['latitude']))) + { + $lng = $m_info['longitude']; + $lat = $m_info['latitude']; + + $coordinates = new Point($lng, $lat); + } + } + } + + return $coordinates; + } } diff --git a/src/Controller/CustomerAppAPI/JobOrderController.php b/src/Controller/CustomerAppAPI/JobOrderController.php index 143f2a2e..fa5a9a85 100644 --- a/src/Controller/CustomerAppAPI/JobOrderController.php +++ b/src/Controller/CustomerAppAPI/JobOrderController.php @@ -21,6 +21,7 @@ use App\Service\HubDistributor; use App\Service\HubFilterLogger; use App\Service\HubFilteringGeoChecker; use App\Service\JobOrderManager; +use App\Service\PriceTierManager; use App\Ramcar\ServiceType; use App\Ramcar\APIRiderStatus; use App\Ramcar\InvoiceCriteria; @@ -484,7 +485,8 @@ class JobOrderController extends ApiController HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger, HubFilteringGeoChecker $hub_geofence, - JobOrderManager $jo_manager + JobOrderManager $jo_manager, + PriceTierManager $pt_manager ) { // validate params $validity = $this->validateRequest($req, [ @@ -698,6 +700,10 @@ class JobOrderController extends ApiController // set JO source $icrit->setSource(TransactionOrigin::MOBILE_APP); + // set price tier + $pt_id = $pt_manager->getPriceTier($jo->getCoordinates()); + $icrit->setPriceTier($pt_id); + // send to invoice generator $invoice = $ic->generateInvoice($icrit); $jo->setInvoice($invoice); @@ -970,7 +976,8 @@ class JobOrderController extends ApiController HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger, HubFilteringGeoChecker $hub_geofence, - JobOrderManager $jo_manager + JobOrderManager $jo_manager, + PriceTierManager $pt_manager ) { // validate params $validity = $this->validateRequest($req, [ @@ -1127,6 +1134,10 @@ class JobOrderController extends ApiController // set JO source $icrit->setSource(TransactionOrigin::MOBILE_APP); + // set price tier + $pt_id = $pt_manager->getPriceTier($jo->getCoordinates()); + $icrit->setPriceTier($pt_id); + // send to invoice generator $invoice = $ic->generateInvoice($icrit); $jo->setInvoice($invoice); diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 91921a0f..17c62a45 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -30,6 +30,7 @@ use App\Service\HubSelector; use App\Service\RiderTracker; use App\Service\MotivConnector; +use App\Service\PriceTierManager; use App\Service\GeofenceTracker; use Symfony\Component\HttpFoundation\Request; @@ -42,6 +43,8 @@ use Doctrine\ORM\EntityManagerInterface; use Catalyst\MenuBundle\Annotation\Menu; +use CrEOF\Spatial\PHP\Types\Geometry\Point; + class JobOrderController extends Controller { public function getJobOrders(Request $req, JobOrderHandlerInterface $jo_handler) @@ -741,7 +744,7 @@ class JobOrderController extends Controller } - public function generateInvoice(Request $req, InvoiceGeneratorInterface $ic) + public function generateInvoice(Request $req, InvoiceGeneratorInterface $ic, PriceTierManager $pt_manager) { // error_log('generating invoice...'); $error = false; @@ -752,6 +755,19 @@ class JobOrderController extends Controller $cvid = $req->request->get('cvid'); $service_charges = $req->request->get('service_charges', []); + // coordinates + // need to check if lng and lat are set + $lng = $req->request->get('coord_lng', 0); + $lat = $req->request->get('coord_lat', 0); + + $price_tier = 0; + if (($lng != 0) && ($lat != 0)) + { + $coordinates = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat')); + $price_tier = $pt_manager->getPriceTier($coordinates); + } + + $em = $this->getDoctrine()->getManager(); // get customer vehicle @@ -767,8 +783,8 @@ class JobOrderController extends Controller $criteria->setServiceType($stype) ->setCustomerVehicle($cv) ->setIsTaxable() - ->setSource(TransactionOrigin::CALL); - + ->setSource(TransactionOrigin::CALL) + ->setPriceTier($price_tier); /* // if it's a jumpstart or troubleshoot only, we know what to charge already diff --git a/src/Controller/TAPI/JobOrderController.php b/src/Controller/TAPI/JobOrderController.php index f7541b50..ae4d5a61 100644 --- a/src/Controller/TAPI/JobOrderController.php +++ b/src/Controller/TAPI/JobOrderController.php @@ -46,6 +46,7 @@ use App\Service\RiderTracker; use App\Service\PromoLogger; use App\Service\MapTools; use App\Service\JobOrderManager; +use App\Service\PriceTierManager; use App\Entity\JobOrder; use App\Entity\CustomerVehicle; @@ -79,7 +80,8 @@ class JobOrderController extends ApiController FCMSender $fcmclient, RiderAssignmentHandlerInterface $rah, PromoLogger $promo_logger, HubSelector $hub_select, HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger, - HubFilteringGeoChecker $hub_geofence, EntityManagerInterface $em, JobOrderManager $jo_manager) + HubFilteringGeoChecker $hub_geofence, EntityManagerInterface $em, JobOrderManager $jo_manager, + PriceTierManager $pt_manager) { $this->denyAccessUnlessGranted('tapi_jo.request', null, 'No access.'); @@ -165,7 +167,17 @@ class JobOrderController extends ApiController // set JO source $icrit->setSource(TransactionOrigin::THIRD_PARTY); - $icrit->addEntry($data['batt'], $data['trade_in_type'], 1); + // set price tier + $pt_id = $pt_manager->getPriceTier($jo->getCoordinates()); + $icrit->setPriceTier($pt_id); + + // add the actual battery item first + $icrit->addEntry($data['batt'], null, 1); + + // if we have a trade in, add it as well, assuming trade in battery == battery purchased + if (!empty($data['trade_in_type'])) { + $icrit->addEntry($data['batt'], $data['trade_in_type'], 1); + } // send to invoice generator $invoice = $ic->generateInvoice($icrit); diff --git a/src/InvoiceRule/BatteryReplacementWarranty.php b/src/InvoiceRule/BatteryReplacementWarranty.php index ee1497b5..46ba5e8a 100644 --- a/src/InvoiceRule/BatteryReplacementWarranty.php +++ b/src/InvoiceRule/BatteryReplacementWarranty.php @@ -11,14 +11,19 @@ use App\Ramcar\TradeInType; use App\Entity\Battery; use App\Entity\ServiceOffering; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class BatteryReplacementWarranty implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -29,6 +34,7 @@ class BatteryReplacementWarranty implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $pt_id = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) @@ -40,7 +46,14 @@ class BatteryReplacementWarranty implements InvoiceRuleInterface { $batt = $entry['battery']; $qty = 1; - $price = $this->getServiceTypeFee(); + + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id); + + if ($pt_price == null) + $price = $this->getServiceTypeFee(); + else + $price = $pt_price; $items[] = [ 'service_type' => $this->getID(), @@ -117,6 +130,34 @@ class BatteryReplacementWarranty implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + $code = 'battery_replacement_warranty_fee'; + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + + protected function getTitle($battery) { $title = $battery->getModel()->getName() . ' ' . $battery->getSize()->getName() . ' - Service Unit'; diff --git a/src/InvoiceRule/BatterySales.php b/src/InvoiceRule/BatterySales.php index 45b060d1..645e545b 100644 --- a/src/InvoiceRule/BatterySales.php +++ b/src/InvoiceRule/BatterySales.php @@ -10,14 +10,19 @@ use App\Ramcar\TradeInType; use App\Ramcar\ServiceType; use App\Entity\Battery; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class BatterySales implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -28,6 +33,7 @@ class BatterySales implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $pt = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) @@ -47,8 +53,13 @@ class BatterySales implements InvoiceRuleInterface if ($trade_in == null) { - // battery purchase - $price = $batt->getSellingPrice(); + // check if price tier has item price for battery + $pt_price = $this->getPriceTierItemPrice($pt, $batt); + + if ($pt_price == null) + $price = $batt->getSellingPrice(); + else + $price = $pt_price; $items[] = [ 'service_type' => $this->getID(), @@ -114,6 +125,25 @@ class BatterySales implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id, $batt) + { + // price tier is default + if ($pt_id == 0) + return null; + + // find the item type battery + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'battery']); + if ($item_type == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $batt->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getTitle($battery) { $title = $battery->getModel()->getName() . ' ' . $battery->getSize()->getName(); diff --git a/src/InvoiceRule/Fuel.php b/src/InvoiceRule/Fuel.php index f843e1c0..e4f365b9 100644 --- a/src/InvoiceRule/Fuel.php +++ b/src/InvoiceRule/Fuel.php @@ -11,14 +11,19 @@ use App\Ramcar\ServiceType; use App\Entity\ServiceOffering; use App\Entity\CustomerVehicle; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class Fuel implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -29,6 +34,7 @@ class Fuel implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $pt_id = $criteria->getPriceTier(); $items = []; @@ -36,7 +42,13 @@ class Fuel implements InvoiceRuleInterface { $cv = $criteria->getCustomerVehicle(); - $fee = $this->getServiceTypeFee($cv); + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id, $cv); + + if ($pt_price == null) + $service_price = $this->getServiceTypeFee($cv); + else + $service_price = $pt_price; $ftype = $cv->getFuelType(); @@ -46,10 +58,10 @@ class Fuel implements InvoiceRuleInterface 'service_type' => $this->getID(), 'qty' => $qty, 'title' => $this->getServiceTitle($ftype), - 'price' => $fee, + 'price' => $service_price, ]; - $qty_fee = bcmul($qty, $fee, 2); + $qty_fee = bcmul($qty, $service_price, 2); $total_price = $qty_fee; switch ($ftype) @@ -57,7 +69,15 @@ class Fuel implements InvoiceRuleInterface case FuelType::GAS: case FuelType::DIESEL: $qty = 1; - $price = $this->getFuelFee($ftype); + + // check if price tier has item price for fuel type + $pt_price = $this->getPriceTierFuelItemPrice($pt_id, $ftype); + + if ($pt_price == null) + $price = $this->getFuelFee($ftype); + else + $price = $pt_price; + $items[] = [ 'service_type' => $this->getID(), 'qty' => $qty, @@ -138,6 +158,70 @@ class Fuel implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id, CustomerVehicle $cv) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + // check if customer vehicle has a motolite battery + // if yes, set the code to the motolite user service fee + if ($cv->hasMotoliteBattery()) + $code = 'motolite_user_service_fee'; + else + $code = 'fuel_service_fee'; + + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + + protected function getPriceTierFuelItemPrice($pt_id, $fuel_type) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + $code = ''; + if ($fuel_type == FuelType::GAS) + $code = 'fuel_gas_fee'; + if ($fuel_type == FuelType::DIESEL) + $code = 'fuel_diesel_fee'; + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getTitle($fuel_type) { $title = '4L - ' . ucfirst($fuel_type); diff --git a/src/InvoiceRule/Jumpstart.php b/src/InvoiceRule/Jumpstart.php index dce41d99..d2e89b0a 100644 --- a/src/InvoiceRule/Jumpstart.php +++ b/src/InvoiceRule/Jumpstart.php @@ -8,16 +8,21 @@ use App\InvoiceRuleInterface; use App\Entity\ServiceOffering; use App\Entity\CustomerVehicle; +use App\Entity\ItemType; use App\Ramcar\TransactionOrigin; +use App\Service\PriceTierManager; + class Jumpstart implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -29,13 +34,21 @@ class Jumpstart implements InvoiceRuleInterface { $stype = $criteria->getServiceType(); $source = $criteria->getSource(); + $pt_id = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) { $cv = $criteria->getCustomerVehicle(); - $fee = $this->getServiceTypeFee($source, $cv); + + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id, $source, $cv); + + if ($pt_price == null) + $price = $this->getServiceTypeFee($source, $cv); + else + $price = $pt_price; // add the service fee to items $qty = 1; @@ -43,10 +56,10 @@ class Jumpstart implements InvoiceRuleInterface 'service_type' => $this->getID(), 'qty' => $qty, 'title' => $this->getServiceTitle(), - 'price' => $fee, + 'price' => $price, ]; - $qty_price = bcmul($fee, $qty, 2); + $qty_price = bcmul($price, $qty, 2); $total['total_price'] = bcadd($total['total_price'], $qty_price, 2); } @@ -86,6 +99,45 @@ class Jumpstart implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id, $source, $cv) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + // check the source of JO + // (1) if from app, service fee is 0 if motolite user. jumpstart fee for app if non-motolite user. + // (2) any other source, jumpstart fees are charged whether motolite user or not + if ($source == TransactionOrigin::MOBILE_APP) + { + if ($cv->hasMotoliteBattery()) + $code = 'motolite_user_service_fee'; + else + $code = 'jumpstart_fee_mobile_app'; + } + else + $code = 'jumpstart_fee'; + + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getServiceTitle() { $title = 'Service - Troubleshooting fee'; diff --git a/src/InvoiceRule/JumpstartWarranty.php b/src/InvoiceRule/JumpstartWarranty.php index 9423da44..4c6ac387 100644 --- a/src/InvoiceRule/JumpstartWarranty.php +++ b/src/InvoiceRule/JumpstartWarranty.php @@ -7,14 +7,19 @@ use Doctrine\ORM\EntityManagerInterface; use App\InvoiceRuleInterface; use App\Entity\ServiceOffering; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class JumpstartWarranty implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -25,12 +30,19 @@ class JumpstartWarranty implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $pt_id = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) { - $fee = $this->getServiceTypeFee(); + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id); + + if ($pt_price == null) + $price = $this->getServiceTypeFee(); + else + $price = $pt_price; // add the service fee to items $qty = 1; @@ -38,10 +50,10 @@ class JumpstartWarranty implements InvoiceRuleInterface 'service_type' => $this->getID(), 'qty' => $qty, 'title' => $this->getServiceTitle(), - 'price' => $fee, + 'price' => $price, ]; - $qty_price = bcmul($fee, $qty, 2); + $qty_price = bcmul($price, $qty, 2); $total['total_price'] = bcadd($total['total_price'], $qty_price, 2); } @@ -72,6 +84,33 @@ class JumpstartWarranty implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + $code = 'jumpstart_warranty_fee'; + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getServiceTitle() { $title = 'Service - Troubleshooting fee'; diff --git a/src/InvoiceRule/Overheat.php b/src/InvoiceRule/Overheat.php index 4c06bddb..af0ce182 100644 --- a/src/InvoiceRule/Overheat.php +++ b/src/InvoiceRule/Overheat.php @@ -10,14 +10,19 @@ use App\Ramcar\ServiceType; use App\Entity\ServiceOffering; use App\Entity\CustomerVehicle; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class Overheat implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -29,13 +34,22 @@ class Overheat implements InvoiceRuleInterface { $stype = $criteria->getServiceType(); $has_coolant = $criteria->hasCoolant(); + $pt_id = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) { $cv = $criteria->getCustomerVehicle(); - $fee = $this->getServiceTypeFee($cv); + + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id, $cv); + + if ($pt_price == null) + $price = $this->getServiceTypeFee($cv); + else + + $price = $pt_price; // add the service fee to items $qty = 1; @@ -43,10 +57,10 @@ class Overheat implements InvoiceRuleInterface 'service_type' => $this->getID(), 'qty' => $qty, 'title' => $this->getServiceTitle(), - 'price' => $fee, + 'price' => $price, ]; - $qty_fee = bcmul($qty, $fee, 2); + $qty_fee = bcmul($qty, $price, 2); $total_price = $qty_fee; if ($has_coolant) @@ -112,6 +126,39 @@ class Overheat implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id, CustomerVehicle $cv) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + $code = 'overheat_fee'; + + // check if customer vehicle has a motolite battery + // if yes, set the code to the motolite user service fee + if ($cv->hasMotoliteBattery()) + $code = 'motolite_user_service_fee'; + + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getServiceTitle() { $title = 'Service - ' . ServiceType::getName(ServiceType::OVERHEAT_ASSISTANCE); diff --git a/src/InvoiceRule/PostRecharged.php b/src/InvoiceRule/PostRecharged.php index 808f2340..b0b20995 100644 --- a/src/InvoiceRule/PostRecharged.php +++ b/src/InvoiceRule/PostRecharged.php @@ -7,14 +7,19 @@ use Doctrine\ORM\EntityManagerInterface; use App\InvoiceRuleInterface; use App\Entity\ServiceOffering; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class PostRecharged implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -25,22 +30,29 @@ class PostRecharged implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $pt_id = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) { - $fee = $this->getServiceTypeFee(); + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id); + + if ($pt_price == null) + $price = $this->getServiceTypeFee(); + else + $price = $pt_price; $qty = 1; $items[] = [ 'service_type' => $this->getID(), 'qty' => $qty, 'title' => $this->getServiceTitle(), - 'price' => $fee, + 'price' => $price, ]; - $qty_price = bcmul($fee, $qty, 2); + $qty_price = bcmul($price, $qty, 2); $total['total_price'] = bcadd($total['total_price'], $qty_price, 2); } @@ -72,6 +84,33 @@ class PostRecharged implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + $code = 'post_recharged_fee'; + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getServiceTitle() { $title = 'Recharge fee'; diff --git a/src/InvoiceRule/PostReplacement.php b/src/InvoiceRule/PostReplacement.php index aba6d9aa..774b61de 100644 --- a/src/InvoiceRule/PostReplacement.php +++ b/src/InvoiceRule/PostReplacement.php @@ -7,14 +7,19 @@ use Doctrine\ORM\EntityManagerInterface; use App\InvoiceRuleInterface; use App\Entity\ServiceOffering; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class PostReplacement implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -25,22 +30,29 @@ class PostReplacement implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $pt_id = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) { - $fee = $this->getServiceTypeFee(); + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id); + + if ($pt_price == null) + $price = $this->getServiceTypeFee(); + else + $price = $pt_price; $qty = 1; $items[] = [ 'service_type' => $this->getID(), 'qty' => $qty, 'title' => $this->getServiceTitle(), - 'price' => $fee, + 'price' => $price, ]; - $qty_price = bcmul($fee, $qty, 2); + $qty_price = bcmul($price, $qty, 2); $total['total_price'] = bcadd($total['total_price'], $qty_price, 2); } @@ -71,6 +83,33 @@ class PostReplacement implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + $code = 'post_replacement_fee'; + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getServiceTitle() { $title = 'Battery replacement'; diff --git a/src/InvoiceRule/Tax.php b/src/InvoiceRule/Tax.php index b1e6a600..50834e44 100644 --- a/src/InvoiceRule/Tax.php +++ b/src/InvoiceRule/Tax.php @@ -9,14 +9,19 @@ use App\InvoiceRuleInterface; use App\Ramcar\ServiceType; use App\Entity\ServiceOffering; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class Tax implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -40,6 +45,7 @@ class Tax implements InvoiceRuleInterface // compute tax per item if service type is battery sales $stype = $criteria->getServiceType(); + $pt = $criteria->getPriceTier(); if ($stype == ServiceType::BATTERY_REPLACEMENT_NEW) { @@ -58,7 +64,13 @@ class Tax implements InvoiceRuleInterface $battery = $entry['battery']; $qty = $entry['qty']; - $price = $battery->getSellingPrice(); + // check if price tier has item price for battery + $pt_price = $this->getPriceTierItemPrice($pt, $battery); + + if ($pt_price == null) + $price = $battery->getSellingPrice(); + else + $price = $pt_price; $vat = $this->getTaxAmount($price, $tax_rate); @@ -96,6 +108,25 @@ class Tax implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id, $batt) + { + // price tier is default + if ($pt_id == 0) + return null; + + // find the item type battery + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'battery']); + if ($item_type == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $batt->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getTaxAmount($price, $tax_rate) { $vat_ex_price = $this->getTaxExclusivePrice($price, $tax_rate); diff --git a/src/InvoiceRule/TireRepair.php b/src/InvoiceRule/TireRepair.php index 755c11bd..96d3c525 100644 --- a/src/InvoiceRule/TireRepair.php +++ b/src/InvoiceRule/TireRepair.php @@ -8,14 +8,19 @@ use App\InvoiceRuleInterface; use App\Entity\ServiceOffering; use App\Entity\CustomerVehicle; +use App\Entity\ItemType; + +use App\Service\PriceTierManager; class TireRepair implements InvoiceRuleInterface { protected $em; + protected $pt_manager; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, PriceTierManager $pt_manager) { $this->em = $em; + $this->pt_manager = $pt_manager; } public function getID() @@ -26,13 +31,21 @@ class TireRepair implements InvoiceRuleInterface public function compute($criteria, &$total) { $stype = $criteria->getServiceType(); + $pt_id = $criteria->getPriceTier(); $items = []; if ($stype == $this->getID()) { $cv = $criteria->getCustomerVehicle(); - $fee = $this->getServiceTypeFee($cv); + + // check if price tier has item price + $pt_price = $this->getPriceTierItemPrice($pt_id, $cv); + + if ($pt_price == null) + $price = $this->getServiceTypeFee($cv); + else + $price = $pt_price; // add the service fee to items $qty = 1; @@ -40,10 +53,10 @@ class TireRepair implements InvoiceRuleInterface 'service_type' => $this->getID(), 'qty' => $qty, 'title' => $this->getServiceTitle(), - 'price' => $fee, + 'price' => $price, ]; - $qty_price = bcmul($fee, $qty, 2); + $qty_price = bcmul($price, $qty, 2); $total['total_price'] = bcadd($total['total_price'], $qty_price, 2); } @@ -79,6 +92,39 @@ class TireRepair implements InvoiceRuleInterface return null; } + protected function getPriceTierItemPrice($pt_id, CustomerVehicle $cv) + { + // price_tier is default + if ($pt_id == 0) + return null; + + // find the item type for service offering + $item_type = $this->em->getRepository(ItemType::class)->findOneBy(['code' => 'service_offering']); + if ($item_type == null) + return null; + + // find the service offering + $code = 'tire_repair_fee'; + + // check if customer vehicle has a motolite battery + // if yes, set the code to the motolite user service fee + if ($cv->hasMotoliteBattery()) + $code = 'motolite_user_service_fee'; + + $service = $this->em->getRepository(ServiceOffering::class)->findOneBy(['code' => $code]); + + // check if service is null. If null, return null + if ($service == null) + return null; + + $item_type_id = $item_type->getID(); + $item_id = $service->getID(); + + $price = $this->pt_manager->getItemPrice($pt_id, $item_type_id, $item_id); + + return $price; + } + protected function getServiceTitle() { $title = 'Service - Flat Tire'; diff --git a/src/Ramcar/InvoiceCriteria.php b/src/Ramcar/InvoiceCriteria.php index b27395da..18ebd82a 100644 --- a/src/Ramcar/InvoiceCriteria.php +++ b/src/Ramcar/InvoiceCriteria.php @@ -17,6 +17,7 @@ class InvoiceCriteria protected $service_charges; protected $flag_taxable; protected $source; // use Ramcar's TransactionOrigin + protected $price_tier; // entries are battery and trade-in combos protected $entries; @@ -32,6 +33,7 @@ class InvoiceCriteria $this->service_charges = []; $this->flag_taxable = false; $this->source = ''; + $this->price_tier = 0; // set to default } public function setServiceType($stype) @@ -179,4 +181,14 @@ class InvoiceCriteria return $this->source; } + public function setPriceTier($price_tier) + { + $this->price_tier = $price_tier; + return $this; + } + + public function getPriceTier() + { + return $this->price_tier; + } } diff --git a/src/Ramcar/TransactionOrigin.php b/src/Ramcar/TransactionOrigin.php index a204b35f..7f459e96 100644 --- a/src/Ramcar/TransactionOrigin.php +++ b/src/Ramcar/TransactionOrigin.php @@ -17,13 +17,17 @@ class TransactionOrigin extends NameValue const YOKOHAMA_TWITTER = 'yokohama_twitter'; const YOKOHAMA_INSTAGRAM = 'yokohama_instagram'; const YOKOHAMA_CAROUSELL = 'yokohama_carousell'; + const HOTLINE_CEBU = 'hotline_cebu'; + const FACEBOOK_CEBU = 'facebook_cebu'; // TODO: for now, resq also gets the walk-in option // resq also gets new YOKOHAMA options const COLLECTION = [ - 'call' => 'Hotline', + 'call' => 'Hotline Manila', + 'hotline_cebu' => 'Hotline Cebu', 'online' => 'Online', - 'facebook' => 'Facebook', + 'facebook' => 'Facebook Manila', + 'facebook_cebu' => 'Facebook Cebu', 'vip' => 'VIP', 'mobile_app' => 'Mobile App', 'walk_in' => 'Walk-in', @@ -33,6 +37,6 @@ class TransactionOrigin extends NameValue 'yokohama_op_facebook' => 'Yokohama OP Facebook', 'yokohama_twitter' => 'Yokohama Twitter', 'yokohama_instagram' => 'Yokohama Instagram', - 'yokohama_carousell' => 'Yokohama Carousell', + 'yokohama_carousell' => 'Yokohama Carousell' ]; } diff --git a/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php b/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php index 5dc86f8d..c1f40509 100644 --- a/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/CMBInvoiceGenerator.php @@ -134,7 +134,7 @@ class CMBInvoiceGenerator implements InvoiceGeneratorInterface } // generate invoice criteria - public function generateInvoiceCriteria($jo, $discount, $invoice_items, $source = null, &$error_array) + public function generateInvoiceCriteria($jo, $discount, $invoice_items, $price_tier = null, $source = null, &$error_array) { $em = $this->em; diff --git a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php index 3809133b..efe0a9de 100644 --- a/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php +++ b/src/Service/InvoiceGenerator/ResqInvoiceGenerator.php @@ -144,7 +144,7 @@ class ResqInvoiceGenerator implements InvoiceGeneratorInterface } // generate invoice criteria - public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source = null, &$error_array) + public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, $price_tier = null, $source = null, &$error_array) { $em = $this->em; diff --git a/src/Service/InvoiceGeneratorInterface.php b/src/Service/InvoiceGeneratorInterface.php index e2cb2cc3..4c46c38f 100644 --- a/src/Service/InvoiceGeneratorInterface.php +++ b/src/Service/InvoiceGeneratorInterface.php @@ -4,6 +4,7 @@ namespace App\Service; use App\Entity\Invoice; use App\Entity\JobOrder; +use App\Entity\PriceTier; use App\Ramcar\InvoiceCriteria; @@ -13,7 +14,7 @@ interface InvoiceGeneratorInterface public function generateInvoice(InvoiceCriteria $criteria); // generate invoice criteria - public function generateInvoiceCriteria(JobOrder $jo, int $promo_id, array $invoice_items, $source, array &$error_array); + public function generateInvoiceCriteria(JobOrder $jo, int $promo_id, array $invoice_items, $source, PriceTier $price_tier, array &$error_array); // prepare draft for invoice public function generateDraftInvoice(InvoiceCriteria $criteria, int $promo_id, array $service_charges, array $items); diff --git a/src/Service/InvoiceManager.php b/src/Service/InvoiceManager.php index 65fc3a43..8f655224 100644 --- a/src/Service/InvoiceManager.php +++ b/src/Service/InvoiceManager.php @@ -10,6 +10,7 @@ use Doctrine\ORM\EntityManagerInterface; use App\InvoiceRule; use App\Service\InvoiceGeneratorInterface; +use App\Service\PriceTierManager; use App\Ramcar\InvoiceCriteria; use App\Ramcar\InvoiceStatus; @@ -28,12 +29,14 @@ class InvoiceManager implements InvoiceGeneratorInterface protected $em; protected $validator; protected $available_rules; + protected $pt_manager; - public function __construct(EntityManagerInterface $em, Security $security, ValidatorInterface $validator) + public function __construct(EntityManagerInterface $em, Security $security, ValidatorInterface $validator, PriceTierManager $pt_manager) { $this->em = $em; $this->security = $security; $this->validator = $validator; + $this->pt_manager = $pt_manager; $this->available_rules = $this->getAvailableRules(); } @@ -42,28 +45,29 @@ class InvoiceManager implements InvoiceGeneratorInterface { // TODO: get list of invoice rules from .env or a json file? return [ - new InvoiceRule\BatterySales($this->em), - new InvoiceRule\BatteryReplacementWarranty($this->em), - new InvoiceRule\Jumpstart($this->em), - new InvoiceRule\JumpstartWarranty($this->em), - new InvoiceRule\PostRecharged($this->em), - new InvoiceRule\PostReplacement($this->em), - new InvoiceRule\Overheat($this->em), - new InvoiceRule\Fuel($this->em), - new InvoiceRule\TireRepair($this->em), + new InvoiceRule\BatterySales($this->em, $this->pt_manager), + new InvoiceRule\BatteryReplacementWarranty($this->em, $this->pt_manager), + new InvoiceRule\Jumpstart($this->em, $this->pt_manager), + new InvoiceRule\JumpstartWarranty($this->em, $this->pt_manager), + new InvoiceRule\PostRecharged($this->em, $this->pt_manager), + new InvoiceRule\PostReplacement($this->em, $this->pt_manager), + new InvoiceRule\Overheat($this->em, $this->pt_manager), + new InvoiceRule\Fuel($this->em, $this->pt_manager), + new InvoiceRule\TireRepair($this->em, $this->pt_manager), new InvoiceRule\DiscountType($this->em), new InvoiceRule\TradeIn(), - new InvoiceRule\Tax($this->em), + new InvoiceRule\Tax($this->em, $this->pt_manager), ]; } // this is called when JO is submitted - public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, &$error_array) + public function generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, $price_tier, &$error_array) { // instantiate the invoice criteria $criteria = new InvoiceCriteria(); $criteria->setServiceType($jo->getServiceType()) - ->setCustomerVehicle($jo->getCustomerVehicle()); + ->setCustomerVehicle($jo->getCustomerVehicle()) + ->setPriceTier($price_tier); // set if taxable // NOTE: ideally, this should be a parameter when calling generateInvoiceCriteria. But that diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index 361c0b22..71f91357 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -69,6 +69,7 @@ use App\Service\HubSelector; use App\Service\HubDistributor; use App\Service\HubFilteringGeoChecker; use App\Service\JobOrderManager; +use App\Service\PriceTierManager; use CrEOF\Spatial\PHP\Types\Geometry\Point; @@ -96,6 +97,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface protected $cust_distance_limit; protected $hub_filter_enable; protected $jo_manager; + protected $pt_manager; protected $template_hash; @@ -104,7 +106,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah, string $country_code, WarrantyHandler $wh, RisingTideGateway $rt, PromoLogger $promo_logger, HubDistributor $hub_dist, HubFilteringGeoChecker $hub_geofence, - string $cust_distance_limit, string $hub_filter_enabled, JobOrderManager $jo_manager) + string $cust_distance_limit, string $hub_filter_enabled, JobOrderManager $jo_manager, PriceTierManager $pt_manager) { $this->em = $em; $this->ic = $ic; @@ -121,6 +123,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $this->cust_distance_limit = $cust_distance_limit; $this->hub_filter_enabled = $hub_filter_enabled; $this->jo_manager = $jo_manager; + $this->pt_manager = $pt_manager; $this->loadTemplates(); } @@ -585,7 +588,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface { $source = $jo->getSource(); - $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, $error_array); + // get the price tier according to location. + $price_tier = $this->pt_manager->getPriceTier($jo->getCoordinates()); + $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, $price_tier, $error_array); } // validate @@ -817,7 +822,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface { $source = $obj->getSource(); - $this->ic->generateInvoiceCriteria($obj, $promo_id, $invoice_items, $source, $error_array); + // get the price tier according to location. + $price_tier = $this->pt_manager->getPriceTier($obj->getCoordinates()); + $this->ic->generateInvoiceCriteria($obj, $promo_id, $invoice_items, $source, $price_tier, $error_array); } // validate @@ -2165,7 +2172,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface // NOTE: this is CMB code but for compilation purposes we need to add this $source = $jo->getSource(); - $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, $error_array); + // get the price tier according to location. + $price_tier = $this->pt_manager->getPriceTier($jo->getCoordinates()); + $this->ic->generateInvoiceCriteria($jo, $promo_id, $invoice_items, $source, $price_tier, $error_array); } // validate @@ -2910,6 +2919,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $params['status_cancelled'] = JOStatus::CANCELLED; $params['hubs'] = []; + $branch_codes = []; // format duration and distance into friendly time foreach ($hubs as $hub) { // duration @@ -4252,6 +4262,10 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface if ($rejection->getReason() == JORejectionReason::ADMINISTRATIVE) return null; + // check if reason is discount + if ($rejection->getReason() == JORejectionReason::DISCOUNT) + return null; + // sms content // Job Order # - can get from jo // Order Date and Time - get from jo diff --git a/src/Service/PriceTierManager.php b/src/Service/PriceTierManager.php new file mode 100644 index 00000000..62d657f4 --- /dev/null +++ b/src/Service/PriceTierManager.php @@ -0,0 +1,80 @@ +em = $em; + } + + public function getItemPrice($pt_id, $item_type_id, $item_id) + { + // find the item price, given the price tier, battery id, and item type (battery) + $db_conn = $this->em->getConnection(); + + $ip_sql = 'SELECT ip.price AS price + FROM item_price ip + WHERE ip.price_tier_id = :pt_id + AND ip.item_type_id = :it_id + AND ip.item_id = :item_id'; + + $ip_stmt = $db_conn->prepare($ip_sql); + $ip_stmt->bindValue('pt_id', $pt_id); + $ip_stmt->bindValue('it_id', $item_type_id); + $ip_stmt->bindValue('item_id', $item_id); + + $ip_result = $ip_stmt->executeQuery(); + + // results found + $actual_price = null; + + // go through rows + while ($row = $ip_result->fetchAssociative()) + { + // get the price + $price = $row['price']; + + // actual price + $actual_price = number_format($price / 100, 2, '.', ''); + } + + return $actual_price; + } + + public function getPriceTier(Point $coordinates) + { + $price_tier_id = 0; + + if ($coordinates != null) + { + $long = $coordinates->getLongitude(); + $lat = $coordinates->getLatitude(); + + // get location's price tier, given a set of coordinates + $query = $this->em->createQuery('SELECT s from App\Entity\SupportedArea s where st_contains(s.coverage_area, point(:long, :lat)) = true'); + $area = $query->setParameter('long', $long) + ->setParameter('lat', $lat) + ->setMaxResults(1) + ->getOneOrNullResult(); + + if ($area != null) + { + $price_tier = $area->getPriceTier(); + if ($price_tier != null) + $price_tier_id = $price_tier->getID(); + } + } + + return $price_tier_id; + } +} diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index ca68e922..edbd97a0 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -1231,6 +1231,8 @@ $(function() { function selectPoint(lat, lng) { // check if point is in coverage area + // commenting out the geofence call for CRM + /* $.ajax({ method: "GET", url: "{{ url('jo_geofence') }}", @@ -1248,7 +1250,7 @@ $(function() { type: 'warning', }); } - }); + }); */ // clear markers markerLayerGroup.clearLayers(); @@ -1761,6 +1763,8 @@ $(function() { var table = $("#invoice-table tbody"); var stype = $("#service_type").val(); var cvid = $("#customer-vehicle").val(); + var lng = $("#map_lng").val(); + var lat = $("#map_lat").val(); console.log(JSON.stringify(invoiceItems)); @@ -1772,7 +1776,9 @@ $(function() { 'stype': stype, 'items': invoiceItems, 'promo': promo, - 'cvid': cvid + 'cvid': cvid, + 'coord_lng': lng, + 'coord_lat': lat, } }).done(function(response) { // mark as invoice changed diff --git a/templates/job-order/form.view.html.twig b/templates/job-order/form.view.html.twig index cc463f11..33d6fc5b 100644 --- a/templates/job-order/form.view.html.twig +++ b/templates/job-order/form.view.html.twig @@ -635,6 +635,8 @@ $(function() { function selectPoint(lat, lng) { // check if point is in coverage area + // commenting out the geofence call for CRM + /* $.ajax({ method: "GET", url: "{{ url('jo_geofence') }}", @@ -652,7 +654,7 @@ $(function() { type: 'warning', }); } - }); + }); */ // clear markers markerLayerGroup.clearLayers(); diff --git a/utils/item_types/item_types.sql b/utils/item_types/item_types.sql new file mode 100644 index 00000000..7c5aeeba --- /dev/null +++ b/utils/item_types/item_types.sql @@ -0,0 +1,53 @@ +-- MySQL dump 10.19 Distrib 10.3.39-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: resq +-- ------------------------------------------------------ +-- Server version 10.3.39-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `item_type` +-- + +DROP TABLE IF EXISTS `item_type`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `item_type` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(80) NOT NULL, + `code` varchar(80) NOT NULL, + PRIMARY KEY (`id`), + KEY `item_type_idx` (`code`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `item_type` +-- + +LOCK TABLES `item_type` WRITE; +/*!40000 ALTER TABLE `item_type` DISABLE KEYS */; +INSERT INTO `item_type` VALUES (1,'Battery','battery'),(2,'Service Offering','service_offering'); +/*!40000 ALTER TABLE `item_type` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2024-01-28 20:59:44