Merge branch '575-adopt-hub-filtering-branch' into 'master-fix'
Resolve "Adopt hub filtering branch" See merge request jankstudio/resq!689
This commit is contained in:
commit
3d8298a674
21 changed files with 1564 additions and 95 deletions
|
|
@ -81,6 +81,8 @@ API_VERSION=insert_api_version_here
|
|||
#SSL_ENABLE for websockets
|
||||
SSL_ENABLE=set_to_true_or_false
|
||||
|
||||
# db
|
||||
DB_USER=db_username
|
||||
DB_PASSWORD=db_password
|
||||
# for hub filtering round robin
|
||||
HUB_JO_KEY=hub_jo_count
|
||||
|
||||
# hub geofence
|
||||
HUB_GEOFENCE_ENABLE=set_to_true_or_false
|
||||
|
|
|
|||
|
|
@ -275,3 +275,27 @@ services:
|
|||
App\Service\PromoLogger:
|
||||
arguments:
|
||||
$em: "@doctrine.orm.entity_manager"
|
||||
|
||||
# hub service
|
||||
App\Service\HubSelector:
|
||||
arguments:
|
||||
$em: "@doctrine.orm.entity_manager"
|
||||
$im: "@App\\Service\\InventoryManager"
|
||||
$hub_distributor: "@App\\Service\\HubDistributor"
|
||||
$hub_filter_logger: "@App\\Service\\HubFilterLogger"
|
||||
|
||||
# hub distributor
|
||||
App\Service\HubDistributor:
|
||||
arguments:
|
||||
$redis: "@App\\Service\\RedisClientProvider"
|
||||
$hub_jo_key: "%env(HUB_JO_KEY)%"
|
||||
|
||||
# hub filter logger
|
||||
App\Service\HubFilterLogger:
|
||||
arguments:
|
||||
$em: "@doctrine.orm.entity_manager"
|
||||
|
||||
# hub filter geofence checking
|
||||
App\Service\HubFilteringGeoChecker:
|
||||
arguments:
|
||||
$geofence_flag: "%env(HUB_GEOFENCE_ENABLE)%"
|
||||
|
|
|
|||
41
src/Command/ImportHubFilterKMLFileCommand.php
Normal file
41
src/Command/ImportHubFilterKMLFileCommand.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use App\Entity\HubFilterArea;
|
||||
|
||||
use App\Service\HubFilterKMLFileImporter;
|
||||
|
||||
class ImportHubFilterKMLFileCommand extends Command
|
||||
{
|
||||
protected $importer;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('hubfilterarea:import')
|
||||
->setDescription('Extracts map data of the hub filter area from the KML file and saves to database')
|
||||
->setHelp('Gets the coordinates of the hub filter area and saves to the database')
|
||||
->addArgument('file', InputArgument::REQUIRED, 'Path to the KML file');
|
||||
}
|
||||
|
||||
public function __construct(HubFilterKMLFileImporter $importer)
|
||||
{
|
||||
$this->importer = $importer;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$kml_file = $input->getArgument('file');
|
||||
|
||||
$this->importer->getMapData($kml_file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
40
src/Command/ResetHubJoCountCommand.php
Normal file
40
src/Command/ResetHubJoCountCommand.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use App\Service\RedisClientProvider;
|
||||
|
||||
class ResetHubJoCountCommand extends Command
|
||||
{
|
||||
protected $redis;
|
||||
|
||||
public function __construct(RedisClientProvider $redis)
|
||||
{
|
||||
$this->redis = $redis->getRedisClient();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('hub:jo:reset')
|
||||
->setDescription('Reset hub\'s job order count')
|
||||
->setHelp('Reset hub\'s job order count');
|
||||
}
|
||||
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$key = 'hub_jo_count';
|
||||
|
||||
$this->redis->del($key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,6 +29,7 @@ use App\Ramcar\JOEventType;
|
|||
use App\Ramcar\AdvanceOrderSlot;
|
||||
use App\Ramcar\AutoAssignStatus;
|
||||
use App\Ramcar\WarrantySource;
|
||||
use App\Ramcar\HubCriteria;
|
||||
use App\Ramcar\CustomerSource;
|
||||
|
||||
use App\Service\InvoiceGeneratorInterface;
|
||||
|
|
@ -41,8 +42,11 @@ use App\Service\InventoryManager;
|
|||
use App\Service\RiderAssignmentHandlerInterface;
|
||||
use App\Service\WarrantyAPILogger;
|
||||
use App\Service\PromoLogger;
|
||||
use App\Service\HubSelector;
|
||||
use App\Service\HubDistributor;
|
||||
use App\Service\HubFilterLogger;
|
||||
use App\Service\HubFilteringGeoChecker;
|
||||
|
||||
|
||||
use App\Entity\MobileSession;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\VehicleManufacturer;
|
||||
|
|
@ -852,7 +856,9 @@ class APIController extends Controller implements LoggedController
|
|||
|
||||
public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo,
|
||||
MapTools $map_tools, InventoryManager $im, MQTTClient $mclient,
|
||||
RiderAssignmentHandlerInterface $rah, PromoLogger $promo_logger)
|
||||
RiderAssignmentHandlerInterface $rah, PromoLogger $promo_logger,
|
||||
HubSelector $hub_select, HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger,
|
||||
HubFilteringGeoChecker $hub_geofence)
|
||||
{
|
||||
// check required parameters and api key
|
||||
$required_params = [
|
||||
|
|
@ -1017,49 +1023,77 @@ class APIController extends Controller implements LoggedController
|
|||
$invoice = $ic->generateInvoice($icrit);
|
||||
$jo->setInvoice($invoice);
|
||||
|
||||
// assign hub and rider
|
||||
if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) ||
|
||||
($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY))
|
||||
// set more hub criteria fields
|
||||
$hub_criteria = new HubCriteria();
|
||||
$hub_criteria->setPoint($jo->getCoordinates());
|
||||
|
||||
if ($hub_geofence->isCovered($long, $lat))
|
||||
{
|
||||
// get nearest hub
|
||||
// $nearest_hub = $this->findNearestHubWithInventory($jo, $batt, $em, $map_tools, $im);
|
||||
$nearest_hub = $this->findNearestHub($jo, $em, $map_tools);
|
||||
}
|
||||
else
|
||||
{
|
||||
$nearest_hub = $this->findNearestHub($jo, $em, $map_tools);
|
||||
// TODO: set this properly, since the other flags
|
||||
// are on default values.
|
||||
// if true, set other values for HubCriteria
|
||||
// error_log('Area is covered by hub filtering');
|
||||
$hub_criteria->setJoType($jo->getServiceType())
|
||||
->setPaymentMethod($jo->getModeOfPayment())
|
||||
->setRoundRobin(true);
|
||||
}
|
||||
|
||||
if (!empty($nearest_hub))
|
||||
// add battery to items
|
||||
$sku = $batt->getSAPCode();
|
||||
if (!empty($sku))
|
||||
$hub_criteria->addItem($batt->getSAPCode(), 1);
|
||||
|
||||
// find nearest hubs
|
||||
$nearest_hubs = $hub_select->find($hub_criteria);
|
||||
|
||||
if (!empty($nearest_hubs))
|
||||
{
|
||||
// go through the hub list, find the nearest hub
|
||||
// with an available rider
|
||||
//error_log('found nearest hub ' . $nearest_hub->getID());
|
||||
// assign rider
|
||||
$available_riders = $nearest_hub->getAvailableRiders();
|
||||
if (count($available_riders) > 0)
|
||||
foreach ($nearest_hubs as $nearest_hub)
|
||||
{
|
||||
$assigned_rider = null;
|
||||
if (count($available_riders) > 1)
|
||||
$available_riders = $nearest_hub['hub']->getAvailableRiders();
|
||||
if (count($available_riders) >= 1)
|
||||
{
|
||||
// TODO: the setting of riders into an array
|
||||
// will no longer be necessary when the contents
|
||||
// of randomizeRider changes
|
||||
$riders = [];
|
||||
foreach ($available_riders as $rider)
|
||||
$assigned_rider = null;
|
||||
if (count($available_riders) == 1)
|
||||
{
|
||||
$riders[] = $rider;
|
||||
$assigned_rider = $available_riders[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: the setting of riders into an array
|
||||
// will no longer be necessary when the contents
|
||||
// of randomizeRider changes
|
||||
$riders = [];
|
||||
foreach ($available_riders as $rider)
|
||||
{
|
||||
$riders[] = $rider;
|
||||
}
|
||||
|
||||
$assigned_rider = $this->randomizeRider($riders);
|
||||
}
|
||||
|
||||
$assigned_rider = $this->randomizeRider($riders);
|
||||
$jo->setHub($nearest_hub['hub']);
|
||||
$jo->setRider($assigned_rider);
|
||||
$jo->setStatus(JOStatus::ASSIGNED);
|
||||
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_AND_RIDER_ASSIGNED);
|
||||
|
||||
$assigned_rider->setAvailable(false);
|
||||
|
||||
// update redis hub_jo_count for hub
|
||||
$hub_dist->incrementJoCountForHub($nearest_hub['hub']);
|
||||
|
||||
// break out of loop
|
||||
break;
|
||||
}
|
||||
else
|
||||
$assigned_rider = $available_riders[0];
|
||||
|
||||
//error_log('found rider ' . $assigned_rider->getID());
|
||||
$jo->setHub($nearest_hub);
|
||||
$jo->setRider($assigned_rider);
|
||||
$jo->setStatus(JOStatus::ASSIGNED);
|
||||
|
||||
$assigned_rider->setAvailable(false);
|
||||
{
|
||||
// log hub into hub_filter_log
|
||||
$hub_filter_logger->logFilteredHub($nearest_hub['hub'], 'no_available_rider');
|
||||
// continue to go through list to find hub with an available rider
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2369,7 +2403,9 @@ class APIController extends Controller implements LoggedController
|
|||
|
||||
public function newRequestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo,
|
||||
MapTools $map_tools, InventoryManager $im, MQTTClient $mclient,
|
||||
RiderAssignmentHandlerInterface $rah, PromoLogger $promo_logger)
|
||||
RiderAssignmentHandlerInterface $rah, PromoLogger $promo_logger,
|
||||
HubSelector $hub_select, HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger,
|
||||
HubFilteringGeoChecker $hub_geofence)
|
||||
{
|
||||
// check required parameters and api key
|
||||
$required_params = [
|
||||
|
|
@ -2554,50 +2590,76 @@ class APIController extends Controller implements LoggedController
|
|||
// check if hub is null
|
||||
if ($hub == null)
|
||||
{
|
||||
// find nearest hub
|
||||
if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) ||
|
||||
($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY))
|
||||
$hub_criteria = new HubCriteria();
|
||||
$hub_criteria->setPoint($jo->getCoordinates());
|
||||
|
||||
if ($hub_geofence->isCovered($long, $lat))
|
||||
{
|
||||
// get nearest hub
|
||||
// $nearest_hub = $this->findNearestHubWithInventory($jo, $batt, $em, $map_tools, $im);
|
||||
$nearest_hub = $this->findNearestHub($jo, $em, $map_tools);
|
||||
}
|
||||
else
|
||||
{
|
||||
$nearest_hub = $this->findNearestHub($jo, $em, $map_tools);
|
||||
// if true, set other values for HubCriteria
|
||||
// TODO: set this properly, since the other flags
|
||||
// are on default values
|
||||
// error_log('Area is covered by hub filtering');
|
||||
$hub_criteria->setJoType($jo->getServiceType())
|
||||
->setPaymentMethod($jo->getModeOfPayment())
|
||||
->setRoundRobin(true);
|
||||
}
|
||||
|
||||
if (!empty($nearest_hub))
|
||||
// add battery to items
|
||||
$sku = $batt->getSAPCode();
|
||||
if (!empty($sku))
|
||||
$hub_criteria->addItem($batt->getSAPCode(), 1);
|
||||
|
||||
// find nearest hubs
|
||||
$nearest_hubs = $hub_select->find($hub_criteria);
|
||||
|
||||
if (!empty($nearest_hubs))
|
||||
{
|
||||
// go through the hub list, find the nearest hub
|
||||
// with an available rider
|
||||
//error_log('found nearest hub ' . $nearest_hub->getID());
|
||||
// assign rider
|
||||
$available_riders = $nearest_hub->getAvailableRiders();
|
||||
if (count($available_riders) > 0)
|
||||
foreach ($nearest_hubs as $nearest_hub)
|
||||
{
|
||||
$assigned_rider = null;
|
||||
if (count($available_riders) > 1)
|
||||
$available_riders = $nearest_hub['hub']->getAvailableRiders();
|
||||
if (count($available_riders) >= 1)
|
||||
{
|
||||
// TODO: the setting of riders into an array
|
||||
// will no longer be necessary when the contents
|
||||
// of randomizeRider changes
|
||||
$riders = [];
|
||||
foreach ($available_riders as $rider)
|
||||
$assigned_rider = null;
|
||||
if (count($available_riders) == 1)
|
||||
{
|
||||
$riders[] = $rider;
|
||||
$assigned_rider = $available_riders[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: the setting of riders into an array
|
||||
// will no longer be necessary when the contents
|
||||
// of randomizeRider changes
|
||||
$riders = [];
|
||||
foreach ($available_riders as $rider)
|
||||
{
|
||||
$riders[] = $rider;
|
||||
}
|
||||
|
||||
$assigned_rider = $this->randomizeRider($riders);
|
||||
}
|
||||
|
||||
$assigned_rider = $this->randomizeRider($riders);
|
||||
$jo->setHub($nearest_hub['hub']);
|
||||
$jo->setRider($assigned_rider);
|
||||
$jo->setStatus(JOStatus::ASSIGNED);
|
||||
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_AND_RIDER_ASSIGNED);
|
||||
|
||||
$assigned_rider->setAvailable(false);
|
||||
|
||||
// update redis hub_jo_count for hub
|
||||
$hub_dist->incrementJoCountForHub($nearest_hub['hub']);
|
||||
|
||||
// break out of loop
|
||||
break;
|
||||
}
|
||||
else
|
||||
$assigned_rider = $available_riders[0];
|
||||
|
||||
//error_log('found rider ' . $assigned_rider->getID());
|
||||
$jo->setHub($nearest_hub);
|
||||
$jo->setRider($assigned_rider);
|
||||
$jo->setStatus(JOStatus::ASSIGNED);
|
||||
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_AND_RIDER_ASSIGNED);
|
||||
|
||||
$assigned_rider->setAvailable(false);
|
||||
{
|
||||
// log hub into hub_filter_log
|
||||
$hub_filter_logger->logFilteredHub($nearest_hub['hub'], 'no_available_rider');
|
||||
// continue to go through list to find hub with an available rider
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2620,7 +2682,10 @@ class APIController extends Controller implements LoggedController
|
|||
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_ASSIGNED);
|
||||
|
||||
if ($date_schedule != null)
|
||||
$jo->setDateSchedule($date_schedule);
|
||||
$jo->setDateSchedule($date_schedule);
|
||||
|
||||
// update redis hub_jo_count for hub
|
||||
$hub_dist->incrementJoCountForHub($hub);
|
||||
}
|
||||
|
||||
$em->persist($jo);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,12 @@ use DateTime;
|
|||
|
||||
use Catalyst\MenuBundle\Annotation\Menu;
|
||||
|
||||
use App\Service\MapTools;
|
||||
use App\Service\RiderTracker;
|
||||
use App\Service\HubSelector;
|
||||
use App\Service\RisingTideGateway;
|
||||
|
||||
use App\Ramcar\HubCriteria;
|
||||
use App\Ramcar\ModeOfPayment;
|
||||
|
||||
class HubController extends Controller
|
||||
{
|
||||
|
|
@ -128,6 +132,7 @@ class HubController extends Controller
|
|||
$params = [];
|
||||
$params['obj'] = new Hub();
|
||||
$params['mode'] = 'create';
|
||||
$params['payment_methods'] = ModeOfPayment::getCollection();
|
||||
|
||||
// response
|
||||
return $this->render('hub/form.html.twig', $params);
|
||||
|
|
@ -154,7 +159,17 @@ class HubController extends Controller
|
|||
->setBranchCode($req->request->get('branch_code', ''))
|
||||
->setStatusOpen($req->request->get('status_open', false))
|
||||
->setRiderSlots($req->request->get('rider_slots', 0))
|
||||
->setHubViewFlag($req->request->get('flag_hub_view', false));
|
||||
->setHubViewFlag($req->request->get('flag_hub_view', false))
|
||||
->setNotifNumber($req->request->get('notif_number'))
|
||||
->clearPaymentMethods();
|
||||
|
||||
// set payment methods
|
||||
$payment_methods = $req->request->get('payment_methods');
|
||||
|
||||
if (!empty($payment_methods))
|
||||
{
|
||||
$obj->setPaymentMethods($payment_methods);
|
||||
}
|
||||
}
|
||||
|
||||
protected function setQueryFilters($datatable, QueryBuilder $query)
|
||||
|
|
@ -166,7 +181,7 @@ class HubController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
public function addSubmit(Request $req, EncoderFactoryInterface $ef, ValidatorInterface $validator)
|
||||
public function addSubmit(Request $req, EncoderFactoryInterface $ef, ValidatorInterface $validator, RisingTideGateway $rt)
|
||||
{
|
||||
$this->denyAccessUnlessGranted('hub.add', null, 'No access.');
|
||||
|
||||
|
|
@ -176,14 +191,23 @@ class HubController extends Controller
|
|||
$em = $this->getDoctrine()->getManager();
|
||||
$obj = new Hub();
|
||||
|
||||
// initialize error list
|
||||
$error_array = [];
|
||||
|
||||
// validate the notification number
|
||||
$mobile = $req->request->get('notif_number');
|
||||
if (!empty($mobile))
|
||||
{
|
||||
$is_valid = $rt->validatePhoneNumber($mobile);
|
||||
if (!$is_valid)
|
||||
$error_array['notif_number'] = 'Invalid notification number';
|
||||
}
|
||||
|
||||
$this->setObject($obj, $req);
|
||||
|
||||
// validate
|
||||
$errors = $validator->validate($obj);
|
||||
|
||||
// initialize error list
|
||||
$error_array = [];
|
||||
|
||||
// add errors to list
|
||||
foreach ($errors as $error) {
|
||||
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
||||
|
|
@ -226,12 +250,14 @@ class HubController extends Controller
|
|||
$params = [];
|
||||
$params['obj'] = $obj;
|
||||
$params['mode'] = 'update';
|
||||
$params['payment_methods'] = ModeOfPayment::getCollection();
|
||||
|
||||
// response
|
||||
return $this->render('hub/form.html.twig', $params);
|
||||
}
|
||||
|
||||
public function updateSubmit(Request $req, EncoderFactoryInterface $ef, ValidatorInterface $validator, $id)
|
||||
public function updateSubmit(Request $req, EncoderFactoryInterface $ef, ValidatorInterface $validator, $id,
|
||||
RisingTideGateway $rt)
|
||||
{
|
||||
$this->denyAccessUnlessGranted('hub.update', null, 'No access.');
|
||||
|
||||
|
|
@ -243,14 +269,23 @@ class HubController extends Controller
|
|||
if (empty($obj))
|
||||
throw $this->createNotFoundException('The item does not exist');
|
||||
|
||||
// initialize error list
|
||||
$error_array = [];
|
||||
|
||||
// validate the notification number
|
||||
$mobile = $req->request->get('notif_number');
|
||||
if (!empty($mobile))
|
||||
{
|
||||
$is_valid = $rt->validatePhoneNumber($mobile);
|
||||
if (!$is_valid)
|
||||
$error_array['notif_number'] = 'Invalid notification number';
|
||||
}
|
||||
|
||||
$this->setObject($obj, $req);
|
||||
|
||||
// validate
|
||||
$errors = $validator->validate($obj);
|
||||
|
||||
// initialize error list
|
||||
$error_array = [];
|
||||
|
||||
// add errors to list
|
||||
foreach ($errors as $error) {
|
||||
$error_array[$error->getPropertyPath()] = $error->getMessage();
|
||||
|
|
@ -295,7 +330,7 @@ class HubController extends Controller
|
|||
$response->send();
|
||||
}
|
||||
|
||||
public function nearest(MapTools $map_tools, Request $req)
|
||||
public function nearest(HubSelector $hub_selector, Request $req)
|
||||
{
|
||||
// get lat / long
|
||||
$lat = $req->query->get('lat');
|
||||
|
|
@ -303,7 +338,11 @@ class HubController extends Controller
|
|||
|
||||
// get nearest hubs according to position
|
||||
$point = new Point($long, $lat);
|
||||
$result = $map_tools->getClosestHubs($point, 10, date("H:i:s"));
|
||||
|
||||
// set up hub criteria
|
||||
$hub_criteria = new HubCriteria();
|
||||
$hub_criteria->setPoint($point);
|
||||
$hub_selector->find($hub_criteria);
|
||||
|
||||
$hubs = [];
|
||||
foreach ($result as $hub_res)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ use App\Service\MapTools;
|
|||
use App\Service\MQTTClient;
|
||||
use App\Service\APNSClient;
|
||||
use App\Service\InventoryManager;
|
||||
use App\Service\HubSelector;
|
||||
|
||||
use App\Service\RiderTracker;
|
||||
use App\Service\MotivConnector;
|
||||
|
|
@ -315,13 +316,13 @@ class JobOrderController extends Controller
|
|||
/**
|
||||
* @Menu(selected="jo_proc")
|
||||
*/
|
||||
public function processingForm(MapTools $map_tools, $id, JobOrderHandlerInterface $jo_handler, GISManagerInterface $gis, MotivConnector $motiv)
|
||||
public function processingForm(HubSelector $hub_selector, $id, JobOrderHandlerInterface $jo_handler, GISManagerInterface $gis, MotivConnector $motiv)
|
||||
{
|
||||
$this->denyAccessUnlessGranted('jo_proc.list', null, 'No access.');
|
||||
|
||||
try
|
||||
{
|
||||
$params = $jo_handler->initializeProcessingForm($id, $map_tools, $motiv);
|
||||
$params = $jo_handler->initializeProcessingForm($id, $hub_selector, $motiv);
|
||||
}
|
||||
catch (AccessDeniedHttpException $e)
|
||||
{
|
||||
|
|
@ -504,14 +505,14 @@ class JobOrderController extends Controller
|
|||
/**
|
||||
* @Menu(selected="jo_open")
|
||||
*/
|
||||
public function openHubForm(MapTools $map_tools, $id, JobOrderHandlerInterface $jo_handler,
|
||||
public function openHubForm(HubSelector $hub_selector, $id, JobOrderHandlerInterface $jo_handler,
|
||||
GISManagerInterface $gis)
|
||||
{
|
||||
$this->denyAccessUnlessGranted('jo_open.list', null, 'No access.');
|
||||
|
||||
try
|
||||
{
|
||||
$params = $jo_handler->initializeHubForm($id, $map_tools);
|
||||
$params = $jo_handler->initializeHubForm($id, $hub_selector);
|
||||
}
|
||||
catch (NotFoundHttpException $e)
|
||||
{
|
||||
|
|
@ -1207,6 +1208,8 @@ class JobOrderController extends Controller
|
|||
/**
|
||||
* @Menu(selected="jo_autoassign")
|
||||
*/
|
||||
// this is uncalled or does not display in admin panel
|
||||
/*
|
||||
public function autoAssignForm(GISManagerInterface $gis, JobOrderHandlerInterface $jo_handler)
|
||||
{
|
||||
$this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.');
|
||||
|
|
@ -1375,6 +1378,6 @@ class JobOrderController extends Controller
|
|||
$selected_rider = $riders[$selected_index];
|
||||
|
||||
return $selected_rider;
|
||||
}
|
||||
} */
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,18 @@ class Hub
|
|||
*/
|
||||
protected $flag_hub_view;
|
||||
|
||||
// notification number to send SMS to if hub doesn't have item
|
||||
/**
|
||||
* @ORM\Column(type="string", length=30)
|
||||
*/
|
||||
protected $notif_number;
|
||||
|
||||
// payment methods
|
||||
/**
|
||||
* @ORM\Column(type="array", nullable=true)
|
||||
*/
|
||||
protected $payment_methods;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->time_open = new DateTime();
|
||||
|
|
@ -76,6 +88,8 @@ class Hub
|
|||
$this->outlets = new ArrayCollection();
|
||||
$this->status_open = true;
|
||||
$this->flag_hub_view = false;
|
||||
$this->notif_number = '';
|
||||
$this->payment_methods = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getRiders()
|
||||
|
|
@ -185,5 +199,37 @@ class Hub
|
|||
return $this->flag_hub_view;
|
||||
}
|
||||
|
||||
public function setNotifNumber($notif_number)
|
||||
{
|
||||
$this->notif_number = $notif_number;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNotifNumber()
|
||||
{
|
||||
return $this->notif_number;
|
||||
}
|
||||
|
||||
public function getPaymentMethods()
|
||||
{
|
||||
return $this->payment_methods;
|
||||
}
|
||||
|
||||
public function setPaymentMethods(array $payment_methods)
|
||||
{
|
||||
$this->payment_methods = new ArrayCollection();
|
||||
|
||||
foreach ($payment_methods as $payment_method)
|
||||
{
|
||||
$this->payment_methods->add($payment_method);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function clearPaymentMethods()
|
||||
{
|
||||
$this->payment_methods = new ArrayCollection();
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
85
src/Entity/HubFilterArea.php
Normal file
85
src/Entity/HubFilterArea.php
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Polygon;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="hub_filter_area")
|
||||
*/
|
||||
class HubFilterArea
|
||||
{
|
||||
// unique id
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
// date supported area was created
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
protected $date_create;
|
||||
|
||||
// name of the supported area
|
||||
/**
|
||||
* @ORM\Column(type="string", length=80)
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
// coordinates of the supported area
|
||||
/**
|
||||
* @ORM\Column(type="polygon")
|
||||
*/
|
||||
protected $coverage_area;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->date_create = new DateTime();
|
||||
}
|
||||
|
||||
public function getID()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setDateCreate(DateTime $date_create)
|
||||
{
|
||||
$this->date_create = $date_create;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateCreate()
|
||||
{
|
||||
return $this->date_Create;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setCoverageArea(Polygon $polygon)
|
||||
{
|
||||
$this->coverage_area = $polygon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCoverageArea()
|
||||
{
|
||||
return $this->coverage_area;
|
||||
}
|
||||
}
|
||||
84
src/Entity/HubFilterLog.php
Normal file
84
src/Entity/HubFilterLog.php
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
use App\Entity\Hub;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(name="hub_filter_log")
|
||||
*/
|
||||
class HubFilterLog
|
||||
{
|
||||
// unique id
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
// date created
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
*/
|
||||
protected $date_create;
|
||||
|
||||
// hub that was not included in results
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Hub", inversedBy="hub_filtered")
|
||||
* @ORM\JoinColumn(name="hub_filtered_id", referencedColumnName="id", nullable=true)
|
||||
*/
|
||||
protected $hub;
|
||||
|
||||
// filter that eliminated hub
|
||||
/**
|
||||
* @ORM\Column(type="string", length=80)
|
||||
* @Assert\NotBlank()
|
||||
*/
|
||||
protected $filter_type_id;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->date_create = new DateTime();
|
||||
}
|
||||
|
||||
public function getID()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getDateCreate()
|
||||
{
|
||||
return $this->date_create;
|
||||
}
|
||||
|
||||
public function setHub(Hub $hub)
|
||||
{
|
||||
$this->hub = $hub;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHub()
|
||||
{
|
||||
return $this->hub;
|
||||
}
|
||||
|
||||
public function setFilterTypeId($filter_type_id)
|
||||
{
|
||||
$this->filter_type_id = $filter_type_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFilterTypeId()
|
||||
{
|
||||
return $this->filter_type_id;
|
||||
}
|
||||
}
|
||||
|
||||
149
src/Ramcar/HubCriteria.php
Normal file
149
src/Ramcar/HubCriteria.php
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
namespace App\Ramcar;
|
||||
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class HubCriteria
|
||||
{
|
||||
protected $point; // coordinates of source
|
||||
protected $limit_results; // number of results to return
|
||||
protected $limit_distance; // distance limit for search in km
|
||||
protected $flag_inventory_check; // flag if we need to check for inventory
|
||||
protected $jo_type; // jo service needed
|
||||
protected $date_time; // date and time to check if hub is open or not
|
||||
protected $items; // array of items: items[sku] = quantity to check for
|
||||
protected $payment_method; // payment method of JO
|
||||
protected $flag_emergency; // flag if emergency or not
|
||||
protected $flag_round_robin; // flag if we use round robin or not
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// TODO: default values might still change
|
||||
$this->limit_results = 10;
|
||||
$this->limit_distance = 500;
|
||||
$this->jo_type = '';
|
||||
$this->date_time = null;
|
||||
$this->flag_inventory_check = false;
|
||||
$this->items = [];
|
||||
$this->payment_method = '';
|
||||
$flag_emergency = false;
|
||||
$flag_round_robin = false;
|
||||
}
|
||||
|
||||
public function setPoint(Point $point)
|
||||
{
|
||||
$this->point = $point;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPoint()
|
||||
{
|
||||
return $this->point;
|
||||
}
|
||||
|
||||
public function setLimitResults($limit_results)
|
||||
{
|
||||
$this->limit_results = $limit_results;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLimitResults()
|
||||
{
|
||||
return $this->limit_results;
|
||||
}
|
||||
|
||||
public function setLimitDistance($limit_distance)
|
||||
{
|
||||
$this->limit_distance = $limit_distance;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLimitDistance()
|
||||
{
|
||||
return $this->limit_distance;
|
||||
}
|
||||
|
||||
public function setInventoryCheck($flag_inventory_check = true)
|
||||
{
|
||||
$this->flag_inventory_check = $flag_inventory_check;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasInventoryCheck()
|
||||
{
|
||||
return $this->flag_inventory_check;
|
||||
}
|
||||
|
||||
public function setJoType($jo_type)
|
||||
{
|
||||
// TODO: validate the jo type
|
||||
$this->jo_type = $jo_type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getJoType()
|
||||
{
|
||||
return $this->jo_type;
|
||||
}
|
||||
|
||||
public function setDateTime(DateTime $date_time)
|
||||
{
|
||||
$this->date_time = $date_time;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDateTime()
|
||||
{
|
||||
return $this->date_time;
|
||||
}
|
||||
|
||||
public function addItem($sku, $quantity)
|
||||
{
|
||||
// at this point, sku is assumed to be a valid item
|
||||
$this->items[$sku] = $quantity;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getItems()
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
public function setPaymentMethod($payment_method)
|
||||
{
|
||||
$this->payment_method = $payment_method;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPaymentMethod()
|
||||
{
|
||||
return $this->payment_method;
|
||||
}
|
||||
|
||||
public function setEmergency($flag_emergency = true)
|
||||
{
|
||||
$this->flag_emergency = $flag_emergency;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isEmergency()
|
||||
{
|
||||
return $this->flag_emergency;
|
||||
}
|
||||
|
||||
public function setRoundRobin($flag_round_robin = true)
|
||||
{
|
||||
$this->flag_round_robin = $flag_round_robin;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRoundRobin()
|
||||
{
|
||||
return $this->flag_round_robin;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
110
src/Service/HubDistributor.php
Normal file
110
src/Service/HubDistributor.php
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Service\RedisClientProvider;
|
||||
|
||||
use App\Entity\Hub;
|
||||
|
||||
class HubDistributor
|
||||
{
|
||||
protected $redis;
|
||||
protected $hub_jo_key;
|
||||
|
||||
public function __construct(RedisClientProvider $redis, $hub_jo_key)
|
||||
{
|
||||
$this->redis = $redis->getRedisClient();
|
||||
$this->hub_jo_key = $hub_jo_key;
|
||||
}
|
||||
|
||||
public function incrementJoCountForHub(Hub $hub)
|
||||
{
|
||||
$key = $hub->getID();
|
||||
|
||||
// get current count
|
||||
$jo_count = $this->redis->hget($this->hub_jo_key, $key);
|
||||
if ($jo_count == false)
|
||||
{
|
||||
// hub not in hash
|
||||
// add hub to hash
|
||||
// set to 1 since this is first jo for hub
|
||||
$this->redis->hset($this->hub_jo_key, $key, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// hub exist in hash
|
||||
// add to count
|
||||
$this->redis->hset($this->hub_jo_key, $key, $jo_count + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public function decrementJoCountForHub(Hub $hub)
|
||||
{
|
||||
$key = $hub->getID();
|
||||
|
||||
// get current count
|
||||
$jo_count = $this->redis->hget($this->hub_jo_key, $key);
|
||||
if ($jo_count)
|
||||
{
|
||||
// hub exist in hash
|
||||
// decrement count
|
||||
$this->redis->hset($this->hub_jo_key, $key, $jo_count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public function arrangeHubs($hubs)
|
||||
{
|
||||
if (count($hubs) == 1)
|
||||
return $hubs;
|
||||
|
||||
$arranged_hubs = [];
|
||||
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
// need the id of hub
|
||||
$key = $hub->getID();
|
||||
|
||||
// get jo count of hub
|
||||
$hub_jo_count = $this->redis->hget($this->hub_jo_key, $key);
|
||||
|
||||
// check if hub is in hash. if not, hub has no jobs
|
||||
// but should still be added to results
|
||||
if ($hub_jo_count != null)
|
||||
{
|
||||
$arranged_hubs[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => $hub_jo_count,
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$arranged_hubs[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
usort($arranged_hubs, function($a, $b) {
|
||||
if ($a['jo_count'] == $b['jo_count'])
|
||||
return 0;
|
||||
if ($a['jo_count'] < $b['jo_count'])
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
});
|
||||
|
||||
//error_log('arranged hubs ' . json_encode($arranged_hubs));
|
||||
|
||||
return $arranged_hubs;
|
||||
}
|
||||
}
|
||||
|
||||
82
src/Service/HubFilterKMLFileImporter.php
Normal file
82
src/Service/HubFilterKMLFileImporter.php
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use XMLReader;
|
||||
|
||||
use App\Entity\HubFilterArea;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Polygon;
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\LineString;
|
||||
|
||||
class HubFilterKMLFileImporter
|
||||
{
|
||||
protected $em;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function getMapData($fh)
|
||||
{
|
||||
$placemark_name = '';
|
||||
|
||||
$reader = new XMLReader();
|
||||
$reader->open($fh);
|
||||
|
||||
while($reader->read())
|
||||
{
|
||||
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "Placemark")
|
||||
{
|
||||
while($reader->read())
|
||||
{
|
||||
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "name")
|
||||
{
|
||||
$placemark_name = $reader->readInnerXML();
|
||||
}
|
||||
|
||||
if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "coordinates")
|
||||
{
|
||||
// each polygon is a new area
|
||||
$hub_filter_area = new HubFilterArea();
|
||||
$hub_filter_area->setName($placemark_name);
|
||||
|
||||
$point_array = [];
|
||||
$coordinates = $reader->readInnerXML();
|
||||
|
||||
// get each line
|
||||
$coord_split = explode("\n", $coordinates);
|
||||
|
||||
// go through all the coordinates
|
||||
foreach ($coord_split as $coord)
|
||||
{
|
||||
// skip blank lines
|
||||
$coord_trim = trim($coord);
|
||||
if (strlen($coord_trim) <= 0)
|
||||
continue;
|
||||
|
||||
// echo "$coord_trim\n";
|
||||
|
||||
$point_split = explode(',', $coord_trim);
|
||||
|
||||
$point_array[] = new Point($point_split[0], $point_split[1]);
|
||||
}
|
||||
|
||||
$area = new Polygon([new LineString($point_array)]);
|
||||
$hub_filter_area->setCoverageArea($area);
|
||||
|
||||
// add hub filter area
|
||||
$this->em->persist($hub_filter_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$reader->close();
|
||||
|
||||
$this->em->flush();
|
||||
}
|
||||
}
|
||||
30
src/Service/HubFilterLogger.php
Normal file
30
src/Service/HubFilterLogger.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use App\Entity\Hub;
|
||||
use App\Entity\HubFilterLog;
|
||||
|
||||
class HubFilterLogger
|
||||
{
|
||||
protected $em;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function logFilteredHub(Hub $hub, $filter_type)
|
||||
{
|
||||
$hub_filter_log = new HubFilterLog();
|
||||
|
||||
$hub_filter_log->setHub($hub)
|
||||
->setFilterTypeId($filter_type);
|
||||
|
||||
$this->em->persist($hub_filter_log);
|
||||
$this->em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
44
src/Service/HubFilteringGeoChecker.php
Normal file
44
src/Service/HubFilteringGeoChecker.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
||||
|
||||
use App\Entity\HubFilterArea;
|
||||
|
||||
class HubFilteringGeoChecker
|
||||
{
|
||||
protected $em;
|
||||
protected $geofence_flag;
|
||||
|
||||
public function __construct(EntityManagerInterface $em, $geofence_flag)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->geofence_flag = $geofence_flag;
|
||||
}
|
||||
|
||||
public function isCovered($long, $lat)
|
||||
{
|
||||
// check if geofence is enabled
|
||||
if ($this->geofence_flag == 'true')
|
||||
{
|
||||
// see if the point is in any of the polygons
|
||||
$query = $this->em->createQuery('SELECT count(s) from App\Entity\HubFilterArea s where st_contains(s.coverage_area, point(:long, :lat)) = true')
|
||||
->setParameter('long', $long)
|
||||
->setParameter('lat', $lat);
|
||||
|
||||
// number of polygons that contain the point
|
||||
$count = $query->getSingleScalarResult();
|
||||
|
||||
if ($count > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
453
src/Service/HubSelector.php
Normal file
453
src/Service/HubSelector.php
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
||||
|
||||
use App\Entity\Hub;
|
||||
|
||||
use App\Service\HubDistributor;
|
||||
use App\Service\InventoryManager;
|
||||
use App\Service\HubFilterLogger;
|
||||
use App\Service\RisingTideGateway;
|
||||
|
||||
use App\Ramcar\HubCriteria;
|
||||
use App\Ramcar\ServiceType;
|
||||
|
||||
class HubSelector
|
||||
{
|
||||
protected $em;
|
||||
protected $im;
|
||||
protected $hub_distributor;
|
||||
protected $hub_filter_logger;
|
||||
protected $trans;
|
||||
protected $rt;
|
||||
|
||||
public function __construct(EntityManagerInterface $em, InventoryManager $im,
|
||||
HubDistributor $hub_distributor, HubFilterLogger $hub_filter_logger,
|
||||
TranslatorInterface $trans, RisingTideGateway $rt)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->im = $im;
|
||||
$this->hub_distributor = $hub_distributor;
|
||||
$this->hub_filter_logger = $hub_filter_logger;
|
||||
$this->trans = $trans;
|
||||
$this->rt = $rt;
|
||||
}
|
||||
|
||||
public function find(HubCriteria $criteria)
|
||||
{
|
||||
$point = $criteria->getPoint();
|
||||
$limit_results = $criteria->getLimitResults();
|
||||
$limit_distance = $criteria->getLimitDistance();
|
||||
$jo_type = $criteria->getJoType();
|
||||
$flag_inventory_check = $criteria->hasInventoryCheck();
|
||||
$items = $criteria->getItems();
|
||||
$date_time = $criteria->getDateTime();
|
||||
$payment_method = $criteria->getPaymentMethod();
|
||||
$flag_emergency = $criteria->isEmergency();
|
||||
$flag_round_robin = $criteria->isRoundRobin();
|
||||
|
||||
$results = [];
|
||||
|
||||
// get all the hubs within distance
|
||||
$filtered_hubs = $this->getClosestHubs($point, $limit_distance);
|
||||
|
||||
error_log('closest hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
if (!$flag_emergency)
|
||||
{
|
||||
// filter the first hub results for date and opening times
|
||||
$hubs_date_time = $this->filterHubsByDateAndTime($filtered_hubs, $date_time);
|
||||
$filtered_hubs = $hubs_date_time;
|
||||
|
||||
//error_log('date_time hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// filter jo types
|
||||
$hubs_jo_type = $this->filterHubsByJoType($filtered_hubs, $jo_type);
|
||||
$filtered_hubs = $hubs_jo_type;
|
||||
|
||||
//error_log('jo_type hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// filter hubs by payment methods
|
||||
$hubs_payment_method = $this->filterHubsByPaymentMethod($filtered_hubs, $payment_method);
|
||||
$filtered_hubs = $hubs_payment_method;
|
||||
|
||||
//error_log('payment hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// inventory filter
|
||||
$hubs_inventory = $this->filterHubsByInventory($filtered_hubs, $flag_inventory_check,
|
||||
$jo_type, $items);
|
||||
$filtered_hubs = $hubs_inventory;
|
||||
|
||||
//error_log('inventory hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// round robin filter
|
||||
$hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs, $flag_round_robin);
|
||||
$filtered_hubs = $hubs_round_robin;
|
||||
|
||||
//error_log('round robin hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// max results filter
|
||||
$hubs_max_result = $this->filterHubsByMaxResults($filtered_hubs, $limit_results);
|
||||
$filtered_hubs = $hubs_max_result;
|
||||
}
|
||||
|
||||
$results = $filtered_hubs;
|
||||
|
||||
error_log(json_encode($results));
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByRoundRobin($hubs, $flag_round_robin)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (!$flag_round_robin)
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
// call hub distributor service
|
||||
$arranged_hubs = $this->hub_distributor->arrangeHubs($hubs);
|
||||
$results = $arranged_hubs;
|
||||
|
||||
return $results;
|
||||
|
||||
}
|
||||
|
||||
protected function filterHubsByMaxResults($hubs, $limit_result)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (empty($limit_result))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
for ($i = 0; $i < count($hubs); $i++)
|
||||
{
|
||||
if ($i < $limit_result)
|
||||
$results[] = $hubs[$i];
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hubs[$i]['hub'], 'max_results');
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByJoType($hubs, $jo_type)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (empty($jo_type))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
// TODO: for now, have this return true
|
||||
$has_jo_type = true;
|
||||
// check if hub offers the jo_type
|
||||
// TODO: add service to hub
|
||||
if ($has_jo_type)
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
];
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'job_order_type');
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByPaymentMethod($hubs, $payment_method)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (empty($payment_method))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
// name of payment method is what is saved
|
||||
$payment_methods = $hub->getPaymentMethods();
|
||||
if ($payment_methods != null)
|
||||
{
|
||||
$flag_found_pmethod = false;
|
||||
foreach ($payment_methods as $pmethod)
|
||||
{
|
||||
if ($pmethod == $payment_method)
|
||||
{
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
];
|
||||
}
|
||||
$flag_found_pmethod = true;
|
||||
}
|
||||
|
||||
if (!$flag_found_pmethod)
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_payment_method');
|
||||
}
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_payment_method');
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByDateAndTime($hubs, $date_time)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
|
||||
if ($date_time == null)
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
// go through each hub's opening times to check if hub is open
|
||||
// for the specified time
|
||||
// get hub opening and closing times
|
||||
// TODO: maybe in the future, might also have to check if hub
|
||||
// is open/available on date/day
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
$time_open = $hub->getTimeOpen()->format("H:i:s");
|
||||
$time_close = $hub->getTimeClose()->format("H:i:s");
|
||||
|
||||
$filter_time = $date_time->format("H:i:s");
|
||||
|
||||
if (($filter_time >= $time_open) &&
|
||||
($filter_time <= $time_close))
|
||||
{
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
];
|
||||
}
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'date_and_time');
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByInventory($hubs, $flag_inventory_check, $jo_type, $items)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
|
||||
if (!$flag_inventory_check)
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
if ($flag_inventory_check)
|
||||
{
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
if ($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW)
|
||||
{
|
||||
// call inventory
|
||||
$has_items = $this->checkInventory($items, $hub);
|
||||
if ($has_items)
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
];
|
||||
else
|
||||
{
|
||||
// get the skus for the message
|
||||
$sku_text = '';
|
||||
foreach ($items as $key => $value)
|
||||
{
|
||||
$sku_text .= ' ' . $key;
|
||||
}
|
||||
// send SMS to hub
|
||||
$message = str_replace('item_display', trim($sku_text), $this->trans->trans('no_inventory_message'));
|
||||
error_log($message);
|
||||
$this->sendSMSMessage($hub, $items);
|
||||
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_inventory');
|
||||
}
|
||||
}
|
||||
if ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY)
|
||||
{
|
||||
// call inventory
|
||||
$has_items = $this->checkInventory($items, $hub);
|
||||
if ($has_items)
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
];
|
||||
else
|
||||
{
|
||||
// get the skus for the message
|
||||
$sku_text = '';
|
||||
foreach ($items as $key => $value)
|
||||
{
|
||||
$sku_text .= ' ' . $key;
|
||||
}
|
||||
// send SMS to hub
|
||||
$message = str_replace('item_display', trim($sku_text), $this->trans->trans('no_inventory_message'));
|
||||
error_log($message);
|
||||
$this->sendSMSMessage($hub, $items);
|
||||
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_inventory');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function getClosestHubs(Point $point, $limit_distance)
|
||||
{
|
||||
// get closest hubs based on st_distance function from db
|
||||
$query_string = 'SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h WHERE h.status_open = true ORDER BY dist';
|
||||
|
||||
$query = $this->em->createQuery($query_string)
|
||||
->setParameter('lat', $point->getLatitude())
|
||||
->setParameter('lng', $point->getLongitude());
|
||||
|
||||
// error_log($query->getSql());
|
||||
$result = $query->getResult();
|
||||
|
||||
$hubs = [];
|
||||
$hubs_data = [];
|
||||
foreach ($result as $row)
|
||||
{
|
||||
$hubs[] = $row[0];
|
||||
|
||||
// get coordinates of hub
|
||||
$hub_coordinates = $row[0]->getCoordinates();
|
||||
|
||||
$cust_lat = $point->getLatitude();
|
||||
$cust_lng = $point->getLongitude();
|
||||
|
||||
$hub_lat = $hub_coordinates->getLatitude();
|
||||
$hub_lng = $hub_coordinates->getLongitude();
|
||||
|
||||
// get distance in kilometers from customer point to hub point
|
||||
$dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng);
|
||||
|
||||
if ($dist < $limit_distance)
|
||||
{
|
||||
$hubs_data[] = [
|
||||
'hub' => $row[0],
|
||||
'db_distance' => $row['dist'],
|
||||
'distance' => $dist,
|
||||
'duration' => 0,
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hub_filter_logger->logFilteredHub($row[0], 'distance');
|
||||
}
|
||||
}
|
||||
|
||||
return $hubs_data;
|
||||
}
|
||||
|
||||
protected function checkInventory($items, $hub)
|
||||
{
|
||||
// check if hub has all items
|
||||
$skus = [];
|
||||
$branch_codes[] = $hub->getBranchCode();
|
||||
$result = false;
|
||||
|
||||
foreach ($items as $key=> $value)
|
||||
{
|
||||
// add sap code of item/battery into array since
|
||||
// getBranchesInventory takes in an array of hubs/branches
|
||||
// and an array of skus
|
||||
// $items as format: $items[sku] = quantity
|
||||
$skus[] = $key;
|
||||
}
|
||||
|
||||
// call InventoryManager's getBranchesInventory to check if hub has all items
|
||||
$branches_with_items = $this->im->getBranchesInventory($branch_codes, $skus);
|
||||
|
||||
if (!empty($branches_with_items))
|
||||
{
|
||||
// check if branch has enough quantity for item
|
||||
foreach ($branches_with_items as $branch)
|
||||
{
|
||||
// get quantity from call
|
||||
$qty_available = $branch['Quantity'];
|
||||
|
||||
// get the quantity request
|
||||
$sku_requested = $branch['SapCode'];
|
||||
$qty_requested = $items[$sku_requested];
|
||||
if ($qty_available >= $qty_requested)
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
|
||||
// return true or false
|
||||
return $result;
|
||||
}
|
||||
|
||||
// convert db distance to kilometers
|
||||
protected function distance($lat1, $lon1, $lat2, $lon2)
|
||||
{
|
||||
if (($lat1 == $lat2) && ($lon1 == $lon2))
|
||||
return 0;
|
||||
|
||||
$theta = $lon1 - $lon2;
|
||||
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
|
||||
$dist = acos($dist);
|
||||
$dist = rad2deg($dist);
|
||||
$miles = $dist * 60 * 1.1515;
|
||||
|
||||
return round(($miles * 1.609344), 1);
|
||||
}
|
||||
|
||||
protected function sendSMSMessage($hub, $items)
|
||||
{
|
||||
// compose message
|
||||
// get the skus for the message
|
||||
$sku_text = '';
|
||||
foreach ($items as $key => $value)
|
||||
{
|
||||
$sku_text .= ' ' . $key;
|
||||
}
|
||||
$message = str_replace('item_display', trim($sku_text), $this->trans->trans('no_inventory_message'));
|
||||
|
||||
// get hub notification number
|
||||
$mobile_number = $hub->getNotifNumber();
|
||||
|
||||
if (!empty($mobile_number))
|
||||
{
|
||||
// send SMS message
|
||||
error_log('sending sms to - ' . $mobile_number);
|
||||
$this->rt->sendSMS($mobile_number, 'MOTOLITE', $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +42,7 @@ use App\Ramcar\CustomerNotWaitReason;
|
|||
use App\Ramcar\NoTradeInReason;
|
||||
use App\Ramcar\WillingToWaitContent;
|
||||
use App\Ramcar\WarrantySource;
|
||||
use App\Ramcar\HubCriteria;
|
||||
|
||||
use App\Service\InvoiceGeneratorInterface;
|
||||
use App\Service\JobOrderHandlerInterface;
|
||||
|
|
@ -52,6 +53,9 @@ use App\Service\APNSClient;
|
|||
use App\Service\MapTools;
|
||||
use App\Service\RisingTideGateway;
|
||||
use App\Service\PromoLogger;
|
||||
use App\Service\HubSelector;
|
||||
use App\Service\HubDistributor;
|
||||
use App\Service\HubFilteringGeoChecker;
|
||||
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
||||
|
||||
|
|
@ -74,6 +78,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
protected $wh;
|
||||
protected $rt;
|
||||
protected $promo_logger;
|
||||
protected $hub_dist;
|
||||
protected $hub_geofence;
|
||||
|
||||
protected $template_hash;
|
||||
|
||||
|
|
@ -81,7 +87,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
InvoiceGeneratorInterface $ic, ValidatorInterface $validator,
|
||||
TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah,
|
||||
string $country_code, WarrantyHandler $wh, RisingTideGateway $rt,
|
||||
PromoLogger $promo_logger)
|
||||
PromoLogger $promo_logger, HubDistributor $hub_dist, HubFilteringGeoChecker $hub_geofence)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->ic = $ic;
|
||||
|
|
@ -93,6 +99,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
$this->wh = $wh;
|
||||
$this->rt = $rt;
|
||||
$this->promo_logger = $promo_logger;
|
||||
$this->hub_dist = $hub_dist;
|
||||
$this->hub_geofence = $hub_geofence;
|
||||
|
||||
$this->loadTemplates();
|
||||
}
|
||||
|
|
@ -493,7 +501,6 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
{
|
||||
foreach ($customer_tags as $customer_tag)
|
||||
{
|
||||
// TODO: not too comfy with this being hardcoded
|
||||
if ($customer_tag->getID() == $jo->getInvoice()->getUsedCustomerTagId())
|
||||
{
|
||||
// remove associated entity
|
||||
|
|
@ -799,6 +806,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
'event' => 'outlet_assign'
|
||||
];
|
||||
$mclient->sendEvent($obj, $payload);
|
||||
|
||||
// update redis hub jo count
|
||||
$this->hub_dist->incrementJoCountForHub($hub);
|
||||
}
|
||||
|
||||
return $error_array;
|
||||
|
|
@ -1170,6 +1180,9 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
$more_reason = $req->request->get('not_wait_notes');
|
||||
}
|
||||
|
||||
// get previously assigned hub, if any
|
||||
$old_hub = $obj->getHub();
|
||||
|
||||
if (empty($error_array))
|
||||
{
|
||||
// rider mqtt event
|
||||
|
|
@ -1243,6 +1256,13 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
'event' => 'outlet_assign'
|
||||
];
|
||||
$mclient->sendEvent($obj, $payload);
|
||||
|
||||
// update redis hub_jo_count for hub
|
||||
// decrement old hub's count and increment new hub's count
|
||||
if ($old_hub != null)
|
||||
$this->hub_dist->decrementJoCountForHub($old_hub);
|
||||
if ($hub != null)
|
||||
$this->hub_dist->incrementJoCountForHub($hub);
|
||||
}
|
||||
|
||||
return $error_array;
|
||||
|
|
@ -1664,6 +1684,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
return $params;
|
||||
}
|
||||
|
||||
// CMB code
|
||||
public function initializeOneStepForm()
|
||||
{
|
||||
$params['obj'] = new JobOrder();
|
||||
|
|
@ -1679,6 +1700,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
return $params;
|
||||
}
|
||||
|
||||
// CMB code
|
||||
public function initializeOneStepEditForm($id, $map_tools)
|
||||
{
|
||||
$em = $this->em;
|
||||
|
|
@ -1859,7 +1881,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
}
|
||||
|
||||
// initialize dispatch/processing job order form
|
||||
public function initializeProcessingForm($id, $map_tools, $motiv)
|
||||
public function initializeProcessingForm($id, HubSelector $hub_selector, $motiv)
|
||||
{
|
||||
$em = $this->em;
|
||||
|
||||
|
|
@ -1925,8 +1947,56 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
// get rejection reasons
|
||||
$params['rejection_reasons'] = JORejectionReason::getCollection();
|
||||
|
||||
$hub_criteria = new HubCriteria();
|
||||
|
||||
// get battery (if any)
|
||||
$skus = [];
|
||||
$items = [];
|
||||
$invoice = $obj->getInvoice();
|
||||
$inv_items = $invoice->getItems();
|
||||
foreach ($inv_items as $inv_item)
|
||||
{
|
||||
$batt = $inv_item->getBattery();
|
||||
if ($batt == null)
|
||||
continue;
|
||||
|
||||
$skus[] = $batt->getSapCode();
|
||||
$item_count = 1;
|
||||
if (!empty($batt->getSapCode()))
|
||||
{
|
||||
$sap_code = $batt->getSapCode();
|
||||
if (isset($items[$sap_code]))
|
||||
$items[$sap_code] = $item_count + 1;
|
||||
else
|
||||
$items[$sap_code] = $item_count;
|
||||
|
||||
$hub_criteria->addItem($sap_code, $item_count);
|
||||
}
|
||||
}
|
||||
|
||||
// get closest hubs
|
||||
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
|
||||
// set more hub criteria fields
|
||||
$long = $obj->getCoordinates()->getLongitude();
|
||||
$lat = $obj->getCoordinates()->getLatitude();
|
||||
|
||||
$hub_criteria->setPoint($obj->getCoordinates())
|
||||
->setLimitResults(50);
|
||||
|
||||
if ($this->hub_geofence->isCovered($long, $lat))
|
||||
{
|
||||
// if true, set other values for HubCriteria
|
||||
// error_log('Area is covered by hub filtering');
|
||||
$hub_criteria->setPaymentMethod($obj->getModeOfPayment())
|
||||
->setJoType($obj->getServiceType())
|
||||
->setRoundRobin(true);
|
||||
}
|
||||
|
||||
// check if emergency or not
|
||||
$willing_to_wait = $obj->getWillWait();
|
||||
if ($willing_to_wait == WillingToWaitContent::NOT_WILLING_TO_WAIT)
|
||||
$hub_criteria->setEmergency(true);
|
||||
|
||||
$hubs = $hub_selector->find($hub_criteria);
|
||||
|
||||
$params['hubs'] = [];
|
||||
|
||||
|
|
@ -2150,7 +2220,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
}
|
||||
|
||||
// initialize hub form
|
||||
public function initializeHubForm($id, $map_tools)
|
||||
public function initializeHubForm($id, HubSelector $hub_selector)
|
||||
{
|
||||
$em = $this->em;
|
||||
|
||||
|
|
@ -2174,8 +2244,56 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
// get rejection reasons
|
||||
$params['rejection_reasons'] = JORejectionReason::getCollection();
|
||||
|
||||
$hub_criteria = new HubCriteria();
|
||||
|
||||
// get battery (if any)
|
||||
$skus = [];
|
||||
$items = [];
|
||||
$invoice = $obj->getInvoice();
|
||||
$inv_items = $invoice->getItems();
|
||||
foreach ($inv_items as $inv_item)
|
||||
{
|
||||
$batt = $inv_item->getBattery();
|
||||
if ($batt == null)
|
||||
continue;
|
||||
|
||||
$skus[] = $batt->getSapCode();
|
||||
$item_count = 1;
|
||||
if (!empty($batt->getSapCode()))
|
||||
{
|
||||
$sap_code = $batt->getSapCode();
|
||||
if (isset($items[$sap_code]))
|
||||
$items[$sap_code] = $item_count + 1;
|
||||
else
|
||||
$items[$sap_code] = $item_count;
|
||||
}
|
||||
|
||||
$hub_criteria->addItem($sap_code, $item_count);
|
||||
}
|
||||
|
||||
// get closest hubs
|
||||
$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s"));
|
||||
// set more hub criteria fields
|
||||
$long = $obj->getCoordinates()->getLongitude();
|
||||
$lat = $obj->getCoordinates()->getLatitude();
|
||||
|
||||
$hub_criteria->setPoint($obj->getCoordinates())
|
||||
->setLimitResults(50);
|
||||
|
||||
if ($this->hub_geofence->isCovered($long, $lat))
|
||||
{
|
||||
// if true, set other values for HubCriteria
|
||||
// error_log('Area is covered by hub');
|
||||
$hub_criteria->setPaymentMethod($obj->getModeOfPayment())
|
||||
->setJoType($obj->getServiceType())
|
||||
->setRoundRobin(true);
|
||||
}
|
||||
|
||||
// check if emergency or not
|
||||
$willing_to_wait = $obj->getWillWait();
|
||||
if ($willing_to_wait == WillingToWaitContent::NOT_WILLING_TO_WAIT)
|
||||
$hub_criteria->setEmergency(true);
|
||||
|
||||
$hubs = $hub_selector->find($hub_criteria);
|
||||
|
||||
$params['status_cancelled'] = JOStatus::CANCELLED;
|
||||
$params['hubs'] = [];
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||
use App\Service\MQTTClient;
|
||||
use App\Service\APNSClient;
|
||||
use App\Service\MapTools;
|
||||
use App\Service\HubSelector;
|
||||
|
||||
use App\Entity\JobOrder;
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ interface JobOrderHandlerInterface
|
|||
public function initializeAllForm(int $id);
|
||||
|
||||
// initialize dispatch/processing job order form
|
||||
public function initializeProcessingForm(int $id, MapTools $map_tools, $motiv);
|
||||
public function initializeProcessingForm(int $id, HubSelector $hub_selector, $motiv);
|
||||
|
||||
// initialize assign job order form
|
||||
public function initializeAssignForm(int $id);
|
||||
|
|
@ -76,7 +77,7 @@ interface JobOrderHandlerInterface
|
|||
public function initializeFulfillmentForm(int $id);
|
||||
|
||||
// initialize hub form
|
||||
public function initializeHubForm(int $id, MapTools $map_tools);
|
||||
public function initializeHubForm(int $id, HubSelector $hub_selector);
|
||||
|
||||
// initialize rider form
|
||||
public function initializeRiderForm(int $id);
|
||||
|
|
|
|||
|
|
@ -83,4 +83,28 @@ class RisingTideGateway
|
|||
|
||||
error_log($result);
|
||||
}
|
||||
|
||||
public function validatePhoneNumber($mobile)
|
||||
{
|
||||
// check valid number
|
||||
$num = trim($mobile);
|
||||
|
||||
// should be 10 digits
|
||||
if (strlen($num) != 10)
|
||||
return false;
|
||||
|
||||
// should start with '9'
|
||||
if ($num[0] != '9')
|
||||
return false;
|
||||
|
||||
// should be numeric
|
||||
if (!is_numeric($num))
|
||||
return false;
|
||||
|
||||
// should not be 9900000000
|
||||
if ($num == '9900000000')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,18 @@
|
|||
<input type="text" name="branch_code" class="form-control m-input" value="{{ obj.getBranchCode() }}">
|
||||
<div class="form-control-feedback hide" data-field="branch_code"></div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<label for="notif_number" data-field="notif_number">
|
||||
Notification Number
|
||||
</label>
|
||||
<div class="input-group m-input-group">
|
||||
<span class="input-group-addon">{% trans %}country_code_prefix{% endtrans %}</span>
|
||||
<input type="text" name="notif_number" class="form-control m-input" value="{{ obj.getNotifNumber|default('') }}" data-name="notif_number">
|
||||
<div class="form-control-feedback hide" data-field="notif_number"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row no-border">
|
||||
<div class="col-lg-3">
|
||||
<label for="rider_slots" data-field="rider_slots">
|
||||
Number of Riders Per Slot
|
||||
|
|
@ -142,6 +154,22 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row no-border">
|
||||
<div class="col-lg-6">
|
||||
<label data-field="payment_method">Payment Methods</label>
|
||||
<div class="m-checkbox-list">
|
||||
{% for key, value in payment_methods %}
|
||||
<label class="m-checkbox">
|
||||
<input type="checkbox" name="payment_methods[]" value="{{ key }}"{{ key in obj.getPaymentMethods ? ' checked' : '' }}>
|
||||
{{ value }}
|
||||
<span></span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="form-control-feedback hide" data-field="payment_methods"></div>
|
||||
<span class="m-form__help">Check all payment methods that apply</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group m-form__group row">
|
||||
<div class="col-lg-12">
|
||||
<label>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ add_cust_vehicle_battery_info: This vehicle is using a Motolite battery
|
|||
jo_title_pdf: Motolite Res-Q Job Order
|
||||
country_code_prefix: '+63'
|
||||
delivery_instructions_label: Delivery Instructions
|
||||
no_inventory_message: No stock for [item_display]
|
||||
|
||||
# images
|
||||
image_logo_login: /assets/images/logo-resq.png
|
||||
|
|
|
|||
Loading…
Reference in a new issue