first commit
This commit is contained in:
@@ -0,0 +1,328 @@
|
||||
<?php if (!defined('BASEPATH')) {
|
||||
exit('No direct script access allowed');
|
||||
}
|
||||
|
||||
class Geofence_area_model extends CI_Model
|
||||
{
|
||||
const GEOFENCING_AREA_TYPES = [
|
||||
'postal',
|
||||
'radius',
|
||||
'polygon'
|
||||
];
|
||||
|
||||
private $read_replica;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->read_replica = $this->load->database('savvy_replica', TRUE);
|
||||
}
|
||||
|
||||
public function getAllWithPagination($page = 1, $perPage = 10, $filterData = [])
|
||||
{
|
||||
$offset = ($page - 1) * $perPage;
|
||||
if ($offset < 0) {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$whereQuery = '';
|
||||
if (!empty($filterData)) {
|
||||
if (!empty($filterData['city_id'])) {
|
||||
$whereQuery .= ' WHERE geo_city.id = ' . $this->read_replica->escape($filterData['city_id']) . ' ';
|
||||
}
|
||||
}
|
||||
|
||||
$totalQueryString =
|
||||
'SELECT
|
||||
geo.id, geo.name, geo.area, geo_city.city as city_name, geo_city.id as city_id, geo.type,
|
||||
geo.country as country_code, geo.latitude, geo.longitude, geo.boundaries,
|
||||
country.country as country_name
|
||||
FROM
|
||||
geofence_area as geo
|
||||
JOIN country ON country.code = geo.country
|
||||
JOIN geofence_area_city as geo_city ON geo_city.id = geo.city_id
|
||||
' . $whereQuery;
|
||||
|
||||
$queryString =
|
||||
'SELECT
|
||||
geo.id, geo.name, geo.area, geo_city.city as city_name, geo_city.id as city_id, geo.type,
|
||||
geo.country as country_code, geo.latitude, geo.longitude, geo.boundaries,
|
||||
country.country as country_name
|
||||
FROM
|
||||
geofence_area as geo
|
||||
JOIN country ON country.code = geo.country
|
||||
JOIN geofence_area_city as geo_city ON geo_city.id = geo.city_id
|
||||
' . $whereQuery . '
|
||||
ORDER BY id DESC
|
||||
LIMIT ' . pg_escape_string($perPage) . ' OFFSET ' . pg_escape_string($offset);
|
||||
|
||||
$totalQuery = $this->read_replica->query($totalQueryString);
|
||||
$query = $this->read_replica->query($queryString);
|
||||
|
||||
return [
|
||||
'total' => count($totalQuery->result()),
|
||||
'data' => $query->result(),
|
||||
'page' => $page
|
||||
];
|
||||
}
|
||||
|
||||
public function getAllAreas()
|
||||
{
|
||||
$query = "SELECT
|
||||
geofence_area.id, geofence_area.name, geofence_area_city.city, geofence_area.latitude, geofence_area.longitude,
|
||||
geofence_area.location, geofence_area.type, geofence_area.boundaries
|
||||
FROM
|
||||
geofence_area
|
||||
JOIN geofence_area_city ON geofence_area_city.id = geofence_area.city_id
|
||||
";
|
||||
|
||||
$query = $this->read_replica->query($query);
|
||||
|
||||
return $query->result();
|
||||
}
|
||||
|
||||
public function getItem($id)
|
||||
{
|
||||
$queryString =
|
||||
'SELECT
|
||||
geo.id, geo.name, geo.area, geo_city.city as city_name, geo_city.id as city_id, geo.type,
|
||||
geo.country as country_code, geo.latitude, geo.longitude, geo.boundaries,
|
||||
country.country as country_name
|
||||
FROM
|
||||
geofence_area as geo
|
||||
JOIN country ON country.code = geo.country
|
||||
JOIN geofence_area_city as geo_city ON geo_city.id = geo.city_id
|
||||
WHERE
|
||||
geo.id = ?
|
||||
LIMIT 1
|
||||
';
|
||||
|
||||
$query = $this->read_replica->query($queryString, $id);
|
||||
return $query->row_array();
|
||||
}
|
||||
|
||||
public function create($inputData)
|
||||
{
|
||||
$test = $this->db->insert('geofence_area', $inputData);
|
||||
$insertId= $this->db->insert_id();
|
||||
|
||||
// update location field
|
||||
$this->db->query("UPDATE geofence_area SET location = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326) WHERE id = {$insertId} ");
|
||||
}
|
||||
|
||||
public function update($id, $inputData)
|
||||
{
|
||||
$this->db->where('id', $id);
|
||||
$this->db->update('geofence_area', $inputData);
|
||||
|
||||
// update location field
|
||||
$this->db->query("UPDATE geofence_area SET location = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326) WHERE id = {$id} ");
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$this->db->delete('geofence_area', ['id' => $id]);
|
||||
}
|
||||
|
||||
public function priceComparison($startAreaId, $endAreaId)
|
||||
{
|
||||
// validate id
|
||||
if (!is_numeric($startAreaId) || !is_numeric($endAreaId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1) Define geofenced areas, get list of areas
|
||||
$startArea = $this->getArea($startAreaId);
|
||||
$endArea = $this->getArea($endAreaId);
|
||||
|
||||
if (!$startArea || !$endArea) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Can not find area.'
|
||||
];
|
||||
}
|
||||
|
||||
// 2. Select trips where "from" falls into origin area and "to" falls into destination area
|
||||
$whereQuery = '';
|
||||
$startBoundaries = json_decode($startArea['boundaries'], true);
|
||||
$endBoundaries = json_decode($endArea['boundaries'], true);
|
||||
if ($startArea['type'] === 'radius') {
|
||||
if (isset($startBoundaries['radius'])) {
|
||||
$radius = $startBoundaries['radius'];
|
||||
$condition = " ST_DWithin('" . $startArea['location'] . "', startAddr.geometry, " . $radius . ") ";
|
||||
$whereQuery = $this->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing radius in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($startArea['type'] === 'postal') {
|
||||
if (is_array($startBoundaries) && array_key_exists("postal_code",$startBoundaries) && is_array($startBoundaries["postal_code"]) && count($startBoundaries["postal_code"]) > 0) {
|
||||
$condition = "";
|
||||
foreach ($startBoundaries['postal_code'] as $code) {
|
||||
if ($condition != "") {
|
||||
$condition .= " OR ";
|
||||
}
|
||||
$condition .= " LEFT(startAddr.postal, " . strlen($code) . ") = '${code}' ";
|
||||
}
|
||||
|
||||
$condition = "(${condition})";
|
||||
$whereQuery = $this->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing postal_code in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($startArea['type'] === 'polygon') {
|
||||
if (isset($startBoundaries['polygon'])) {
|
||||
$polygon = $startBoundaries['polygon'];
|
||||
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
$condition = " ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), startAddr.geometry::geometry) ";
|
||||
$whereQuery = $this->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing polygon in boundaries field.'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($endArea['type'] === 'radius') {
|
||||
if (isset($endBoundaries['radius'])) {
|
||||
$radius = $endBoundaries['radius'];
|
||||
$condition = " ST_DWithin('" . $endArea['location'] . "', endAddr.geometry, " . $radius . ") ";
|
||||
$whereQuery = $this->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing radius in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($endArea['type'] === 'postal') {
|
||||
if (is_array($endBoundaries) && array_key_exists("postal_code",$endBoundaries) && is_array($endBoundaries["postal_code"]) && count($endBoundaries["postal_code"]) > 0) {
|
||||
$condition = "";
|
||||
foreach ($endBoundaries['postal_code'] as $code) {
|
||||
if ($condition != "") {
|
||||
$condition .= " OR ";
|
||||
}
|
||||
$condition .= " LEFT(endAddr.postal, " . strlen($code) . ") = '${code}' ";
|
||||
}
|
||||
|
||||
$condition = "(${condition})";
|
||||
$whereQuery = $this->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing postal_code in boundaries field.'
|
||||
];
|
||||
}
|
||||
} else if ($endArea['type'] === 'polygon') {
|
||||
if (isset($endBoundaries['polygon'])) {
|
||||
$polygon = $endBoundaries['polygon'];
|
||||
|
||||
$polygonCoords = [];
|
||||
foreach ($polygon as $coord) {
|
||||
$polygonCoords[] = "$coord[0] $coord[1]";
|
||||
}
|
||||
$polygonCoordsString = implode(",", $polygonCoords);
|
||||
|
||||
$condition = " ST_Contains(ST_GeomFromText('POLYGON((${polygonCoordsString}))', 4326), endAddr.geometry::geometry) ";
|
||||
$whereQuery = $this->checkCondition($condition, $whereQuery);
|
||||
} else {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Missing polygon in boundaries field.'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Filter pricing by transport_provider_id and calculate average within last year
|
||||
|
||||
// only get trips within last year
|
||||
$numberOfDays = 365;
|
||||
$condition = " parsedemail_item.travel_date BETWEEN NOW() - INTERVAL '" . $numberOfDays . " days' AND NOW() ";
|
||||
$whereQuery = $this->checkCondition($condition, $whereQuery);
|
||||
|
||||
$tripQuery =
|
||||
"SELECT
|
||||
ROUND(AVG(parsedemail_item.cost), 2) as avg_price, parsedemail_item.transport_provider_id,
|
||||
transport_providers.name as transport_provider_name
|
||||
FROM
|
||||
parsedemail_item
|
||||
JOIN transport_providers ON transport_providers.id = parsedemail_item.transport_provider_id
|
||||
JOIN address AS startAddr ON (startAddr.id = parsedemail_item.location_start_id AND transport_provider_id IS NOT NULL
|
||||
AND LOWER(startAddr.country) = '" . strtolower($startArea['country_code']) . "')
|
||||
JOIN address AS endAddr ON (endAddr.id = parsedemail_item.location_end_id
|
||||
AND LOWER(endAddr.country) = '" . strtolower($endArea['country_code']) . "')
|
||||
" . $whereQuery . "
|
||||
GROUP BY parsedemail_item.transport_provider_id, transport_providers.name
|
||||
";
|
||||
|
||||
$query = $this->read_replica->query($tripQuery);
|
||||
|
||||
$result = [
|
||||
'success' => true,
|
||||
'from_area' => $startArea,
|
||||
'to_area' => $endArea,
|
||||
'price_comparison' => $query->result_array() ?: []
|
||||
];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function checkCondition($condition, $query)
|
||||
{
|
||||
if (strpos($query, 'WHERE') === false) {
|
||||
$query .= " WHERE $condition";
|
||||
} else {
|
||||
$query .= " AND $condition";
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function getArea($id)
|
||||
{
|
||||
$query = "SELECT
|
||||
geofence_area.id, geofence_area.name, geofence_area.country as country_code, geofence_area.latitude, geofence_area.longitude,
|
||||
geofence_area.location, geofence_area.type, geofence_area.boundaries
|
||||
FROM
|
||||
geofence_area
|
||||
WHERE
|
||||
geofence_area.id = $id
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
$query = $this->read_replica->query($query);
|
||||
$data = $query->result_array();
|
||||
|
||||
return !empty($data) ? $data[0] : null;
|
||||
}
|
||||
|
||||
public function getLocationByID($id) {
|
||||
$this->read_replica->select('*');
|
||||
$this->read_replica->from('geofence_area');
|
||||
$this->read_replica->where('id', $id);
|
||||
|
||||
$query = $this->read_replica->get();
|
||||
|
||||
return $query->result_array();
|
||||
}
|
||||
|
||||
public function getLocationByCityID($city_id) {
|
||||
$this->read_replica->select('ga.id AS id, ga.name AS geo_area_name');
|
||||
$this->read_replica->from('geofence_area ga');
|
||||
$this->read_replica->join('geofence_area_city gac', 'gac.id = ga.city_id');
|
||||
$this->read_replica->where('gac.id', $city_id);
|
||||
$this->read_replica->order_by('geo_area_name');
|
||||
|
||||
return $this->read_replica->get()->result_array();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user