From 09d04a8a7ef9ff071bd632491ebeee4498a94e1d Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 10 Mar 2021 08:27:23 +0000 Subject: [PATCH 01/29] Add hub criteria object. #543 --- src/Ramcar/HubCriteria.php | 103 +++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/Ramcar/HubCriteria.php diff --git a/src/Ramcar/HubCriteria.php b/src/Ramcar/HubCriteria.php new file mode 100644 index 00000000..bc695dce --- /dev/null +++ b/src/Ramcar/HubCriteria.php @@ -0,0 +1,103 @@ +has_inventory = false; + $this->items = []; + } + + 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 setHasInventory($has_inventory = true) + { + $this->has_inventory = $has_inventory; + return $this; + } + + public function hasInventory() + { + return $this->has_inventory; + } + + 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 setDayTime(DateTime $day_time) + { + $this->day_time = $day_time; + return $this; + } + + public function getDayTime() + { + return $this->day_time; + } + + public function addItem($id, $quantity) + { + // at this point, id is assumed to be a valid item + $this->items[$id] = $quantity; + return $this; + } + + public function getItems() + { + return $this->items; + } +} From 4efef6d397399ffa6f41fffccaaef82949d180ad Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 10 Mar 2021 10:49:31 +0000 Subject: [PATCH 02/29] Add HubSelector service. #543 --- config/services.yaml | 4 + src/Controller/APIController.php | 2 + src/Service/HubSelector.php | 123 +++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 src/Service/HubSelector.php diff --git a/config/services.yaml b/config/services.yaml index 75c83d1d..8f05c28b 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -266,3 +266,7 @@ services: event: 'postPersist' entity: 'App\Entity\CustomerVehicle' + # hub service + App\Service\HubSelector: + arguments: + $em: "@doctrine.orm.entity_manager" diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 94e9fb38..8f268309 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -1011,12 +1011,14 @@ class APIController extends Controller implements LoggedController if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) || ($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) { + // TODO: call HubSelector service here // get nearest hub // $nearest_hub = $this->findNearestHubWithInventory($jo, $batt, $em, $map_tools, $im); $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); } else { + // TODO: call HubSelector service here $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); } diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php new file mode 100644 index 00000000..cf0d37a7 --- /dev/null +++ b/src/Service/HubSelector.php @@ -0,0 +1,123 @@ +em = $em; + } + + public function find(HubCriteria $criteria) + { + $point = $criteria->getPoint(); + $limit_results = $criteria->getLimitResults(); + $limit_distance = $criteria->getLimitDistance(); + $jo_type = $criteria->getJoType(); + $has_inventory = $criteria->hasInventory(); + $items = $criteria->getItems(); + $day_time = $criteria->getDayTime(); + + // check for jo type + if (($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW)) || + ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) + { + // check if we need to get inventory + if ($has_inventory) + { + if ($day_time != null) + { + // call function for jo type, inventory == true, and check for day and time + } + else + { + // call function for jo type and inventory == true + } + } + else + { + if ($day_time != null) + { + // call function for jo type and check for day and time + } + else + { + // call function for jo type only + } + } + } + + // TODO: this needs to go to a function.. somewhere + // 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'; + + $query_string .= ' ORDER BY dist'; + + $query = $this->em->createQuery($query_string) + ->setParameter('lat', $point->getLatitude()) + ->setParameter('lng', $point->getLongitude()); + + $query->setMaxResults($limit); + + // error_log($query->getSql()); + $result = $query->getResult(); + + $hubs = []; + $final_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) + { + $final_data[] = [ + 'hub' => $row[0], + 'db_distance' => $row['dist'], + 'distance' => $dist, + 'duration' => 0, + ]; + } + } + + return $final_data; + } + + // 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); + } +} From 156742ea3a5a3b5e24caf57f045754c5eb3f7e27 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 11 Mar 2021 09:56:07 +0000 Subject: [PATCH 03/29] Add functions for the queries in HubSelector. #543 --- src/Ramcar/HubCriteria.php | 10 +- src/Service/HubSelector.php | 202 ++++++++++++++++++++++++++++++++++-- 2 files changed, 196 insertions(+), 16 deletions(-) diff --git a/src/Ramcar/HubCriteria.php b/src/Ramcar/HubCriteria.php index bc695dce..cb42ce04 100644 --- a/src/Ramcar/HubCriteria.php +++ b/src/Ramcar/HubCriteria.php @@ -13,7 +13,7 @@ class HubCriteria protected $limit_distance; // distance limit for search in km protected $has_inventory; // flag if we need to check for inventory protected $jo_type; // jo service needed - protected $day_time; // day and time to check if hub is open or not + protected $date_time; // date and time to check if hub is open or not protected $items; // array of items: items[id] = quantity to check for and has_inventory is true public function __construct() @@ -78,15 +78,15 @@ class HubCriteria return $this->jo_type; } - public function setDayTime(DateTime $day_time) + public function setDateTime(DateTime $date_time) { - $this->day_time = $day_time; + $this->date_time = $date_time; return $this; } - public function getDayTime() + public function getDateTime() { - return $this->day_time; + return $this->date_time; } public function addItem($id, $quantity) diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index cf0d37a7..a2f5d53f 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -28,18 +28,20 @@ class HubSelector $jo_type = $criteria->getJoType(); $has_inventory = $criteria->hasInventory(); $items = $criteria->getItems(); - $day_time = $criteria->getDayTime(); + $date_time = $criteria->getDateTime(); + + $results = []; // check for jo type - if (($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW)) || + if (($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW) || ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) { // check if we need to get inventory if ($has_inventory) { - if ($day_time != null) + if ($date_time != null) { - // call function for jo type, inventory == true, and check for day and time + // call function for jo type, inventory == true, and check for date and time } else { @@ -48,28 +50,206 @@ class HubSelector } else { - if ($day_time != null) + if ($date_time != null) { - // call function for jo type and check for day and time + // call function for jo type and check for date and time + $results = $this->getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time); } else { // call function for jo type only + $results = $this->getClosestHubsWithJoType($point, $limit_results, $limit_distance, $jo_type); } } } + else + { + // no need to check for items and inventory. + // check for date and time + if ($date_time != null) + { + // call function that gets hubs with opening times + $results = $this->getClosestHubsWithTime($point, $limit_results, $limit_distance, $date_time); + } + else + { + // call default function that just gets the hubs within distance limit + // and number of results + $results = $this->getClosestHubs($point, $limit_results, $limit_distance); + } + } - // TODO: this needs to go to a function.. somewhere - // 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'; + return $results; + } - $query_string .= ' ORDER BY dist'; + protected function getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time) + { + // get closest hubs that are open at the given time offering jo_type service 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist') $query = $this->em->createQuery($query_string) ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); - $query->setMaxResults($limit); + // add the jo_type/service parameter + + // have to add date and time to query + // right now, hub only has opening times + // so we extract the time from date_time + $time = $date_time->format("H:i:s"); + if ($time) { + $query->setParameter('time', $time); + } + + $query->setMaxResults($limit_results); + + // error_log($query->getSql()); + $result = $query->getResult(); + + $hubs = []; + $final_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) + { + $final_data[] = [ + 'hub' => $row[0], + 'db_distance' => $row['dist'], + 'distance' => $dist, + 'duration' => 0, + ]; + } + } + + return $final_data; + } + + protected function getClosestHubsWithJoType($point, $limit_results, $limit_distance, $jo_type) + { + // get closest hubs offering jo_type service 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()); + + // add the jo type/service parameter here + + $query->setMaxResults($limit_results); + + // error_log($query->getSql()); + $result = $query->getResult(); + + $hubs = []; + $final_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) + { + $final_data[] = [ + 'hub' => $row[0], + 'db_distance' => $row['dist'], + 'distance' => $dist, + 'duration' => 0, + ]; + } + } + + return $final_data; + } + + protected function getClosestHubsWithTime(Point $point, $limit_results, $limit_distance, $date_time) + { + // get closest hubs that are open at the given time 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist') + + $query = $this->em->createQuery($query_string) + ->setParameter('lat', $point->getLatitude()) + ->setParameter('lng', $point->getLongitude()); + + // have to add date and time to query + // right now, hub only has opening times + // so we extract the time from date_time + $time = $date_time->format("H:i:s"); + if ($time) { + $query->setParameter('time', $time); + } + + $query->setMaxResults($limit_results); + + // error_log($query->getSql()); + $result = $query->getResult(); + + $hubs = []; + $final_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) + { + $final_data[] = [ + 'hub' => $row[0], + 'db_distance' => $row['dist'], + 'distance' => $dist, + 'duration' => 0, + ]; + } + } + + return $final_data; + } + + protected function getClosestHubs(Point $point, $limit_results, $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()); + + $query->setMaxResults($limit_results); // error_log($query->getSql()); $result = $query->getResult(); From 9a6ca7ae5d3c6a3cc1dade04a88ff4fd328c26ca Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 12 Mar 2021 06:54:09 +0000 Subject: [PATCH 04/29] Add inventory manager service to HubSelector. #543 --- config/services.yaml | 1 + src/Service/HubSelector.php | 138 ++++++++++++++++++++++++++++++++++-- 2 files changed, 132 insertions(+), 7 deletions(-) diff --git a/config/services.yaml b/config/services.yaml index 8f05c28b..4fb5f088 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -270,3 +270,4 @@ services: App\Service\HubSelector: arguments: $em: "@doctrine.orm.entity_manager" + $im: "@App\\Service\\InventoryManager" diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index a2f5d53f..6773f0d8 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -8,6 +8,8 @@ use CrEOF\Spatial\PHP\Types\Geometry\Point; use App\Entity\Hub; +use App\Service\InventoryManager; + use App\Ramcar\HubCriteria; use App\Ramcar\ServiceType; @@ -15,9 +17,10 @@ class HubSelector { protected $em; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, InventoryManager $im) { $this->em = $em; + $this->im = $im; } public function find(HubCriteria $criteria) @@ -42,10 +45,12 @@ class HubSelector if ($date_time != null) { // call function for jo type, inventory == true, and check for date and time + $results = $this->getClosestHubsWithJoTypeAndInventoryAndTime($point, $limit_results, $limit_distance, $jo_type, $items, $date_time); } else { // call function for jo type and inventory == true + $results = $this->getClosestHubsWithJoTypeAndInventory($point, $limit_results, $limit_distance, $jo_type, $items); } } else @@ -82,18 +87,130 @@ class HubSelector return $results; } - protected function getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time) + protected function getClosestHubsWithJoTypeAndInventoryAndTime($point, $limit_results, $limit_distance, $jo_type, $items, $date_time) { // get closest hubs that are open at the given time offering jo_type service 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist') + $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); $query = $this->em->createQuery($query_string) ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); - // add the jo_type/service parameter + // TODO: add the jo_type/service parameter - // have to add date and time to query + // TODO: have to add date and time to query + // right now, hub only has opening times + // so we extract the time from date_time + $time = $date_time->format("H:i:s"); + if ($time) { + $query->setParameter('time', $time); + } + + $query->setMaxResults($limit_results); + + // error_log($query->getSql()); + $result = $query->getResult(); + + $hubs = []; + $final_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) + { + // TODO: insert call to function that will check inventory here + // checkInventory is going to return true if hub has all items + $this->checkInventory($items, $$row[0]); + // TODO: add checking here if hub has all items or not + $final_data[] = [ + 'hub' => $row[0], + 'db_distance' => $row['dist'], + 'distance' => $dist, + 'duration' => 0, + ]; + } + } + + return $final_data; + } + + protected function getClosestHubsWithJoTypeAndInventory($point, $limit_results, $limit_distance, $jo_type, $items) + { + // 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()); + + // TODO: add the jo_type/service parameter + + $query->setMaxResults($limit_results); + + // error_log($query->getSql()); + $result = $query->getResult(); + + $hubs = []; + $final_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) + { + // TODO: insert call to function that will check inventory here + // checkInventory is going to return true if hub has all items + $this->checkInventory($items, $$row[0]); + // TODO: add checking here if hub has all items or not + $final_data[] = [ + 'hub' => $row[0], + 'db_distance' => $row['dist'], + 'distance' => $dist, + 'duration' => 0, + ]; + } + } + + return $final_data; + } + + protected function getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time) + { + // get closest hubs that are open at the given time offering jo_type service 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); + + $query = $this->em->createQuery($query_string) + ->setParameter('lat', $point->getLatitude()) + ->setParameter('lng', $point->getLongitude()); + + // TODO: add the jo_type/service parameter + + // TODO: have to add date and time to query // right now, hub only has opening times // so we extract the time from date_time $time = $date_time->format("H:i:s"); @@ -147,7 +264,7 @@ class HubSelector ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); - // add the jo type/service parameter here + // TODO: add the jo type/service parameter here $query->setMaxResults($limit_results); @@ -195,7 +312,7 @@ class HubSelector ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); - // have to add date and time to query + // TODO: have to add date and time to query // right now, hub only has opening times // so we extract the time from date_time $time = $date_time->format("H:i:s"); @@ -286,6 +403,13 @@ class HubSelector return $final_data; } + protected function checkInventory($items, $hub) + { + // check if hub has all items + + // return true or false + } + // convert db distance to kilometers protected function distance($lat1, $lon1, $lat2, $lon2) { From d812e347979c05577427d57e56093d4925042e19 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 12 Mar 2021 07:02:26 +0000 Subject: [PATCH 05/29] Fix compilation error. #543 --- src/Service/HubSelector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index 6773f0d8..3ab1eb90 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -306,7 +306,7 @@ class HubSelector protected function getClosestHubsWithTime(Point $point, $limit_results, $limit_distance, $date_time) { // get closest hubs that are open at the given time 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist') + $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); $query = $this->em->createQuery($query_string) ->setParameter('lat', $point->getLatitude()) From de742906244cf587c6c6f1a254c5af4aac57da92 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 12 Mar 2021 11:43:39 +0000 Subject: [PATCH 06/29] Rename inventory flag. Fix find function. #543 --- src/Ramcar/HubCriteria.php | 22 +- src/Service/HubSelector.php | 408 ++++++++---------------------------- 2 files changed, 99 insertions(+), 331 deletions(-) diff --git a/src/Ramcar/HubCriteria.php b/src/Ramcar/HubCriteria.php index cb42ce04..001b4cd3 100644 --- a/src/Ramcar/HubCriteria.php +++ b/src/Ramcar/HubCriteria.php @@ -8,13 +8,13 @@ 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 $has_inventory; // 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[id] = quantity to check for and has_inventory is true + 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[id] = quantity to check for and has_inventory is true public function __construct() { @@ -55,15 +55,15 @@ class HubCriteria return $this->limit_distance; } - public function setHasInventory($has_inventory = true) + public function setInventoryCheck($flag_inventory_check = true) { - $this->has_inventory = $has_inventory; + $this->flag_inventory_check = $flag_inventory_check; return $this; } - public function hasInventory() + public function hasInventoryCheck() { - return $this->has_inventory; + return $this->flag_inventory_check; } public function setJoType($jo_type) diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index 3ab1eb90..ad6f54dd 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -8,6 +8,7 @@ use CrEOF\Spatial\PHP\Types\Geometry\Point; use App\Entity\Hub; +use App\Service\RedisClientProvider; use App\Service\InventoryManager; use App\Ramcar\HubCriteria; @@ -16,11 +17,15 @@ use App\Ramcar\ServiceType; class HubSelector { protected $em; + protected $im; + protected $redis; - public function __construct(EntityManagerInterface $em, InventoryManager $im) + public function __construct(EntityManagerInterface $em, InventoryManager $im, + RedisClientProvider $redis) { $this->em = $em; $this->im = $im; + $this->redis = $redis; } public function find(HubCriteria $criteria) @@ -29,125 +34,100 @@ class HubSelector $limit_results = $criteria->getLimitResults(); $limit_distance = $criteria->getLimitDistance(); $jo_type = $criteria->getJoType(); - $has_inventory = $criteria->hasInventory(); + $flag_inventory_check = $criteria->hasInventoryCheck(); $items = $criteria->getItems(); $date_time = $criteria->getDateTime(); $results = []; - // check for jo type - if (($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW) || - ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) + // get all the hubs within distance + $filtered_hubs = $this->getClosestHubs($point, $limit_distance); + + // filter the first hub results for date and opening times + $hubs_date_time = $this->filterHubsByDateAndTime($filtered_hubs, $date_time); + $filtered_hubs = $hubs_date_time; + + // filter jo types + $hubs_jo_type = $this->filterHubsByJoType($filtered_hubs, $jo_type); + $filtered_hubs = $hubs_jo_type; + + // inventory filter + $hubs_inventory = $this->filterHubsByInventory($filtered_hubs, $has_inventory, + $jo_type, $items); + $filtered_hubs = $hubs_inventory; + + // round robin filter + $hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs); + $filtered_hubs = $hubs_round_robin; + + // max results filter + $hubs_max_result = $this->filterHubsByMaxResults($filtered_hubs, $limit_results); + $filtered_hubs = $hubs_max_result; + + $results = $filtered_hubs; + + return $results; + } + + protected function filterHubsByRoundRobin($hubs) + { + } + + protected function filterHubsByMaxResults($hubs, $limit_result) + { + } + + protected function filterHubsByJoType($hubs, $jo_type) + { + } + + protected function filterHubsByDateAndTime($hubs, $date_time) + { + if (empty($hubs)) + return $hubs; + + if ($date_time == null) + return $hubs; + + $results = []; + + foreach ($hubs as $hub) { - // check if we need to get inventory - if ($has_inventory) - { - if ($date_time != null) - { - // call function for jo type, inventory == true, and check for date and time - $results = $this->getClosestHubsWithJoTypeAndInventoryAndTime($point, $limit_results, $limit_distance, $jo_type, $items, $date_time); - } - else - { - // call function for jo type and inventory == true - $results = $this->getClosestHubsWithJoTypeAndInventory($point, $limit_results, $limit_distance, $jo_type, $items); - } - } - else - { - if ($date_time != null) - { - // call function for jo type and check for date and time - $results = $this->getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time); - } - else - { - // call function for jo type only - $results = $this->getClosestHubsWithJoType($point, $limit_results, $limit_distance, $jo_type); - } - } + // go through each hub's opening times to check if hub is open + // for the specified time } - else + + return $results; + } + + protected function filterHubsByInventory($hubs, $has_inventory, $jo_type, $items) + { + if (empty($hubs)) + return $hubs; + + if (!$flag_inventory_check) + return $hubs; + + $results = []; + if ($flag_inventory_check) { - // no need to check for items and inventory. - // check for date and time - if ($date_time != null) + foreach ($hubs as $hub) { - // call function that gets hubs with opening times - $results = $this->getClosestHubsWithTime($point, $limit_results, $limit_distance, $date_time); - } - else - { - // call default function that just gets the hubs within distance limit - // and number of results - $results = $this->getClosestHubs($point, $limit_results, $limit_distance); + if ($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW) + { + // call inventory + } + if ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY) + { + // call inventory + } } } return $results; } - protected function getClosestHubsWithJoTypeAndInventoryAndTime($point, $limit_results, $limit_distance, $jo_type, $items, $date_time) - { - // get closest hubs that are open at the given time offering jo_type service 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - // TODO: add the jo_type/service parameter - - // TODO: have to add date and time to query - // right now, hub only has opening times - // so we extract the time from date_time - $time = $date_time->format("H:i:s"); - if ($time) { - $query->setParameter('time', $time); - } - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_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) - { - // TODO: insert call to function that will check inventory here - // checkInventory is going to return true if hub has all items - $this->checkInventory($items, $$row[0]); - // TODO: add checking here if hub has all items or not - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubsWithJoTypeAndInventory($point, $limit_results, $limit_distance, $jo_type, $items) + 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'; @@ -156,15 +136,11 @@ class HubSelector ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); - // TODO: add the jo_type/service parameter - - $query->setMaxResults($limit_results); - // error_log($query->getSql()); $result = $query->getResult(); $hubs = []; - $final_data = []; + $hubs_data = []; foreach ($result as $row) { $hubs[] = $row[0]; @@ -183,11 +159,7 @@ class HubSelector if ($dist < $limit_distance) { - // TODO: insert call to function that will check inventory here - // checkInventory is going to return true if hub has all items - $this->checkInventory($items, $$row[0]); - // TODO: add checking here if hub has all items or not - $final_data[] = [ + $hubs_data[] = [ 'hub' => $row[0], 'db_distance' => $row['dist'], 'distance' => $dist, @@ -196,211 +168,7 @@ class HubSelector } } - return $final_data; - } - - protected function getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time) - { - // get closest hubs that are open at the given time offering jo_type service 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - // TODO: add the jo_type/service parameter - - // TODO: have to add date and time to query - // right now, hub only has opening times - // so we extract the time from date_time - $time = $date_time->format("H:i:s"); - if ($time) { - $query->setParameter('time', $time); - } - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_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) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubsWithJoType($point, $limit_results, $limit_distance, $jo_type) - { - // get closest hubs offering jo_type service 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()); - - // TODO: add the jo type/service parameter here - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_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) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubsWithTime(Point $point, $limit_results, $limit_distance, $date_time) - { - // get closest hubs that are open at the given time 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 :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - // TODO: have to add date and time to query - // right now, hub only has opening times - // so we extract the time from date_time - $time = $date_time->format("H:i:s"); - if ($time) { - $query->setParameter('time', $time); - } - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_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) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubs(Point $point, $limit_results, $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()); - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_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) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; + return $hubs_data; } protected function checkInventory($items, $hub) From 498c88ce3814292c724c0175476ce9e3030674c1 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 15 Mar 2021 03:46:13 +0000 Subject: [PATCH 07/29] Add jo type, date, and inventory filters. #543 --- src/Service/HubSelector.php | 56 ++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index ad6f54dd..2a9f7a80 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -71,14 +71,36 @@ class HubSelector protected function filterHubsByRoundRobin($hubs) { + if (empty($hubs)) + return $hubs; } protected function filterHubsByMaxResults($hubs, $limit_result) { + if (empty($hubs)) + return $hubs; + if (empty($limit_result)) + return $hubs; } protected function filterHubsByJoType($hubs, $jo_type) { + if (empty($hubs)) + return $hubs; + if (empty($jo_type)) + return $hubs; + + $results = []; + foreach ($hubs as $hub) + { + $has_jo_type = false; + // check if hub offers the jo_type + // TODO: add service to hub + if ($has_jo_type) + $results[] = $hub; + } + + return $results; } protected function filterHubsByDateAndTime($hubs, $date_time) @@ -95,6 +117,17 @@ class HubSelector { // go through each hub's opening times to check if hub is open // for the specified time + // get hub opening and closing times + $time_open = date("H:i:s", $hub->getTimeOpen()); + $time_close = date("H:i:s", $hub->getTimeClose()); + + $filter_time = date("H:i:s", $date_time); + + if (($filter_time >= $time_open) && + ($filter_time <= $time_close)) + { + $results[] = $hub; + } } return $results; @@ -115,11 +148,17 @@ class HubSelector { if ($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW) { - // call inventory + // call inventory + $has_items = $this->checkInventory($items, $hub); + if ($has_items) + $results[] = $hub; } if ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY) { // call inventory + $has_items = $this->checkInventory($items, $hub); + if ($has_items) + $results[] = $hub; } } } @@ -174,8 +213,23 @@ class HubSelector protected function checkInventory($items, $hub) { // check if hub has all items + $skus = []; + $hubs[] = $hub; + $result = false; + + foreach ($items as $item) + { + // add sap code of item/battery into array since + // getBranchesInventory takes in an array of hubs/branches + // and an array of skus + $sku[] = $item->getSAPCode(); + } + + // call InventoryManager's getBranchesInventory to check if hub has all items + $result = $this->im->getBranchesInventory($hubs, $skus); // return true or false + return $result; } // convert db distance to kilometers From 0f245e9038bf77485f1abfb9f06fcd0e1c9d47ab Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 15 Mar 2021 08:32:37 +0000 Subject: [PATCH 08/29] Fixes to issues found during testing. #543 --- src/Controller/APIController.php | 28 ++++++++-- src/Ramcar/HubCriteria.php | 8 +-- src/Service/HubSelector.php | 93 +++++++++++++++++++++++++------- src/Service/InventoryManager.php | 1 + 4 files changed, 102 insertions(+), 28 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 8f268309..919c2b1e 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -26,6 +26,7 @@ use App\Ramcar\TradeInType; use App\Ramcar\JOEventType; use App\Ramcar\AdvanceOrderSlot; use App\Ramcar\AutoAssignStatus; +use App\Ramcar\HubCriteria; use App\Service\InvoiceGeneratorInterface; use App\Service\RisingTideGateway; @@ -35,6 +36,7 @@ use App\Service\RiderTracker; use App\Service\MapTools; use App\Service\InventoryManager; use App\Service\RiderAssignmentHandlerInterface; +use App\Service\HubSelector; use App\Entity\MobileSession; use App\Entity\Customer; @@ -2330,7 +2332,7 @@ class APIController extends Controller implements LoggedController public function newRequestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo, MapTools $map_tools, InventoryManager $im, MQTTClient $mclient, - RiderAssignmentHandlerInterface $rah) + RiderAssignmentHandlerInterface $rah, HubSelector $hub_select) { // check required parameters and api key $required_params = [ @@ -2515,24 +2517,40 @@ class APIController extends Controller implements LoggedController // check if hub is null if ($hub == null) { + // TODO: set this properly. This is test data + $hub_criteria = new HubCriteria(); + $hub_criteria->setPoint($jo->getCoordinates()) + ->setLimitResults(1) + ->setLimitDistance(5) + ->setInventoryCheck(true) + ->setJoType($jo->getServiceType()) + ->setDateTime(new DateTime()); + + // add battery to items + $sku = $batt->getSAPCode(); + if (!empty($sku)) + $hub_criteria->addItem($batt->getSAPCode(), 1); + // find nearest hub 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); - $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); + //$nearest_hub = $this->findNearestHub($jo, $em, $map_tools); + $nearest_hubs = $hub_select->find($hub_criteria); } else { $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); + $nearest_hubs = $hub_select->find($hub_criteria); } - if (!empty($nearest_hub)) + if (!empty($nearest_hubs)) { //error_log('found nearest hub ' . $nearest_hub->getID()); // assign rider - $available_riders = $nearest_hub->getAvailableRiders(); + $available_riders = $nearest_hubs[0]['hub']->getAvailableRiders(); if (count($available_riders) > 0) { $assigned_rider = null; @@ -2553,7 +2571,7 @@ class APIController extends Controller implements LoggedController $assigned_rider = $available_riders[0]; //error_log('found rider ' . $assigned_rider->getID()); - $jo->setHub($nearest_hub); + $jo->setHub($nearest_hubs[0]['hub']); $jo->setRider($assigned_rider); $jo->setStatus(JOStatus::ASSIGNED); $jo->setStatusAutoAssign(AutoAssignStatus::HUB_AND_RIDER_ASSIGNED); diff --git a/src/Ramcar/HubCriteria.php b/src/Ramcar/HubCriteria.php index 001b4cd3..a57b4b99 100644 --- a/src/Ramcar/HubCriteria.php +++ b/src/Ramcar/HubCriteria.php @@ -14,7 +14,7 @@ class HubCriteria 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[id] = quantity to check for and has_inventory is true + protected $items; // array of items: items[sku] = quantity to check for public function __construct() { @@ -89,10 +89,10 @@ class HubCriteria return $this->date_time; } - public function addItem($id, $quantity) + public function addItem($sku, $quantity) { - // at this point, id is assumed to be a valid item - $this->items[$id] = $quantity; + // at this point, sku is assumed to be a valid item + $this->items[$sku] = $quantity; return $this; } diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index 2a9f7a80..c5403dd2 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -52,13 +52,13 @@ class HubSelector $filtered_hubs = $hubs_jo_type; // inventory filter - $hubs_inventory = $this->filterHubsByInventory($filtered_hubs, $has_inventory, + $hubs_inventory = $this->filterHubsByInventory($filtered_hubs, $flag_inventory_check, $jo_type, $items); $filtered_hubs = $hubs_inventory; // round robin filter - $hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs); - $filtered_hubs = $hubs_round_robin; + //$hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs); + //$filtered_hubs = $hubs_round_robin; // max results filter $hubs_max_result = $this->filterHubsByMaxResults($filtered_hubs, $limit_results); @@ -73,6 +73,9 @@ class HubSelector { if (empty($hubs)) return $hubs; + + // for now only + return $hubs; } protected function filterHubsByMaxResults($hubs, $limit_result) @@ -81,6 +84,14 @@ class HubSelector return $hubs; if (empty($limit_result)) return $hubs; + + $results = []; + for ($i = 0; $i < $limit_result; $i++) + { + $results[] = $hubs[$i]; + } + + return $results; } protected function filterHubsByJoType($hubs, $jo_type) @@ -91,13 +102,21 @@ class HubSelector return $hubs; $results = []; - foreach ($hubs as $hub) + foreach ($hubs as $hub_data) { - $has_jo_type = false; + $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; + $results[] = [ + 'hub' => $hub, + 'db_distance' => $hub_data['db_distance'], + 'distance' => $hub_data['distance'], + 'duration' => $hub_data['duration'], + ]; } return $results; @@ -113,27 +132,34 @@ class HubSelector $results = []; - foreach ($hubs as $hub) + 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 - $time_open = date("H:i:s", $hub->getTimeOpen()); - $time_close = date("H:i:s", $hub->getTimeClose()); + $hub = $hub_data['hub']; - $filter_time = date("H:i:s", $date_time); + $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; + $results[] = [ + 'hub' => $hub, + 'db_distance' => $hub_data['db_distance'], + 'distance' => $hub_data['distance'], + 'duration' => $hub_data['duration'], + ]; } } return $results; } - protected function filterHubsByInventory($hubs, $has_inventory, $jo_type, $items) + protected function filterHubsByInventory($hubs, $flag_inventory_check, $jo_type, $items) { if (empty($hubs)) return $hubs; @@ -144,21 +170,33 @@ class HubSelector $results = []; if ($flag_inventory_check) { - foreach ($hubs as $hub) + 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; + $results[] = [ + 'hub' => $hub, + 'db_distance' => $hub_data['db_distance'], + 'distance' => $hub_data['distance'], + 'duration' => $hub_data['duration'], + ]; } if ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY) { // call inventory $has_items = $this->checkInventory($items, $hub); if ($has_items) - $results[] = $hub; + $results[] = [ + 'hub' => $hub, + 'db_distance' => $hub_data['db_distance'], + 'distance' => $hub_data['distance'], + 'duration' => $hub_data['duration'], + ]; } } } @@ -214,19 +252,36 @@ class HubSelector { // check if hub has all items $skus = []; - $hubs[] = $hub; + $branch_codes[] = $hub->getBranchCode(); $result = false; - foreach ($items as $item) + 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 - $sku[] = $item->getSAPCode(); + // $items as format: $items[sku] = quantity + $skus[] = $key; } // call InventoryManager's getBranchesInventory to check if hub has all items - $result = $this->im->getBranchesInventory($hubs, $skus); + $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; diff --git a/src/Service/InventoryManager.php b/src/Service/InventoryManager.php index 4dc5a8b1..f0669559 100644 --- a/src/Service/InventoryManager.php +++ b/src/Service/InventoryManager.php @@ -71,6 +71,7 @@ class InventoryManager // check if the response is empty $results = []; + //error_log($response); if (!empty($response)) $results = json_decode($response, true); From 1abaad1727cf23332e27ccf185420d163f9994f3 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 15 Mar 2021 10:09:11 +0000 Subject: [PATCH 09/29] Add HubDistributor service. #543 --- .env.dist | 1 + config/services.yaml | 7 +++++ src/Controller/APIController.php | 1 + src/Service/HubDistributor.php | 54 ++++++++++++++++++++++++++++++++ src/Service/HubSelector.php | 21 ++++++++----- 5 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 src/Service/HubDistributor.php diff --git a/.env.dist b/.env.dist index f6d35eec..33902df3 100644 --- a/.env.dist +++ b/.env.dist @@ -57,6 +57,7 @@ COUNTRY_CODE=+insert_country_code_here # redis hash LATEST_ACTIVE_JO=latest_active_jo +HUB_JO_KEY=hub_jo_count # dashboard DASHBOARD_ENABLE=set_to_true_or_false diff --git a/config/services.yaml b/config/services.yaml index 4fb5f088..988c1f95 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -271,3 +271,10 @@ services: arguments: $em: "@doctrine.orm.entity_manager" $im: "@App\\Service\\InventoryManager" + $hub_distributor: "@App\\Service\\HubDistributor" + + # hub distributor + App\Service\HubDistributor: + arguments: + $redis: "@App\\Service\\RedisClientProvider" + $hub_jo_key: "%env(HUB_JO_KEY)%" diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 919c2b1e..850bddd9 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -2546,6 +2546,7 @@ class APIController extends Controller implements LoggedController $nearest_hubs = $hub_select->find($hub_criteria); } + // TODO: this might need changes after the new hub selector if (!empty($nearest_hubs)) { //error_log('found nearest hub ' . $nearest_hub->getID()); diff --git a/src/Service/HubDistributor.php b/src/Service/HubDistributor.php new file mode 100644 index 00000000..acfafd1a --- /dev/null +++ b/src/Service/HubDistributor.php @@ -0,0 +1,54 @@ +redis = $redis->getRedisClient(); + $this->hub_jo_key = $hub_jo_key; + } + + public function addJoCountForHub(Hub $hub) + { + $key = $hub->gtID(); + + // get current count + $result = $this->redis->hget($this->hub_jo_key, $key); + if ($result == true) + { + // hub exist in hash + // add to count + } + else + { + // hub not in hash + // add hub to hash + } + } + + public function arrangeHubs($hubs) + { + $arranged_hubs = []; + + foreach ($hubs as $hub_data) + { + $hub = $hub_data['hub']; + + // get hub in hash + } + + return $arranged_hubs; + } +} diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index c5403dd2..58f8f99f 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -8,7 +8,7 @@ use CrEOF\Spatial\PHP\Types\Geometry\Point; use App\Entity\Hub; -use App\Service\RedisClientProvider; +use App\Service\HubDistributor; use App\Service\InventoryManager; use App\Ramcar\HubCriteria; @@ -18,14 +18,14 @@ class HubSelector { protected $em; protected $im; - protected $redis; + protected $hub_distributor; public function __construct(EntityManagerInterface $em, InventoryManager $im, - RedisClientProvider $redis) + HubDistributor $hub_distributor) { $this->em = $em; $this->im = $im; - $this->redis = $redis; + $this->hub_distributor = $hub_distributor; } public function find(HubCriteria $criteria) @@ -57,8 +57,8 @@ class HubSelector $filtered_hubs = $hubs_inventory; // round robin filter - //$hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs); - //$filtered_hubs = $hubs_round_robin; + $hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs); + $filtered_hubs = $hubs_round_robin; // max results filter $hubs_max_result = $this->filterHubsByMaxResults($filtered_hubs, $limit_results); @@ -74,8 +74,13 @@ class HubSelector if (empty($hubs)) return $hubs; - // for now only - 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) From 0115328801b4c02c6c7ec54788b533c5802f1a46 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 16 Mar 2021 06:33:40 +0000 Subject: [PATCH 10/29] Add arranging of hubs, based on job orders assigned to hub. #543 --- src/Controller/APIController.php | 7 ++-- src/Service/HubDistributor.php | 59 +++++++++++++++++++++++++------- src/Service/HubSelector.php | 7 +++- 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 850bddd9..cc6e2ed3 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -37,6 +37,7 @@ use App\Service\MapTools; use App\Service\InventoryManager; use App\Service\RiderAssignmentHandlerInterface; use App\Service\HubSelector; +use App\Service\HubDistributor; use App\Entity\MobileSession; use App\Entity\Customer; @@ -2520,9 +2521,9 @@ class APIController extends Controller implements LoggedController // TODO: set this properly. This is test data $hub_criteria = new HubCriteria(); $hub_criteria->setPoint($jo->getCoordinates()) - ->setLimitResults(1) - ->setLimitDistance(5) - ->setInventoryCheck(true) + ->setLimitResults(50) + ->setLimitDistance(100) + ->setInventoryCheck(false) ->setJoType($jo->getServiceType()) ->setDateTime(new DateTime()); diff --git a/src/Service/HubDistributor.php b/src/Service/HubDistributor.php index acfafd1a..fb0bc3b1 100644 --- a/src/Service/HubDistributor.php +++ b/src/Service/HubDistributor.php @@ -2,8 +2,6 @@ namespace App\Service; -use Doctrine\ORM\EntityManagerInterface; - use App\Service\RedisClientProvider; use App\Entity\Hub; @@ -13,8 +11,7 @@ class HubDistributor protected $redis; protected $hub_jo_key; - public function __construct(RedisClientProvider $redis, - $hub_jo_key) + public function __construct(RedisClientProvider $redis, $hub_jo_key) { $this->redis = $redis->getRedisClient(); $this->hub_jo_key = $hub_jo_key; @@ -22,33 +19,69 @@ class HubDistributor public function addJoCountForHub(Hub $hub) { - $key = $hub->gtID(); + $key = $hub->getID(); // get current count - $result = $this->redis->hget($this->hub_jo_key, $key); - if ($result == true) - { - // hub exist in hash - // add to count - } - else + $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 arrangeHubs($hubs) { + if (count($hubs) == 1) + return $hubs; + $arranged_hubs = []; foreach ($hubs as $hub_data) { $hub = $hub_data['hub']; - // get hub in hash + // 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 + $arranged_hubs[] = [ + 'hub' => $hub, + 'db_distance' => $hub_data['db_distance'], + 'distance' => $hub_data['distance'], + 'duration' => $hub_data['duration'], + 'jo_count' => 0, + ]; + + if ($hub_jo_count != null) + { + $arranged_hubs['jo_count'] = $hub_jo_count; + } } + 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; } } diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index 58f8f99f..ececc91b 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -60,12 +60,16 @@ class HubSelector $hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs); $filtered_hubs = $hubs_round_robin; + //error_log(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; } @@ -93,7 +97,8 @@ class HubSelector $results = []; for ($i = 0; $i < $limit_result; $i++) { - $results[] = $hubs[$i]; + if ($i < count($hubs)) + $results[] = $hubs[$i]; } return $results; From 50e15cd77061024379b205898e0f37023ec05c03 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 16 Mar 2021 07:50:18 +0000 Subject: [PATCH 11/29] Update hub_jo_count when hub is assigned or reassigned via admin panel. #543 --- src/Controller/APIController.php | 11 ++++- src/Service/HubDistributor.php | 42 ++++++++++++++----- .../JobOrderHandler/ResqJobOrderHandler.php | 19 ++++++++- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index cc6e2ed3..3b19a942 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -2333,7 +2333,8 @@ class APIController extends Controller implements LoggedController public function newRequestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo, MapTools $map_tools, InventoryManager $im, MQTTClient $mclient, - RiderAssignmentHandlerInterface $rah, HubSelector $hub_select) + RiderAssignmentHandlerInterface $rah, HubSelector $hub_select, + HubDistributor $hub_dist) { // check required parameters and api key $required_params = [ @@ -2579,6 +2580,9 @@ class APIController extends Controller implements LoggedController $jo->setStatusAutoAssign(AutoAssignStatus::HUB_AND_RIDER_ASSIGNED); $assigned_rider->setAvailable(false); + + // update redis hub_jo_count for hub + $hub_dist->incrementJoCountForHub($nearest_hubs[0]['hub']); } } } @@ -2601,7 +2605,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); diff --git a/src/Service/HubDistributor.php b/src/Service/HubDistributor.php index fb0bc3b1..e401a4a1 100644 --- a/src/Service/HubDistributor.php +++ b/src/Service/HubDistributor.php @@ -17,7 +17,7 @@ class HubDistributor $this->hub_jo_key = $hub_jo_key; } - public function addJoCountForHub(Hub $hub) + public function incrementJoCountForHub(Hub $hub) { $key = $hub->getID(); @@ -38,6 +38,20 @@ class HubDistributor } } + 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) @@ -57,17 +71,25 @@ class HubDistributor // check if hub is in hash. if not, hub has no jobs // but should still be added to results - $arranged_hubs[] = [ - 'hub' => $hub, - 'db_distance' => $hub_data['db_distance'], - 'distance' => $hub_data['distance'], - 'duration' => $hub_data['duration'], - 'jo_count' => 0, - ]; - if ($hub_jo_count != null) { - $arranged_hubs['jo_count'] = $hub_jo_count; + $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, + ]; } } diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index 70cac92d..040109d1 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -49,6 +49,7 @@ use App\Service\MQTTClient; use App\Service\APNSClient; use App\Service\MapTools; use App\Service\RisingTideGateway; +use App\Service\HubDistributor; use CrEOF\Spatial\PHP\Types\Geometry\Point; @@ -70,13 +71,15 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface protected $country_code; protected $wh; protected $rt; + protected $hub_dist; protected $template_hash; public function __construct(Security $security, EntityManagerInterface $em, InvoiceGeneratorInterface $ic, ValidatorInterface $validator, TranslatorInterface $translator, RiderAssignmentHandlerInterface $rah, - string $country_code, WarrantyHandler $wh, RisingTideGateway $rt) + string $country_code, WarrantyHandler $wh, RisingTideGateway $rt, + HubDistributor $hub_dist) { $this->em = $em; $this->ic = $ic; @@ -87,6 +90,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $this->country_code = $country_code; $this->wh = $wh; $this->rt = $rt; + $this->hub_dist = $hub_dist; $this->loadTemplates(); } @@ -753,6 +757,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; @@ -1122,6 +1129,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 @@ -1195,6 +1205,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; From c69a18d89bbe2d4ec63c6ae5fe1d043d9e823f42 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 16 Mar 2021 08:19:20 +0000 Subject: [PATCH 12/29] Add command to reset hub jo count in redis. #543 --- src/Command/ResetHubJoCountCommand.php | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/Command/ResetHubJoCountCommand.php diff --git a/src/Command/ResetHubJoCountCommand.php b/src/Command/ResetHubJoCountCommand.php new file mode 100644 index 00000000..ea2314f3 --- /dev/null +++ b/src/Command/ResetHubJoCountCommand.php @@ -0,0 +1,39 @@ +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; + } +} From 0ecc55cf56e03b7929540be95b733c862b7b09c0 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 16 Mar 2021 09:31:19 +0000 Subject: [PATCH 13/29] Have admin panel use the HubSelector service when getting closest hubs. #543 --- src/Controller/HubController.php | 12 ++++++++--- src/Controller/JobOrderController.php | 11 ++++++---- src/Ramcar/HubCriteria.php | 4 ++++ src/Service/HubSelector.php | 4 +++- .../JobOrderHandler/ResqJobOrderHandler.php | 20 +++++++++++++++---- src/Service/JobOrderHandlerInterface.php | 5 +++-- 6 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/Controller/HubController.php b/src/Controller/HubController.php index edc6e599..478a37a0 100644 --- a/src/Controller/HubController.php +++ b/src/Controller/HubController.php @@ -17,8 +17,9 @@ use DateTime; use Catalyst\MenuBundle\Annotation\Menu; -use App\Service\MapTools; use App\Service\RiderTracker; +use App\Service\HubSelector; +use App\Ramcar\HubCriteria; class HubController extends Controller { @@ -295,7 +296,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 +304,12 @@ 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); + //$result = $map_tools->getClosestHubs($point, 10, date("H:i:s")); $hubs = []; foreach ($result as $hub_res) diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 11c7edf0..15f524d6 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -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) { @@ -1204,6 +1205,7 @@ class JobOrderController extends Controller ]); } + // this is uncalled or does not display in admin panel /** * @Menu(selected="jo_autoassign") */ @@ -1223,6 +1225,7 @@ class JobOrderController extends Controller return $this->render($template, $params); } + // this is uncalled or does not display in admin panel public function autoAssignSubmit(Request $req, JobOrderHandlerInterface $jo_handler, EntityManagerInterface $em, MapTools $map_tools, InventoryManager $im) diff --git a/src/Ramcar/HubCriteria.php b/src/Ramcar/HubCriteria.php index a57b4b99..eae31acc 100644 --- a/src/Ramcar/HubCriteria.php +++ b/src/Ramcar/HubCriteria.php @@ -18,6 +18,10 @@ class HubCriteria public function __construct() { + $this->limit_results = 10; + $this->limit_distance = 500; + $this->jo_type = ''; + $this->date_time = null; $this->has_inventory = false; $this->items = []; } diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index ececc91b..e6507529 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -43,6 +43,8 @@ class HubSelector // get all the hubs within distance $filtered_hubs = $this->getClosestHubs($point, $limit_distance); + //error_log('closest hubs ' . json_encode($filtered_hubs)); + // filter the first hub results for date and opening times $hubs_date_time = $this->filterHubsByDateAndTime($filtered_hubs, $date_time); $filtered_hubs = $hubs_date_time; @@ -68,7 +70,7 @@ class HubSelector $results = $filtered_hubs; - //error_log(json_encode($results)); + error_log(json_encode($results)); return $results; } diff --git a/src/Service/JobOrderHandler/ResqJobOrderHandler.php b/src/Service/JobOrderHandler/ResqJobOrderHandler.php index 040109d1..bbfe71e6 100644 --- a/src/Service/JobOrderHandler/ResqJobOrderHandler.php +++ b/src/Service/JobOrderHandler/ResqJobOrderHandler.php @@ -40,6 +40,7 @@ use App\Ramcar\JORejectionReason; use App\Ramcar\CustomerNotWaitReason; use App\Ramcar\NoTradeInReason; use App\Ramcar\WillingToWaitContent; +use App\Ramcar\HubCriteria; use App\Service\InvoiceGeneratorInterface; use App\Service\JobOrderHandlerInterface; @@ -49,6 +50,7 @@ use App\Service\MQTTClient; use App\Service\APNSClient; use App\Service\MapTools; use App\Service\RisingTideGateway; +use App\Service\HubSelector; use App\Service\HubDistributor; use CrEOF\Spatial\PHP\Types\Geometry\Point; @@ -1647,6 +1649,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface return $params; } + // CMB code public function initializeOneStepEditForm($id, $map_tools) { $em = $this->em; @@ -1827,7 +1830,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; @@ -1894,7 +1897,12 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $params['rejection_reasons'] = JORejectionReason::getCollection(); // get closest hubs - $hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s")); + // set hub criteria + $hub_criteria = new HubCriteria(); + $hub_criteria->setPoint($obj->getCoordinates()) + ->setLimitResults(50); + $hubs = $hub_selector->find($hub_criteria); + //$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s")); $params['hubs'] = []; @@ -2118,7 +2126,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface } // initialize hub form - public function initializeHubForm($id, $map_tools) + public function initializeHubForm($id, HubSelector $hub_selector) { $em = $this->em; @@ -2143,7 +2151,11 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface $params['rejection_reasons'] = JORejectionReason::getCollection(); // get closest hubs - $hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s")); + $hub_criteria = new HubCriteria(); + $hub_criteria->setPoint($obj->getCoordinates()) + ->setLimitResults(50); + $hubs = $hub_selector->find($hub_criteria); + //$hubs = $map_tools->getClosestHubs($obj->getCoordinates(), 50, date("H:i:s")); $params['status_cancelled'] = JOStatus::CANCELLED; $params['hubs'] = []; diff --git a/src/Service/JobOrderHandlerInterface.php b/src/Service/JobOrderHandlerInterface.php index 59aea943..cff06242 100644 --- a/src/Service/JobOrderHandlerInterface.php +++ b/src/Service/JobOrderHandlerInterface.php @@ -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); From 2db7c6791f1d7bd5e6dfce7293270a8eddd1c30f Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 17 Mar 2021 03:09:33 +0000 Subject: [PATCH 14/29] Add entity for logging of filtered hubs. #543 --- src/Entity/HubFilterLog.php | 83 +++++++++++++++++++++++++++++++++++++ src/Ramcar/HubCriteria.php | 1 + 2 files changed, 84 insertions(+) create mode 100644 src/Entity/HubFilterLog.php diff --git a/src/Entity/HubFilterLog.php b/src/Entity/HubFilterLog.php new file mode 100644 index 00000000..00f8394d --- /dev/null +++ b/src/Entity/HubFilterLog.php @@ -0,0 +1,83 @@ +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; + } +} diff --git a/src/Ramcar/HubCriteria.php b/src/Ramcar/HubCriteria.php index eae31acc..2c91654f 100644 --- a/src/Ramcar/HubCriteria.php +++ b/src/Ramcar/HubCriteria.php @@ -18,6 +18,7 @@ class HubCriteria public function __construct() { + // TODO: default values might still change $this->limit_results = 10; $this->limit_distance = 500; $this->jo_type = ''; From 4966e7e0c692c97daf2158161ae59f267975cfe8 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 17 Mar 2021 07:12:25 +0000 Subject: [PATCH 15/29] Add logging for filtered hubs. #543 --- config/services.yaml | 6 ++++++ src/Controller/APIController.php | 9 +++------ src/Service/HubFilterLogger.php | 29 +++++++++++++++++++++++++++++ src/Service/HubSelector.php | 27 +++++++++++++++++++++++---- 4 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 src/Service/HubFilterLogger.php diff --git a/config/services.yaml b/config/services.yaml index 988c1f95..29231ef0 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -272,9 +272,15 @@ services: $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" diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 3b19a942..89886872 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -2519,14 +2519,11 @@ class APIController extends Controller implements LoggedController // check if hub is null if ($hub == null) { - // TODO: set this properly. This is test data + // TODO: set this properly, since the other flags + // are on default values $hub_criteria = new HubCriteria(); $hub_criteria->setPoint($jo->getCoordinates()) - ->setLimitResults(50) - ->setLimitDistance(100) - ->setInventoryCheck(false) - ->setJoType($jo->getServiceType()) - ->setDateTime(new DateTime()); + ->setJoType($jo->getServiceType()); // add battery to items $sku = $batt->getSAPCode(); diff --git a/src/Service/HubFilterLogger.php b/src/Service/HubFilterLogger.php new file mode 100644 index 00000000..71cc1929 --- /dev/null +++ b/src/Service/HubFilterLogger.php @@ -0,0 +1,29 @@ +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(); + } +} diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index e6507529..ea55b160 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -10,6 +10,7 @@ use App\Entity\Hub; use App\Service\HubDistributor; use App\Service\InventoryManager; +use App\Service\HubFilterLogger; use App\Ramcar\HubCriteria; use App\Ramcar\ServiceType; @@ -19,13 +20,15 @@ class HubSelector protected $em; protected $im; protected $hub_distributor; + protected $hub_filter_logger; public function __construct(EntityManagerInterface $em, InventoryManager $im, - HubDistributor $hub_distributor) + HubDistributor $hub_distributor, HubFilterLogger $hub_filter_logger) { $this->em = $em; $this->im = $im; $this->hub_distributor = $hub_distributor; + $this->hub_filter_logger = $hub_filter_logger; } public function find(HubCriteria $criteria) @@ -97,10 +100,12 @@ class HubSelector return $hubs; $results = []; - for ($i = 0; $i < $limit_result; $i++) + for ($i = 0; $i < count($hubs); $i++) { - if ($i < count($hubs)) + if ($i < $limit_result) $results[] = $hubs[$i]; + else + $this->hub_filter_logger->logFilteredHub($hubs[$i]['hub'], 'max_results'); } return $results; @@ -129,6 +134,8 @@ class HubSelector 'distance' => $hub_data['distance'], 'duration' => $hub_data['duration'], ]; + else + $this->hub_filter_logger->logFilteredHub($hub, 'job_order_type'); } return $results; @@ -149,6 +156,8 @@ class HubSelector // 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"); @@ -166,6 +175,8 @@ class HubSelector 'duration' => $hub_data['duration'], ]; } + else + $this->hub_filter_logger->logFilteredHub($hub, 'date_and_time'); } return $results; @@ -196,7 +207,9 @@ class HubSelector 'db_distance' => $hub_data['db_distance'], 'distance' => $hub_data['distance'], 'duration' => $hub_data['duration'], - ]; + ]; + else + $this->hub_filter_logger->logFilteredHub($hub, 'inventory'); } if ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY) { @@ -209,6 +222,8 @@ class HubSelector 'distance' => $hub_data['distance'], 'duration' => $hub_data['duration'], ]; + else + $this->hub_filter_logger->logFilteredHub($hub, 'inventory'); } } } @@ -255,6 +270,10 @@ class HubSelector 'duration' => 0, ]; } + else + { + $this->hub_filter_logger->logFilteredHub($row[0], 'distance'); + } } return $hubs_data; From a5aef93ccb77f9ef2fe86b581334160324524a52 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 22 Mar 2021 07:16:30 +0000 Subject: [PATCH 16/29] Add logging of hub if hub has no available rider. #543 --- src/Controller/APIController.php | 65 ++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 89886872..8bcc682f 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -38,6 +38,7 @@ use App\Service\InventoryManager; use App\Service\RiderAssignmentHandlerInterface; use App\Service\HubSelector; use App\Service\HubDistributor; +use App\Service\HubFilterLogger; use App\Entity\MobileSession; use App\Entity\Customer; @@ -2334,7 +2335,7 @@ class APIController extends Controller implements LoggedController public function newRequestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo, MapTools $map_tools, InventoryManager $im, MQTTClient $mclient, RiderAssignmentHandlerInterface $rah, HubSelector $hub_select, - HubDistributor $hub_dist) + HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger) { // check required parameters and api key $required_params = [ @@ -2548,38 +2549,52 @@ class APIController extends Controller implements LoggedController // TODO: this might need changes after the new hub selector 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_hubs[0]['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_hubs[0]['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_hubs[0]['hub']); + { + // 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 + } } } } From 6bc24c4756b435a45a89418229c7c64d84eaacfe Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 30 Mar 2021 09:03:19 +0000 Subject: [PATCH 17/29] Remove checking for jo type in newRequestJobOrder. #543 --- src/Controller/APIController.php | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 21e4a0a9..c1ea75fe 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -2533,22 +2533,9 @@ class APIController extends Controller implements LoggedController if (!empty($sku)) $hub_criteria->addItem($batt->getSAPCode(), 1); - // find nearest hub - 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); - //$nearest_hub = $this->findNearestHub($jo, $em, $map_tools); - $nearest_hubs = $hub_select->find($hub_criteria); - } - else - { - $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); - $nearest_hubs = $hub_select->find($hub_criteria); - } + // find nearest hubs + $nearest_hubs = $hub_select->find($hub_criteria); - // TODO: this might need changes after the new hub selector if (!empty($nearest_hubs)) { // go through the hub list, find the nearest hub From f7983e4c1d80a99d48d5f32e2b39124bafe8d6b8 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 21 Apr 2021 03:22:51 +0000 Subject: [PATCH 18/29] Add hub round robin to requestJobOrder. #543 --- src/Controller/APIController.php | 91 +++++++++++++++++++------------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index c1ea75fe..c510db98 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -848,7 +848,8 @@ class APIController extends Controller implements LoggedController public function requestJobOrder(Request $req, InvoiceGeneratorInterface $ic, GeofenceTracker $geo, MapTools $map_tools, InventoryManager $im, MQTTClient $mclient, - RiderAssignmentHandlerInterface $rah) + RiderAssignmentHandlerInterface $rah, HubSelector $hub_select, + HubDistributor $hub_dist, HubFilterLogger $hub_filter_logger) { // check required parameters and api key $required_params = [ @@ -1013,51 +1014,69 @@ 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)) - { - // TODO: call HubSelector service here - // get nearest hub - // $nearest_hub = $this->findNearestHubWithInventory($jo, $batt, $em, $map_tools, $im); - $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); - } - else - { - // TODO: call HubSelector service here - $nearest_hub = $this->findNearestHub($jo, $em, $map_tools); - } - if (!empty($nearest_hub)) + // TODO: set this properly, since the other flags + // are on default values + $hub_criteria = new HubCriteria(); + $hub_criteria->setPoint($jo->getCoordinates()) + ->setJoType($jo->getServiceType()); + + // 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 + } } } From f24f3e2bb9eb6cf386f81771fe36f39a07b1634f Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 23 Apr 2021 06:07:21 +0000 Subject: [PATCH 19/29] Add notification number to hub. #552 --- src/Controller/HubController.php | 34 +++++++++++++++++++++++-------- src/Entity/Hub.php | 17 ++++++++++++++++ src/Service/RisingTideGateway.php | 24 ++++++++++++++++++++++ templates/hub/form.html.twig | 12 +++++++++++ 4 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/Controller/HubController.php b/src/Controller/HubController.php index edc6e599..d2e52d6a 100644 --- a/src/Controller/HubController.php +++ b/src/Controller/HubController.php @@ -19,6 +19,7 @@ use Catalyst\MenuBundle\Annotation\Menu; use App\Service\MapTools; use App\Service\RiderTracker; +use App\Service\RisingTideGateway; class HubController extends Controller { @@ -143,6 +144,8 @@ class HubController extends Controller $time_open = DateTime::createFromFormat($format, $req->request->get('time_open')); $time_close = DateTime::createFromFormat($format, $req->request->get('time_close')); + error_log($req->request->get('notif_number')); + // set and save values $obj->setName($req->request->get('name')) ->setBranch($req->request->get('branch')) @@ -154,7 +157,8 @@ 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('63' . $req->request->get('notif_number')); } protected function setQueryFilters($datatable, QueryBuilder $query) @@ -166,7 +170,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 +180,20 @@ 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'); + $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(); @@ -231,7 +241,7 @@ class HubController extends Controller 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 +253,20 @@ 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'); + $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(); diff --git a/src/Entity/Hub.php b/src/Entity/Hub.php index 0b1769b2..ec4aff75 100644 --- a/src/Entity/Hub.php +++ b/src/Entity/Hub.php @@ -68,6 +68,12 @@ 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; + public function __construct() { $this->time_open = new DateTime(); @@ -76,6 +82,7 @@ class Hub $this->outlets = new ArrayCollection(); $this->status_open = true; $this->flag_hub_view = false; + $this->notif_number = ''; } public function getRiders() @@ -185,5 +192,15 @@ 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; + } } diff --git a/src/Service/RisingTideGateway.php b/src/Service/RisingTideGateway.php index 38276619..acd7d4d5 100644 --- a/src/Service/RisingTideGateway.php +++ b/src/Service/RisingTideGateway.php @@ -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; + } } diff --git a/templates/hub/form.html.twig b/templates/hub/form.html.twig index d7101260..ea300ab6 100644 --- a/templates/hub/form.html.twig +++ b/templates/hub/form.html.twig @@ -90,6 +90,18 @@ +
+ +
+ {% trans %}country_code_prefix{% endtrans %} + + +
+
+ +
+
+
+ +
+ {% for payment_method in payment_methods %} + + {% endfor %} +
+ + Check all payment methods that apply +
+