diff --git a/.env.dist b/.env.dist index 30f9a925..b6766d67 100644 --- a/.env.dist +++ b/.env.dist @@ -57,3 +57,12 @@ COUNTRY_CODE=+insert_country_code_here # dashboard DASHBOARD_ENABLE=set_to_true_or_false + +# auth token for Inventory API +INVENTORY_API_URL=insert_api_url_here +INVENTORY_API_OCP=insert_ocp_text_here +INVENTORY_API_AUTH_TOKEN_PREFIX=Bearer +INVENTORY_API_AUTH_TOKEN=insert_auth_token_here + +# API logging +API_LOGGING=set_to_true_or_false diff --git a/config/acl.yaml b/config/acl.yaml index c6ccc243..bfd6c6cc 100644 --- a/config/acl.yaml +++ b/config/acl.yaml @@ -264,6 +264,8 @@ access_keys: label: Walk-in - id: jo_walkin.edit label: Walk-in Edit + - id: jo_autoassign.test + label: Autoassign Test - id: support label: Customer Support Access diff --git a/config/menu.yaml b/config/menu.yaml index b0096cf5..45ceab40 100644 --- a/config/menu.yaml +++ b/config/menu.yaml @@ -122,6 +122,10 @@ main_menu: acl: jo_all.list label: View All parent: joborder + - id: jo_autoassign + acl: jo_autoassign.test + label: Autoassign Test + parent: joborder - id: support acl: support.menu diff --git a/config/resq.services.yaml b/config/resq.services.yaml index 1756cf98..0c927f98 100644 --- a/config/resq.services.yaml +++ b/config/resq.services.yaml @@ -226,3 +226,11 @@ services: $redis_prov: "@App\\Service\\RedisClientProvider" $loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%" $status_key: "%env(STATUS_RIDER_KEY)%" + + # inventory manager + App\Service\InventoryManager: + arguments: + $api_url: "%env(INVENTORY_API_URL)%" + $api_ocp_key: "%env(INVENTORY_API_OCP)%" + $api_auth_prefix: "%env(INVENTORY_API_AUTH_TOKEN_PREFIX)%" + $api_auth_token: "%env(INVENTORY_API_AUTH_TOKEN)%" diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index d5cd8dfc..f239402d 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -226,3 +226,12 @@ jo_walkin_edit_submit: controller: App\Controller\JobOrderController::walkInEditSubmit methods: [POST] +jo_autoassign: + path: /job-order/autoassign + controller: App\Controller\JobOrderController::autoAssignForm + methods: [GET] + +jo_autoassign_test_submit: + path: /job-order/autoassign + controller: App\Controller\JobOrderController::autoAssignSubmit + methods: [POST] diff --git a/config/services.yaml b/config/services.yaml index 1756cf98..4bfaf95a 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -226,3 +226,16 @@ services: $redis_prov: "@App\\Service\\RedisClientProvider" $loc_key: "%env(LOCATION_RIDER_ACTIVE_KEY)%" $status_key: "%env(STATUS_RIDER_KEY)%" + + # inventory manager + App\Service\InventoryManager: + arguments: + $api_url: "%env(INVENTORY_API_URL)%" + $api_ocp_key: "%env(INVENTORY_API_OCP)%" + $api_auth_prefix: "%env(INVENTORY_API_AUTH_TOKEN_PREFIX)%" + $api_auth_token: "%env(INVENTORY_API_AUTH_TOKEN)%" + + # API logging + App\EventSubscriber\LogSubscriber: + arguments: + $api_log_flag: "%env(API_LOGGING)%" diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 9765ad8f..038ac73b 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -29,6 +29,9 @@ use App\Service\RisingTideGateway; use App\Service\MQTTClient; use App\Service\GeofenceTracker; use App\Service\RiderTracker; +use App\Service\MapTools; +use App\Service\InventoryManager; +use App\Service\RiderAssignmentHandlerInterface; use App\Entity\MobileSession; use App\Entity\Customer; @@ -45,12 +48,13 @@ use App\Entity\Service; use App\Entity\Partner; use App\Entity\Review; use App\Entity\PrivacyPolicy; +use App\Entity\Hub; use DateTime; use Exception; // mobile API -class APIController extends Controller +class APIController extends Controller implements LoggedController { protected $session; @@ -817,7 +821,9 @@ class APIController extends Controller return $res->getReturnResponse(); } - public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo) + public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo, + MapTools $map_tools, InventoryManager $im, MQTTClient $mclient, + RiderAssignmentHandlerInterface $rah) { // check required parameters and api key $required_params = [ @@ -982,16 +988,86 @@ class APIController extends Controller $invoice = $ic->generateInvoice($icrit); $jo->setInvoice($invoice); + // assign hub and rider + if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) || + ($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) + { + // get nearest hub + $nearest_hub = $this->findNearestHubWithInventory($jo, $batt, $em, $map_tools, $im); + } + else + { + $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); + } + + if (!empty($nearest_hub)) + { + // assign rider + $available_riders = $nearest_hub->getAvailableRiders(); + if (count($available_riders) > 0) + { + $assigned_rider = null; + 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) + { + $riders[] = $rider; + } + + $assigned_rider = $this->randomizeRider($riders); + } + else + $assigned_rider = $available_riders[0]; + + $jo->setHub($nearest_hub); + $jo->setRider($assigned_rider); + $jo->setStatus(JOStatus::ASSIGNED); + + $assigned_rider->setAvailable(false); + } + } + $em->persist($jo); $em->persist($invoice); - // add event log + // add event log for JO $event = new JOEvent(); $event->setDateHappen(new DateTime()) ->setTypeID(JOEventType::CREATE) ->setJobOrder($jo); $em->persist($event); + // check JO status + if ($jo->getStatus() == JOStatus::ASSIGNED) + { + // add event logs for hub and rider assignments + $hub_assign_event = new JOEvent(); + $hub_assign_event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::HUB_ASSIGN) + ->setJobOrder($jo); + + $em->persist($hub_assign_event); + + $rider_assign_event = new JOEvent(); + $rider_assign_event->setDateHappen(new DateTime()) + ->setTypeID(JOEventType::RIDER_ASSIGN) + ->setJobOrder($jo); + + $em->persist($rider_assign_event); + + // user mqtt event + $payload = [ + 'event' => 'outlet_assign' + ]; + $mclient->sendEvent($jo, $payload); + + $rah->assignJobOrder($jo, $jo->getRider()); + } + $em->flush(); // make invoice json data @@ -2213,4 +2289,152 @@ class APIController extends Controller return $cust; } + protected function findNearestHub($jo, EntityManagerInterface $em, + MapTools $map_tools) + { + // get the nearest 10 hubs + $selected_hub = null; + $hubs = $map_tools->getClosestOpenHubs($jo->getCoordinates(), 10, date("H:i:s")); + + $nearest_hubs_with_distance = []; + $nearest_branch_codes = []; + foreach ($hubs as $hub) + { + $nearest_hubs_with_distance[] = $hub; + //if (!empty($hub['hub']->getBranchCode())) + // $nearest_branch_codes[] = $hub['hub']->getBranchCode(); + } + + // check if nearest hubs have branch codes + //if (count($nearest_branch_codes) == 0) + // return $selected_hub; + + // assume all 10 have stock + // find the nearest hub with available riders + $nearest = null; + foreach ($nearest_hubs_with_distance as $nhd) + { + if (count($nhd['hub']->getAvailableRiders()) > 0) + { + if (empty($nearest)) + $nearest = $nhd; + else + { + if ($nhd['distance'] < $nearest['distance']) + $nearest = $nhd; + } + } + } + + $selected_hub = $nearest['hub']; + + return $selected_hub; + } + + protected function findNearestHubWithInventory($jo, Battery $batt, EntityManagerInterface $em, + MapTools $map_tools, InventoryManager $im) + { + // get the nearest 10 hubs + $selected_hub = null; + $hubs = $map_tools->getClosestOpenHubs($jo->getCoordinates(), 10, date("H:i:s")); + + $nearest_hubs_with_distance = []; + $nearest_branch_codes = []; + foreach ($hubs as $hub) + { + $nearest_hubs_with_distance[] = $hub; + //if (!empty($hub['hub']->getBranchCode())) + // $nearest_branch_codes[] = $hub['hub']->getBranchCode(); + } + + // check if nearest hubs have branch codes + //if (count($nearest_branch_codes) == 0) + // return $selected_hub; + + // assume all 10 have stock + // find the nearest hub with available riders + $nearest = null; + foreach ($nearest_hubs_with_distance as $nhd) + { + if (count($nhd['hub']->getAvailableRiders()) > 0) + { + if (empty($nearest)) + $nearest = $nhd; + else + { + if ($nhd['distance'] < $nearest['distance']) + $nearest = $nhd; + } + } + } + + $selected_hub = $nearest['hub']; + + // uncomment this snippet when inventory check becomes active + // get battery sku + /* + if ($batt != null) + { + $skus[] = $batt->getSAPCode(); + + // api call to check inventory + // pass the list of branch codes of nearest hubs and the skus + // go through returned list of branch codes + // bypass inventory check for now + // $hubs_with_inventory = $im->getBranchesInventory($nearest_branch_codes, $skus); + if (!empty($hubs_with_inventory)) + { + $nearest = []; + $flag_hub_found = false; + foreach ($hubs_with_inventory as $hub_with_inventory) + { + // find hub according to branch code + $found_hub = $em->getRepository(Hub::class)->findOneBy(['branch_code' => $hub_with_inventory['BranchCode']]); + if ($found_hub != null) + { + // check rider availability + if (count($found_hub->getAvailableRiders()) > 0) + { + // check against nearest hubs with distance + foreach ($nearest_hubs_with_distance as $nhd) + { + // get distance of hub from location, compare with $nearest. if less, replace nearest + if ($found_hub->getID() == $nhd['hub']->getID()) + { + if (empty($nearest)) + { + $nearest = $nhd; + $flag_hub_found = true; + } + else + { + if ($nhd['distance'] < $nearest['distance']) + { + $nearest = $nhd; + $flag_hub_found = true; + } + } + } + } + } + } + } + $selected_hub = $nearest['hub']; + } + } */ + return $selected_hub; + } + + protected function randomizeRider($riders) + { + // TODO: get redis to track the sales per rider per day + // check the time they came in + // for now, randomize the rider + $selected_index = array_rand($riders); + + $selected_rider = $riders[$selected_index]; + + return $selected_rider; + } + } diff --git a/src/Controller/CustomerController.php b/src/Controller/CustomerController.php index 9b62df8c..fd9417cc 100644 --- a/src/Controller/CustomerController.php +++ b/src/Controller/CustomerController.php @@ -181,11 +181,15 @@ class CustomerController extends Controller public function getCustomerVehicles(Request $req, CustomerHandlerInterface $cust_handler) { + /* + // TODO: fix if ((!$this->isGranted('jo_onestep.form')) || - (!$this->isGranted('jo_walkin.form'))) { + (!$this->isGranted('jo_walkin.form')) || + (!$this->isGranted('jo_in.list'))) { $exception = $this->createAccessDeniedException('No access.'); throw $exception; } + */ $results = $cust_handler->getCustomerVehicles($req); diff --git a/src/Controller/HubController.php b/src/Controller/HubController.php index e1d41525..d6334c80 100644 --- a/src/Controller/HubController.php +++ b/src/Controller/HubController.php @@ -150,7 +150,9 @@ class HubController extends Controller ->setContactNumbers($req->request->get('contact_nums')) ->setTimeOpen($time_open) ->setTimeClose($time_close) - ->setCoordinates($point); + ->setCoordinates($point) + ->setBranchCode($req->request->get('branch_code', '')) + ->setStatusOpen($req->request->get('status_open') ?? false); } protected function setQueryFilters($datatable, QueryBuilder $query) diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 1d1d84c1..c92de36a 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -5,6 +5,7 @@ namespace App\Controller; use App\Ramcar\JOStatus; use App\Ramcar\InvoiceCriteria; use App\Ramcar\CMBServiceType; +use App\Ramcar\ServiceType; use App\Entity\CustomerVehicle; use App\Entity\Promo; @@ -20,6 +21,7 @@ use App\Service\GISManagerInterface; use App\Service\MapTools; use App\Service\MQTTClient; use App\Service\APNSClient; +use App\Service\InventoryManager; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -96,7 +98,9 @@ class JobOrderController extends Controller $this->denyAccessUnlessGranted('jo_open.edit', null, 'No access.'); $error_array = []; - $error_array = $jo_handler->generateJobOrder($req, $id); + $result = $jo_handler->generateJobOrder($req, $id); + + $error_array = $result['error_array']; // check if any errors were found if (!empty($error_array)) { @@ -145,7 +149,9 @@ class JobOrderController extends Controller // initialize error list $error_array = []; $id = -1; - $error_array = $jo_handler->generateJobOrder($req, $id); + $result = $jo_handler->generateJobOrder($req, $id); + + $error_array = $result['error_array']; // check if any errors were found if (!empty($error_array)) { @@ -1053,5 +1059,177 @@ class JobOrderController extends Controller ]); } + /** + * @Menu(selected="jo_autoassign") + */ + public function autoAssignForm(GISManagerInterface $gis, JobOrderHandlerInterface $jo_handler) + { + $this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.'); + + $params = $jo_handler->initializeIncomingForm(); + + $params['submit_url'] = $this->generateUrl('jo_autoassign_test_submit'); + $params['return_url'] = $this->generateUrl('jo_autoassign'); + $params['map_js_file'] = $gis->getJSJOFile(); + + $template = 'job-order/autoassign.form.html.twig'; + + // response + return $this->render($template, $params); + } + + public function autoAssignSubmit(Request $req, JobOrderHandlerInterface $jo_handler, + EntityManagerInterface $em, MapTools $map_tools, + InventoryManager $im) + { + $this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.'); + + // initialize error list + $error_array = []; + $id = -1; + $result = $jo_handler->generateJobOrder($req, $id); + + $error_array = $result['error_array']; + + // check if any errors were found + if (!empty($error_array)) { + // return validation failure response + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 422); + } + + // get job order + $jo = $result['job_order']; + + if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) || + ($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) + $this->autoAssignHubAndRider($jo, $em, $map_tools, $im); + + // return successful response + return $this->json([ + 'success' => 'Changes have been saved!' + ]); + + } + + protected function autoAssignHubAndRider($jo, EntityManagerInterface $em, + MapTools $map_tools, InventoryManager $im) + { + // get the nearest 10 hubs + // TODO: move this snippet to a function + $hubs = $map_tools->getClosestHubs($jo->getCoordinates(), 10, date("H:i:s")); + + $nearest_hubs = []; + $nearest_hubs_with_distance = []; + + foreach ($hubs as $hub) + { + $nearest_hubs_with_distance[] = $hub; + // TODO: uncomment this when we have branch codes in data + // and when they have real codes and not test ones + //$nearest_branch_codes[] = $hub['hub']->getBranchCode(); + $nearest_branch_codes = ['WestAve','jay_franchise']; + } + + // get battery sku + $invoice = $jo->getInvoice(); + if ($invoice != null) + { + $items = $invoice->getItems(); + $skus = []; + foreach ($items as $item) + { + // TODO: uncomment this when they have real codes and not test ones + //$skus[] = $item->getBattery()->getSAPCode(); + $skus[] = 'WMGD31EL-CPNM0-L'; + } + + // api call to check inventory + // pass the list of branch codes of nearest hubs and the skus + // go through returned list of branch codes + $hubs_with_inventory = $im->getBranchesInventory($nearest_branch_codes, $skus); + if (!empty($hubs_with_inventory)) + { + $nearest = []; + $flag_hub_found = false; + foreach ($hubs_with_inventory as $hub_with_inventory) + { + // find hub according to branch code + $found_hub = $em->getRepository(Hub::class)->findOneBy(['branch_code' => $hub_with_inventory['BranchCode']]); + if ($found_hub != null) + { + // check rider availability + if (count($found_hub->getAvailableRiders()) > 0) + { + // check against nearest hubs with distance + foreach ($nearest_hubs_with_distance as $nhd) + { + // get distance of hub from location, compare with $nearest. if less, replace nearest + if ($found_hub->getID() == $nhd['hub']->getID()) + { + if (empty($nearest)) + { + $nearest = $nhd; + $flag_hub_found = true; + } + else + { + if ($nhd['distance'] < $nearest['distance']) + { + $nearest = $nhd; + $flag_hub_found = true; + } + } + } + } + } + } + } + + if ($flag_hub_found) + { + $jo->setHub($nearest['hub']); + + $hub_riders = $nearest['hub']->getAvailableRiders(); + $rider = null; + if (count($hub_riders) > 1) + { + // TODO: this will no longer be necessary when the contents + // of randomizeRider changes + $available_riders = []; + foreach ($hub_riders as $rider) + { + $available_riders[] = $rider; + } + + $rider = $this->randomizeRider($available_riders); + } + else + $rider = $hub_riders[0]; + + $jo->setRider($rider); + + $jo->setStatus(JOStatus::ASSIGNED); + + $em->persist($jo); + $em->flush(); + } + } + } + } + + protected function randomizeRider($riders) + { + // TODO: get redis to track the sales per rider per day + // check the time they came in + // for now, randomize the rider + $selected_index = array_rand($riders); + + $selected_rider = $riders[$selected_index]; + + return $selected_rider; + } } diff --git a/src/Controller/LoggedController.php b/src/Controller/LoggedController.php new file mode 100644 index 00000000..00e7c02a --- /dev/null +++ b/src/Controller/LoggedController.php @@ -0,0 +1,7 @@ +time_open = new DateTime(); $this->time_close = new DateTime(); $this->riders = new ArrayCollection(); $this->outlets = new ArrayCollection(); + $this->status_open = true; } public function getRiders() @@ -114,4 +127,27 @@ class Hub { return $this->outlets; } + + public function setBranchCode($branch_code) + { + $this->branch_code = $branch_code; + return $this; + } + + public function getBranchCode() + { + return $this->branch_code; + } + + public function setStatusOpen($status = true) + { + $this->status_open = $status; + return $this; + } + + public function isStatusOpen() + { + return $this->status_open; + } + } diff --git a/src/EventSubscriber/LogSubscriber.php b/src/EventSubscriber/LogSubscriber.php new file mode 100644 index 00000000..1f62f577 --- /dev/null +++ b/src/EventSubscriber/LogSubscriber.php @@ -0,0 +1,72 @@ +api_log_flag = $api_log_flag; + } + + public function onKernelController(ControllerEvent $event) + { + if ($this->api_log_flag == 'false') + return; + + $controller = $event->getController(); + $this->allow = false; + + // when a controller class defines multiple action methods, the controller + // is returned as [$controllerInstance, 'methodName'] + if (is_array($controller)) + $controller = $controller[0]; + + if (!($controller instanceof LoggedController)) + return; + + $this->allow = true; + + $req = $event->getRequest(); + $reqdata = [ + $req->getPathInfo(), + $req->getMethod(), + $req->query->all(), + $req->request->all(), + ]; + error_log(print_r($reqdata, true)); + } + + public function onKernelResponse(ResponseEvent $event) + { + if ($this->api_log_flag == 'false') + return; + + if (!$this->allow) + return; + + $resp = $event->getResponse(); + + $content = $resp->getContent(); + + error_log(print_r($content, true)); + } + + public static function getSubscribedEvents() + { + return [ + KernelEvents::CONTROLLER => 'onKernelController', + KernelEvents::RESPONSE => 'onKernelResponse', + ]; + } +} diff --git a/src/Service/InventoryManager.php b/src/Service/InventoryManager.php new file mode 100644 index 00000000..4dc5a8b1 --- /dev/null +++ b/src/Service/InventoryManager.php @@ -0,0 +1,80 @@ +api_url = $api_url; + $this->api_ocp_key = $api_ocp_key; + $this->api_auth_prefix = $api_auth_prefix; + $this->api_auth_token = $api_auth_token; + } + + public function getBranchesInventory($nearest_branch_codes, $skus) + { + // api call to check inventory + // pass the list of branch codes and the skus + $data = [ + "BranchCodes" => $nearest_branch_codes, + "Skus" => $skus, + ]; + + $json_data = json_encode($data); + error_log('JSON ' . $json_data); + + // initializes a new cURL session + $curl = curl_init($this->api_url); + + // Set the CURLOPT_RETURNTRANSFER option to true + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + + // Set the CURLOPT_POST option to true for POST request + curl_setopt($curl, CURLOPT_POST, true); + + // Set the request data as JSON using json_encode function + curl_setopt($curl, CURLOPT_POSTFIELDS, $json_data); + + // set timeout + curl_setopt($curl, CURLOPT_TIMEOUT, 300); + + $authorization = $this->api_auth_prefix . ' ' . $this->api_auth_token; + $ocp = $this->api_ocp_key; + + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Authorization: ' . $authorization, + 'Content-Type: application/json', + 'Ocp-Apim-Subscription-Key: ' . $ocp, + ]); + + $response = curl_exec($curl); + + // close cURL session + curl_close($curl); + + // response is array of these + // { + // "Id": 37, + // "BranchCode": "WestAve", + // "BranchName": "West ave. Branch", + // "BranchRole": 0, + // "Name": "3SMF / GOLD ", + // "SapCode": "WMGD31EL-CPNM0-L", + // "Quantity": 38 + // } + + // check if the response is empty + $results = []; + if (!empty($response)) + $results = json_decode($response, true); + + return $results; + } + +} diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index a12e09d5..deeea114 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -405,7 +405,14 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface } } - return $error_array; + $data['error_array'] = $error_array; + + if ($jo != null) + { + $data['job_order'] = $jo; + } + + return $data; } // dispatch job order diff --git a/src/Service/MapTools.php b/src/Service/MapTools.php index 6aa5848c..17511fba 100644 --- a/src/Service/MapTools.php +++ b/src/Service/MapTools.php @@ -148,6 +148,52 @@ class MapTools return $final_data; */ } + + public function getClosestOpenHubs(Point $point, $limit, $time = false) + { + // get closest hubs based on st_distance function from db + $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE h.status_open = true AND :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist') + ->setParameter('lat', $point->getLatitude()) + ->setParameter('lng', $point->getLongitude()); + + if ($time) { + $query->setParameter('time', $time); + } + + $query->setMaxResults($limit); + + // error_log($query->getSql()); + $result = $query->getResult(); + + $hubs = []; + $final_data = []; + foreach ($result as $row) + { + //error_log($row[0]->getName() . ' - ' . $row['dist']); + $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); + + $final_data[] = [ + 'hub' => $row[0], + 'db_distance' => $row['dist'], + 'distance' => $dist, + 'duration' => 0, + ]; + } + + return $final_data; + } protected function distance($lat1, $lon1, $lat2, $lon2) { diff --git a/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php b/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php index b5bed63b..3c3ede6c 100644 --- a/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php +++ b/src/Service/RiderAPIHandler/ResqRiderAPIHandler.php @@ -483,7 +483,9 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface return $data; } - // TODO: tag rider as available + // tag rider as available + $rider = $this->session->getRider(); + $rider->setAvailable(true); $this->em->flush(); @@ -515,7 +517,8 @@ class ResqRiderAPIHandler implements RiderAPIHandlerInterface ->setRider($rider); $this->em->persist($event); - // TODO: tag rider as unavailable + // tag rider as unavailable + $rider->setAvailable(false); // save to customer vehicle battery record $this->jo_handler->updateVehicleBattery($jo); diff --git a/templates/hub/form.html.twig b/templates/hub/form.html.twig index df8a7190..aed63021 100644 --- a/templates/hub/form.html.twig +++ b/templates/hub/form.html.twig @@ -82,6 +82,24 @@
+
+
+ + + +
+
+ + + +
+