0) { $q.= " AND a.transport_provider_id=${tpid}"; } $q.= " AND a.cost>0"; $r = pg_query($db, $q); if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) { $total = $f[0]; } if ($total>0 && $offset<$total) { $q = Quotes::BASE_SQL_DATA . Quotes::BASE_SQL_FROM . " AND lower(ls.address)='${db_origin}' "; $q.= " AND lower(le.address)='${db_destination}' ".($tpid>0?" AND a.transport_provider_id=${tpid}":""); $q.= " AND a.cost>0"; $q.= " ORDER BY a.created DESC LIMIT ${limit} OFFSET ${offset}"; $r = pg_query($db, $q); if ($r && pg_num_rows($r)) { while ($f=pg_fetch_assoc($r)) { $f["location_start"] = html_entity_decode ($f["location_start"],ENT_QUOTES|ENT_HTML5,"UTF-8"); $f["location_end"] = html_entity_decode ($f["location_end"],ENT_QUOTES|ENT_HTML5,"UTF-8"); $results[] = $f; } } } return array($total, $results); } public static function getLastQuoteByOriginDestinationId($db, $origin, $destination, $tpid, $cacheTimeout = 300) { $db_origin = pg_escape_string(strtolower($origin)); $db_destination = pg_escape_string(strtolower($destination)); $q = Quotes::BASE_SQL_DATA . Quotes::BASE_SQL_FROM; $q.= " AND a.completed > now() - ( ${cacheTimeout} ||' seconds')::interval "; $q.= " AND lower(ls.address)='${db_origin}' "; $q.= " AND lower(le.address)='${db_destination}' ".($tpid>0?" AND a.transport_provider_id=${tpid}":""); $q.= " AND a.cost>0"; $q.= " ORDER BY a.created DESC LIMIT 1 OFFSET 0"; $result = NULL; $r = pg_query($db, $q); if ( $r && pg_num_rows( $r ) && $f = pg_fetch_assoc( $r ) ) { $result = $f; } return $result; } public static function getLastQuoteByOriginDestinationCoordinates($db, $origin, $destination, $tpId, $cacheTimeout = 300) { if (!is_array($origin) || !is_array($destination) || !isset($origin['lat'])|| !isset($origin['lng']) || !isset($destination['lat'])|| !isset($destination['lng']) ) { return NULL; } $origin_lat = $origin['lat']; $origin_lng = $origin['lng']; $destination_lat = $destination['lat']; $destination_lng = $destination['lng']; $q = Quotes::BASE_SQL_DATA . Quotes::BASE_SQL_FROM; $q.= " AND a.completed > now() - ( ${cacheTimeout} ||' seconds')::interval "; $q.= " AND ls.geometry = ST_SetSRID(ST_MakePoint( ${origin_lng}, ${origin_lat}), 4326)::geography "; $q.= " AND le.geometry = ST_SetSRID(ST_MakePoint( ${destination_lng}, ${destination_lat}), 4326)::geography"; $q.= ($tpId>0?" AND a.transport_provider_id=${tpId}":""); $q.= " AND a.cost>0"; $q.= " ORDER BY a.created DESC LIMIT 1 OFFSET 0"; $result = NULL; $r = pg_query($db, $q); if ( $r && pg_num_rows( $r ) && $f = pg_fetch_assoc( $r ) ) { $result = $f; } return $result; } public static function getByQuoteGroupId($db, $id) { $q = Quotes::BASE_SQL_DATA . Quotes::BASE_SQL_FROM . " AND quote_group_id>0 AND quote_group_id=".((int)$id); $r = pg_query($db, $q); if ($r && pg_num_rows($r)) { $results = []; while ($f=pg_fetch_assoc($r)) { $f["location_start"] = html_entity_decode ($f["location_start"],ENT_QUOTES|ENT_HTML5,"UTF-8"); $f["location_end"] = html_entity_decode ($f["location_end"],ENT_QUOTES|ENT_HTML5,"UTF-8"); $results[] = $f; } return array($results, NULL); } return array(NULL,pg_last_error($db)); } public static function create($db, $data) { syslog(LOG_WARNING,'Quote::create($db, $data)'); $location_start_id = Address::getAddress($db, $data, "location_start"); $location_end_id = Address::getAddress($db, $data, "location_end"); if ($location_start_id==NULL || $location_end_id==NULL) { return array(NULL,"Failed to save address"); } $q = "INSERT INTO quotes (transport_provider_id,automation_id,member_id,location_start_id,location_end_id, quote_group_id, prefill, pool) "; $q.= " VALUES(".((int)$data["transport_provider_id"]).",".((int)$data["automation_id"]).",".((int)$data["member_id"]).","; $q.= "${location_start_id},${location_end_id},".((int)$data["quote_group_id"]).",".($data["prefill"]!='t'?"'f'":"'t'"); $q.= ",".($data["pool"]!=2?"1":"2"); $q.= ") RETURNING id"; $log = [ 'message' => 'insert quote', 'data' =>$data, 'query' =>$q ]; Logger::debug($log); syslog(LOG_WARNING,'***************************************************************************'); syslog(LOG_WARNING,$q); syslog(LOG_WARNING,'***************************************************************************'); $r = pg_query($db, $q); if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) { return [Quotes::getById($db, $f["id"]),NULL]; } syslog(LOG_WARNING,pg_last_error($db)); return [NULL,pg_last_error($db)]; } public static function update($db, $data) { syslog(LOG_WARNING,'Quotes::update(): '.json_encode($data)); // cost_raw='".$data["cost_raw"]."', // created='".$data["created"]."', // member_id='".$data["member_id"]."' $q = "UPDATE quotes SET transport_provider_id=".((int)$data["transport_provider_id"]).", automation_id=".((int)$data["automation_id"]).", cost=".((float)$data["cost"]).", completed='".$data["completed"]."', travel_date='".$data["travel_date"]."', location_start_id=".$data["location_start_id"].", location_end_id=".$data["location_end_id"]." WHERE id='".$data["id"]."'"; //error_log($q); syslog(LOG_WARNING,$q); $r = pg_query($db, $q); /* $log = [ 'affected_row' => pg_affected_rows($r), 'message' => 'update quote', 'data' =>$data, 'query' =>$q ]; Logger::debug($log); */ if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) { return array(self::getById($db, $data["id"]),NULL); } return array(NULL, pg_last_error($db)); } public static function getLegStepQuoteBySID($db, $sid) { $q = "SELECT * FROM leg_step_quote WHERE google_directions_leg_step_id=".((int)$sid); $r = pg_query($db, $q); if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) { return [$f, NULL]; } return [NULL, pg_last_error($db)]; } public static function deeplink($db, $quote) { syslog(LOG_WARNING,"Quote::deeplink(\$db, \$quote)"); Logger::debug("Quote::deeplink(\$db, \$quote)"); $url = ""; switch ($quote["transport_provider_id"]) { case Quotes::VENDOR_UBER: // Uber // https://developer.uber.com/docs/riders/ride-requests/tutorials/deep-links/introduction $url = sprintf("uber://?client_id=IrcAu0gxX7EsPKWg3QJe8reR5Q8w1jDm&action=setPickup&pickup[latitude]=%f&pickup[longitude]=%f&dropoff[latitude]=%f&dropoff[longitude]=%f", $quote["location_start_lat"], $quote["location_start_lng"], $quote["location_end_lat"], $quote["location_end_lng"] ); break; case Quotes::VENDOR_LYFT: // Lyft // https://developer.lyft.com/docs/deeplinking // &partner=GZbtPgh56RQb // &credits= $url = sprintf("lyft://ridetype?id=lyft&pickup[latitude]=%f&pickup[longitude]=%f&destination[latitude]=%f&destination[longitude]=%f", $quote["location_start_lat"], $quote["location_start_lng"], $quote["location_end_lat"], $quote["location_end_lng"] ); break; case Quotes::VENDOR_GRAB: // Grab // TODO: rotate the sources! $url = sprintf("grab://open?screenType=BOOKING&sourceId=raZbevC7RB&sourceAppName=SingaporeAir&dropOffLatitude=%f&dropOffLongitude=%f&pickUpLatitude=%f&pickUpLongitude=%f", $quote["location_end_lat"], $quote["location_end_lng"], $quote["location_start_lat"], $quote["location_start_lng"] ); break; case Quotes::VENDOR_COMFORTDELGRO: // ComfortDelGro $url = sprintf("ComfortDelGroTaxi:///?action=setBooking&endingLat=%f&endingLong=%f&startingLat=%f&startingLong=%f", $quote["location_end_lat"], $quote["location_end_lng"], $quote["location_start_lat"], $quote["location_start_lng"] ); break; case Quotes::VENDOR_GOJEK: // Gojek $url = sprintf("gojek://sggocar/gocar?product_id=car&pickup_latitude=%f&pickup_longitude=%f&dropoff_latitude=%f&dropoff_longitude=%f", $quote["location_start_lat"], $quote["location_start_lng"], $quote["location_end_lat"], $quote["location_end_lng"] ); break; } //syslog(LOG_WARNING,"url=${url}"); return $url; } public static function checkQuote($id) { global $savvyext; $httpAuthToken = $savvyext->cfgReadChar('system.automation_api_token'); $automation_api_url = $savvyext->cfgReadChar('system.automation_api_url'); $url = $automation_api_url."automation-job/" . $id; $opts = array( 'http' => array( 'method' => "GET", 'header' => "Content-Type: application/json\r\n" . "Accept: application/json\r\n" . "Authorization: Server-Token ${httpAuthToken}\r\n" ), "ssl" => array( "verify_peer"=>false, "verify_peer_name"=>false, ) ); $context = stream_context_create($opts); $body = file_get_contents($url, false, $context); $quote = json_decode($body,true); if (is_array($quote) && isset($quote["id"])) { return array($quote, NULL); } else if (is_array($quote) && isset($quote["message"])) { $body = $quote["message"]; error_log(isset($quote["error"]) ? json_encode($quote["error"]) : $quote["message"]); } return array(NULL, $body); } public static function getQuoteDetails($id) { global $savvyext; $httpAuthToken = $savvyext->cfgReadChar('system.automation_api_token'); $automation_api_url = $savvyext->cfgReadChar('system.automation_api_url'); $url = $automation_api_url."automation-job-detail/" . $id; $opts = array( 'http' => array( 'method' => "GET", 'header' => "Content-Type: application/json\r\n" . "Accept: application/json\r\n" . "Authorization: Server-Token ${httpAuthToken}\r\n" ), "ssl" => array( "verify_peer"=>false, "verify_peer_name"=>false, ) ); $context = stream_context_create($opts); $body = file_get_contents($url, false, $context); $details = json_decode($body,true); if (is_array($details) && count($details)>0 && isset($details[0]["id"])) { return array($details, NULL); } else if (is_array($details) && isset($details["message"])) { $body = $details["message"]; error_log(isset($details["error"]) ? json_encode($details["error"]) : $details["message"]); } return array(NULL, $body); } } // vi:ts=2