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();